Deploying a Symfony 4 application with Ansible

Jon Torrado
3 min readFeb 14, 2018

Hey! Did you tried to deploy your Symfony 4 app with Ansible and it didn’t work? I’ve already wrote about how to do this for Symfony 2 and 3. So, in this story, I’m going to tell you just the things you need to change. Please, read my previous Ansible story and then come back and continue reading.

Symfony 4 changes

Ok, this is not a “changelog”. I just want to to tell you the main change that is crashing your deployments: no more parameters.yml. Well, you can create the file and it will work, but you should use environment variables for, at least, infrastructure settings such as database credentials.

So, how is this working? When your environment is dev, the dotenv component should be working (require-dev). This will load a .env file with your variables and the process should be almost like in Symfony 2 and 3. But, dotenv won’t be loaded in prod. This means: your webserver won’t know how to connect to your database, nor the console will know the environment, and so on. How should you fix that?

Solution 1: move dotenv from require-dev to require. This is not an antipattern, feel free to do it!

Solution 2.1: for an Apache webserver, you must load the variables in your VirtualHost configuration:

<VirtualHost *:80>
#...
#SetEnv APP_ENV prod
#SetEnv APP_SECRET <app-secret-id>
#SetEnv DATABASE_URL "mysql://username:p4ssw0rd@host:3306/database"

</VirtualHost>

For the console, you have two different approaches:

  • 2.2a — Prepend the needed environment variables, such as APP_ENV=prod bin/console command:execute.
  • 2.2b — Load the environment variables from a file.

The 2.2b solution works like a .bashrc file, exporting the needed variables. We are going to use this solution to fix our Ansible deployment.

Ansible configuration changes

Remember to read this story first. Have you read it? Ok, let’s continue.

First of all, the deploy.yml file changes:

  • var/logs is now var/log
  • No need for ansistrano_shared_files (we won’t have a parameters file)
  • The symfony_run_doctrine_migrations should be false because it’s not using environment variables and it fails (at this moment!)
  • At the end of the file, add the environment section:
environment:
APP_ENV:
"{{ sf_env }}"
BASE_URL: "{{ sf_base_url }}"
HOST: "{{ sf_host }}"
SCHEME: "{{ sf_scheme }}"

As you see, I won’t write here the database credentials, because they will be committed, and we don’t want our credentials on git, do we?

Let’s add those needed variables. For example, edit the group_vars/prod file:

#...
sf_env: prod
sf_base_url: /
sf_host: project.com
sf_scheme: http

Then, check all your defined tasks and remove the SYMFONY_ environment variables because they are not working anymore.

Last step: database migrations. All this works like a charm, but we won’t have our database credentials for the console commands, and we definitely don’t want our credentials in the group vars files. So, go to your shared folder in your destination server and create a .env file there. Write there the exporting lines, and remember to prepend them with the export keyword. For example:

export DATABASE_URL=mysql://username:p4ssw0rd@127.0.0.1:3306/database

We just have to source that file and the execute the needed commands. This is my before-symlink-tasks-file.yml file (remember to include it in your deploy.yml file!):

---
- name: Run doctrine migrations
shell: chdir={{ansistrano_release_path.stdout}}
source {{ansistrano_shared_path}}/.env && {{symfony_php_path}} {{symfony_console_path}} doctrine:migrations:migrate --no-interaction

That’s all, enjoy your Symfony 4 project!

--

--

Jon Torrado

IT Manager at Demium. Former CTO of different companies and startups. Father of one. Health learning lover.