Part 1/2 - Deploying Symfony 4 with rsync
We've covered setting up a basic LAMP and LEMP stack for Symfony 4, and seen how this involves working with environment variables. We've also covered the demo project we will be using for all of our Symfony 4 deployment examples. Now it's time to deploy Symfony 4.
To begin with, we will use
rsync deployment is as basic as can be, and likely wouldn't be suitable for a real world project. Consider this your starting point, and in the next two videos we will explore ways to make this process more robust, and ultimately, more real world.
In order to deploy our project, we are going to start by creating our first "build".
In reality, this Symfony project build is nothing more than running a
composer install without the development dependencies. As we are going into production at this point, we should have no need for anything only required in development. This might be the local web server, or our test suite, or in the case of a fresh Symfony 4 installation, the
Our First Symfony 4 Build
Our first build is simple:
composer install --no-dev --optimize-autoloader # if you encounter any issues, try: export APP_ENV=prod composer install --no-dev --optimize-autoloader
The theory goes that we shouldn't need access to any development dependencies from our production environment (
--no-dev), and so anything in the
composer.json file under
require-dev won't be downloaded.
optimize-autoloader [in this video.]
Ok, so is everything good and ready to go?
Well, let's try our deploy and find out.
rsync --exclude '.git' --exclude=.env --exclude=var -avzh \ . \ firstname.lastname@example.org:/var/www/crvfakeexample.com
Note: As has been covered during the LAMP and LEMP tutorials, I am uploading as
root user. In reality you would not do this. Please adapt accordingly.
This shouldn't take too long, depending on your upload speed. Symfony 4 is slimmer than Symfony 3.
Notice that we have excluded the
var directories as before.
We have already configured the
var directory with the correct permissions.
New is the exclusion of the local
.env file, by adding
--exclude=.env to the command.
At present the Symfony deployment guide is really vague about the
Here's some extra info I found whilst reading the docs for the [DotEnv component]:
You should never store a .env file in your code repository as it might contain sensitive information; create a .env.dist file with sensible defaults instead.
Symfony Dotenv should only be used in development/testing/staging environments. For production environments, use "real" environment variables.
This is why we spent the time adding in environment variables to our Apache / nginx configurations before hand.
Are We There Yet?
Amazingly, we aren't far off at this point.
There's three further steps we need to take:
- Sort out permissions
- Kick start the database
- Clear and warmup the Symfony cache
Sorting out the permissions issues should be a one liner:
# from your server sudo chown -R www-data:www-data /var/www/crvfakeexample.com
This recursively changes the owning user and group of each file and folder to the user
www-data, and the group
Whether using Apache or nginx, on Ubuntu our web server user will be
www-data, so this should give the required permissions for access.
Next, sorting out the database is specific to this project.
We need to run three commands:
# from your server cd /var/www/crvfakeexample.com php bin/console doctrine:database:create php bin/console doctrine:schema:create php bin/console doctrine:fixtures:load
And like in Symfony 2 or Symfony 3, clearing and warming the cache is required:
php bin/console cache:clear --no-warmup php bin/console cache:warmup
And that's it.
This should feel very similar to a Symfony 2 or Symfony 3 project deploy. The primary difference is in the use of environment variables. Also, there are a few ways this approach is less likely to give you errors or problems - particularly around the
php bin/console doctrine:... commands.
Overall though, not hugely different to what you may already know and use.
Why This Approach Is Too Basic
The problem in this approach is in our
We're copying all the files and folders from our local computer, right over the top of any existing files and folders on the server.
This becomes a problem beyond the very first time we run this command.
Any subsequent runs are going to affect the files and folders being actively used by Apache or nginx to serve real visitors.
This means if a file is being accessed by someone whilst we are also updating that file, they may encounter very odd errors. Refreshing their page may hopefully fix it. But worse, any new files and folders are going to have the wrong permissions. This is less obvious, especially on subsequent deploys.
If you'd like to read more on this then I've covered this already in this video write up under the section "Is rsync Risky?".
In this instance, I'm going to consider our deployment done. But in the next two videos we will improve on this process to remove this problem.