Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Anatomy of an Ansistrano Deploy

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Go back to the Ansistrano GitHub page. Find the table of contents near the top, and click Deploying. Excellent! This tells us how to use this role and how it works! Ansistrano is based off of Capistrano... which means it creates a really cool directory structure on your server. In this example, we're deploying to a /var/www/my-app.com directory on the server. Each time we deploy, it creates a new, timestamped, directory inside releases/ with our code. Then, when the deploy finishes, it creates a symlink from a current/ directory to this release directory.

Next time you deploy? Yep, the same thing happens: it will create a new release directory and update the symbolic link to point to it instead. This means that our web server should use the current/ directory as its document root.

This is amazing. Why? With this setup, we can patiently do all the steps needed to prepare the new release directory. No traffic hits this directory until the very end of deployment, when the symbolic link is changed.

There's also a shared/ directory, which allows you to share some files between releases. We'll talk more about that later.

Set the Deploy Directory then Deploy!

To start with Ansistrano... well... the only thing we need to do is tell it where to deploy to on the server! How? The same way you control any role: by overriding variables that it exposes.

Scroll up a little on their docs to find a giant box of variables. Yes! This tells you every single possible variable that you can override to control how Ansistrano works. This is documentation gold!

The first variable we need ansistrano_deploy_to. Copy that. Inside deploy.yml, add a vars key and paste. Set this to the directory that's already waiting on our server: /var/www/project:

- hosts: aws
# Ansistrano vars
ansistrano_deploy_to: "/var/www/project" # Base path to deploy to.
... lines 7 - 10

Ok... well... we haven't done much... but let's see if it works! In your local terminal, run the same command as before, but without the --list-tasks flag:

ansible-playbook -i ansible/hosts.ini ansible/deploy.yml

Ok... it looks like it's working. A few of the tasks mention rsync. That's because, by default, Ansistrano uses rsync to get the files from your local machine up to your server. We'll change to a different strategy in a few minutes.

Ding! It finished! Let's go see what it did! Change to the terminal where you're SSH'ed onto your server. Inside /var/www/project, run ls.


Awesome! We have the Ansistrano directory structure: current/, releases/ and shared/. So far, we only have one directory in releases/ and current/ is a symlink to it.

Now, move into the current/ directory and look inside:

cd /var/www/project/current

Woh! There's almost nothing here: just a REVISION file that Ansistrano created and an ansible/ directory... which is a copy of our local ansible/ directory.

This looks weird... but it makes sense! Right now, Ansistrano is using rsync to deploy only the directory where the playbook lives... so, ansible/. This is not what we want. So next, let's change our deployment strategy to git so that Ansistrano pulls down our entire repository.

Leave a comment!

Login or Register to join the conversation
Cat in space

"Houston: no signs of life"
Start the conversation!

While the fundamentals of Ansistrano haven't changed, this tutorial is built using Symfony 3, which has significant differences versus Symfony 4 and later.

What PHP libraries does this tutorial use?

// composer.json
    "require": {
        "php": ">=5.5.9",
        "doctrine/doctrine-bundle": "^1.6", // 1.6.8
        "doctrine/orm": "^2.5", // v2.7.2
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "sensio/distribution-bundle": "^5.0.19", // v5.0.20
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.26
        "symfony/monolog-bundle": "^3.1.0", // v3.1.0
        "symfony/polyfill-apcu": "^1.0", // v1.4.0
        "symfony/swiftmailer-bundle": "^2.3.10", // v2.6.3
        "symfony/symfony": "3.3.*", // v3.3.5
        "twig/twig": "^1.0||^2.0", // v1.34.4
        "doctrine/doctrine-migrations-bundle": "^1.2", // v1.2.1
        "predis/predis": "^1.1", // v1.1.1
        "composer/package-versions-deprecated": "^1.11" // 1.11.99
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.1.6
        "symfony/phpunit-bridge": "^3.0", // v3.3.5
        "doctrine/data-fixtures": "^1.1", // 1.3.3
        "hautelook/alice-bundle": "^1.3" // v1.4.1

What Ansible libraries does this tutorial use?

# ansible/requirements.yml
    src: DavidWittman.redis
    version: 1.2.4
    src: ansistrano.deploy
    version: 2.7.0
    src: ansistrano.rollback
    version: 2.0.1