Part 1/3 - Deploying with rsync
Our first deploy process is going to be extremely basic - and in the real world, risky.
This said, "basic" does not necessarily mean simple. If this process is new to you then as a heads up, things can go wrong and that's why we're practicing on a demo server.
We will make use rsync
.
Now, rsync
is great. It allows you to reliably copy files from your local machine up to your server with a bare minimum of fuss.
It's also built in and good to go on both Linux and OSX.
I'll get back to why I consider this particular approach to using rsync
to be risky in just a moment.
Building The Project
In order to get a production-ready version of our site, we must complete a 'build' process.
Whilst this step can (and will) get more involved later on in this series, for the moment our build process is simple:
SYMFONY_ENV=prod composer install --no-dev --optimize-autoloader
Most of this command should likely be familiar to you. In fact, it's the command taken right from the Symfony deployment documentation page.
For clarity, --no-dev
means we won't download anything inside the require-dev
section of our project's composer.json
file. We don't (or shouldn't!) need any of the dev stuff for our production build, so including it would just make our build size that much bigger.
The --optimize-autoloader
flag converts the autoload
rules from both your own project's composer.json
, and each of the composer.json
files from each vendor/{whatever}
directory into a big PHP array called vendor/composer/autoload_classmap.php
. An example of this is given in the video, or you can read more on the Composer docs.
The use of SYMFONY_ENV
environment variable (SYMFONY_ENV=prod
) ensures that any Symfony commands will be run using production
configuration. This is useful as we cannot pass in a flag such as --env=prod
, as composer
would try to interpret that flag and get confused. If we don't pass SYMFONY_ENV=prod
in this case, a bunch of development dependencies would be expected to be found (SensioGeneratorBundle
for example), which aren't there as we explicitly said --no-dev
to exclude them.
In this example we will still get some database errors. This is understandable as we do not have a local development environment, nor local database server to connect too. You can safely ignore these errors for the purposes of this example.
Is rsync
Risky?
Earlier I mentioned that I consider this use of rsync
to be risky.
For clarity I do not mean rsync
in general is risky, just this specific approach.
Why is it risky?
Well, let's examine the command:
# from your local PC
# substitute this out for your path to your Symfony project directory
cd /home/chris/Development/symfony-deploy-test-site
rsync --exclude '.git' --exclude=var -avzh . root@104.236.215.199:/var/www/crvfakeexample.com
# equal to:
rsync --exclude '.git' --exclude=var -avzh /home/chris/Development/symfony-deploy-test-site root@104.236.215.199:/var/www/crvfakeexample.com
# or over multiple lines
rsync --exclude '.git' --exclude=var -avzh \
/home/chris/Development/symfony-deploy-test-site \
root@104.236.215.199:/var/www/crvfakeexample.com
Breaking this down...
We run this from our local PC (or Mac, of course). This PC is where we have our Symfony code.
We need to run this command from inside our Symfony project's root directory. In my case this directory is:
/home/chris/Development/symfony-deploy-test-site
The period / dot (.
) in the command indicates to copy everything from the current directory.
The flags (-avzh
) are not super important, but here we go all the same:
a
- archive mode (a bunch of other flags combined)v
- verbose, because it's nice to see what's being copiedz
- compress, (-c
is used taken for checksum :))h
- human readable output figures, because I am not a robot
In short rsync
does a great job of quickly and reliably transferring the local folder contents up to the server.
You may be wondering why rsync
, and not scp
(secure copy).
rsync
has the benefit of only transferring up what's changed, which makes the process of synchronising data really easy.
scp
would copy everything from my local to the remote, every time.
With rsync
, the files are copied using a particular user (root
), on a particular IP (104.236.215.199
), and into a directory (:/var/www/crvfakeexample.com
- note the leading colon, very important).
Why this is risky is it is copying directly from your desktop / laptop to your live / production website directory.
We will implement an improvement on this process in the next video.
As it stands, this process is not safe, and shouldn't be considered a viable deployment strategy for a working, production website. It does introduce us to moving data from our development to a production environment, so is a valid starting point.
We will get on to more robust solutions later in this series, some of which mirror this process in a more automated fashion.
Once this process completes then your project files are up, on your server.
# back on the server
cd /var/www/crvfakeexample.com/
ls -la
total 136
drwxr-xr-x 9 1000 1000 4096 Oct 14 19:02 .
drwxr-xr-x 4 root root 4096 Oct 14 19:17 ..
-rw-r--r-- 1 1000 1000 265 Oct 6 00:10 .gitignore
-rw-rw-rw- 1 1000 1000 107 Oct 14 19:02 README.md
drwxr-xr-x 4 1000 1000 4096 Oct 14 19:02 app
drwxr-xr-x 2 1000 1000 4096 Oct 14 19:03 bin
-rw-rw-rw- 1 1000 1000 2277 Oct 14 19:02 composer.json
-rw-rw-rw- 1 1000 1000 85612 Oct 14 19:03 composer.lock
-rw-r--r-- 1 1000 1000 988 Oct 6 00:10 phpunit.xml.dist
drwxr-xr-x 3 1000 1000 4096 Oct 14 19:02 src
drwxr-xr-x 3 1000 1000 4096 Oct 14 19:02 tests
drwxr-xr-x 5 1000 1000 4096 Oct 14 19:03 var
drwxr-xr-x 16 1000 1000 4096 Oct 14 19:03 vendor
drwxr-xr-x 3 1000 1000 4096 Oct 14 19:03 web
Notice how all the files and folders are owned by user / group 1000
?
That won't work.
Our files and folders need to be owned by the user, and group of www-data
.
Let's fix that.
chown -R www-data:www-data /var/www/crvfakeexample.com
This command recursively changes the owning user and group to both be www-data
.
In order for our application to function properly, we must follow the commands described in the deploy process for the Symfony Demo app:
php bin/console doctrine:database:create
php bin/console doctrine:schema:create
php bin/console doctrine:fixtures:load
The last one will prompt you, so type y
to accept.
Note that it is at this point that you would do your own custom setup routine for a real site.
The Symfony docs list some examples.
Finally, let's clear, and then warm-up the Symfony cache for the production environment:
cd /var/www/crvfakeexample.com
php bin/console cache:clear --env=prod --no-debug --no-warmup
php bin/console cache:warmup --env=prod
Now browse to your site:
http://crvfakeexample.com/
And et voila, a working Symfony website.
As part of this process we have validated our PHP build is working, as is our web server and database.
Cleaning Up
Don't forget to destroy your Digital Ocean Droplet.
Simply powering off is not enough. If you leave your Droplet available, but powered off, you will still be billed as though the Droplet were online. Be careful, I have made this mistake myself!
Wrapping Up
This was the most basic deploy I could think to show.
We covered a lot of ground, but not in very much depth.
Both Apache and PHP have been installed and left in their default setups. In reality you would likely want to tweak these setups considerably for production. We will cover more on this later in this series.
The crazy thing, however, is that this is likely good enough if this is your very first attempt at getting a Symfony site online. This will quite happily serve 100's of users per day without flinching.
Sure, once your site starts to become a little more frequently visited you will need to change some settings, but don't fall into the trap of thinking you need some crazy mega deploy process.
I guess what I'm trying to say, in a very roundabout way is:
Don't over complicate it.