Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Setup: Server Provisioning

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.

Hey guys! Ok, here's my situation: I've built this amazing new app: MooTube: the latest fad in cow fitness. There's just one more problem to solve, before cattle start signing up in herds: the site only lives on my local computer! It's time to release it to the cow masses. Yep, it's time to deploy!

But... how? There are probably 50 good ways to deploy! Bah! And these days, you can even deploy with a Platform as a Service: something like Platform.sh or Heroku. These take care of almost everything for you. I love these, and we use Platform.sh for part of KnpUniversity. They do have some limitations, but they are the fastest way to get your app to production.

In this tutorial, we're going to talk about one, really nice deployment tool: Ansistrano. It's built on top of Ansible... so if you watched our Ansible tutorial, you're going to love it! And if you haven't, what are you waiting for!? Well actually, I'll give you all the details you need, regardless.

Download the Project

As always, learning, like grazing, is best done in a group: so you should definitely code along with me. Download the course code from this page and unzip it. Inside, you'll find a start/ directory, which will have the same code I have here. See that README file? It holds all the secrets for getting the project setup. But actually... this is a tutorial about deployment! So... you don't really need to get the project running locally... because we're going to get the project running... in the cloud!

But, if you do want to get the project running, the last step will be to find your terminal, sip some coffee, and run:

bin/console server:run

to start the built-in PHP web server. Open the app in your browser at http://localhost:8000. Ah yes, MooTube: our bovine fitness app that is about to stampede through the cow world! This is the same app we used in our Ansible tutorial, with just a few small changes.

Booting a new Server

Let's get to work! So first... well... we need a server! You can use any service to get a server, but I already booted a new EC2 instance from AWS. I actually did this via Ansible. In our Ansible tutorial, we created a small playbook - aws.yml - whose only job is to boot an EC2 instance using an Ubuntu 14.04 image.

You're free to get a server from anywhere... but if you do want to use this script to boot a new instance, you'll just need to do 2 things. First, edit the ansible vault at ansible/vars/aws_vault.yml.

ansible-vault edit ansible/vars/aws_vault.yml

The password is beefpass.

These access keys are mine... and as much fun as it would be for me to pay for your servers... these keys won't work anymore. Sorry! Replace them with your own. Second, in aws.yml, see that key_name?

31 lines ansible/aws.yml
- hosts: local
... lines 3 - 13
- name: Create an instance
... lines 17 - 21
key_name: KnpU-Tutorial
... lines 23 - 31

You'll need to create your own "Key Pair" in the EC2 management console, and put its name here. The key pair will give you the private key needed to SSH onto the new server.

Server Provisioning

Once you have a server... deploying is really two steps. Step 1: provisioning: the fancy word that basically means installing everything you need, like Nginx, PHP, PHP extensions and whatever else. And then step 2: actually deploying.

I don't care how you setup - or provision - your server. In the Ansible tutorial, we - of course! - used Ansible to do this, but that is not a requirement for using Ansistrano.

But since we already have a working provision playbook, let's use it! First, I'll find the public IP address to my new server. Open ansible/hosts.ini and put this under the aws group:

... lines 1 - 6
... lines 9 - 13

If you're still new to Ansible, we'll talk more about this file once we start to deploy.

Now, run Ansible:

ansible-playbook ansible/playbook.yml -i ansible/hosts.ini -l aws

Go Ansible go! See that -l aws at the end? Well, the provision playbook - playbook.yml - is setup to provision both my aws hosts and also a local VirtualBox machine. The -l tells Ansible to only provisioning the AWS server right now.

Ansible Authentication

Behind the scenes, Ansible is SSH'ing onto the server and running commands. But... how does authentication to the server work? In our case, it's with the private key from the "Key Pair" that we used to boot the server. Open ansible/group_vars/aws.yml:

ansible_user: ubuntu
ansible_ssh_private_key_file: ~/.ssh/KnpU-Tutorial.pem
ansible_python_interpreter: /usr/bin/python3
host_server_name: mootube.example.com

Because we're using the aws group, this file is automatically loaded. It sets two important variables: ansible_user and ansible_ssh_private_key_file.

When you use Ansistrano to deploy, you'll need to make sure these two variables are set... or ansible_ssh_pass if you're using a password. You don't need to set them in a fancy group variable file like this. If you're still new to Ansible, I'll show you how to create variables right in your deploy playbook later.

For now, just know that we are telling Ansible how to authenticate: there's no magic.

Checking out the Server

Since Ansible is still working, open a third tab. Let's SSH onto the server: ssh -i, the path to the private key, then ubuntu@ followed up the IP address:

ssh -i ~/.ssh/KnpU-Tutorial.pem ubuntu@54.XXX.XX.XXX

Perfect! Now... pour a fresh cup of coffee and learn a foreign language while we wait for provisioning to finish. Fast forward!!!!!

Ding! Our server is ready! Check this out! We have PHP 7.1, Nginx and even an Nginx Virtual host.

cd /etc/nginx/sites-available
sudo vim mootube.example.com.conf

Our site will be mootube.example.com, and this is setup with a document root at /var/www/project/web. Right now, there is a /var/www/project directory... but it's empty. Putting code there? Yea, that's the job of this tutorial.

Let's go!

Leave a comment!

Login or Register to join the conversation
Markus L. Avatar
Markus L. Avatar Markus L. | posted 4 years ago

To get the project running on my windows machine when it comes to running 'yarn' I first had to:
- install windows build tools globally in administrator mode
- install node-sass explicitly: yarn add node-sass


Hey Markus L.

Thanks for sharing it! Windows likes to make things harder than it should be :)


Patrick Avatar
Patrick Avatar Patrick | posted 4 years ago

Hey, I've been using a deployment system based off this great tutorial for some time now - it's saved me so many errors before they hit production it's unreal!
I'm now looking to update the underlying ansistrano code - as I would like this in particular. How would you recommend to do that? I see on the ansistrano readme is refers to updating via ansible galaxy, but I don't think that's an option in this case, as the role isn't installed as such in the first place.


Hey Patrick,

I suppose you use requirements.yml file as we do in our screencast: https://symfonycasts.com/sc... . So, you can tweak the version constraint and install the new version of Ansistrano Deploy role. Unfortunately, I don't see any CHANGELOG there, so it's difficult to say if you would have any BC breaks or no after upgrade, but I think you can check descriptions to releases to get a clue what was changed since the version you've installed: https://github.com/ansistra...

I hope this helps!


Patrick Avatar

Hi Victor,
Just to note that this method worked perfectly.
You need to change the name of the role to ansistrano.deploy as it mentions in the tutorial update (it's been changed on Galaxy) but it's working great at version 2.11 with ansible 2.9



Hey Patrick!

Thank you for confirming it works for you this way! Glad to hear it :)


Krzysztof I. Avatar
Krzysztof I. Avatar Krzysztof I. | posted 4 years ago

Hi, great tutorial. Is moving working project to ansistrano is complicated? I thought about it and the best way is to: init ansistrano folder structure, get need code from git, then do the rest (like in tutorial, move current files/logs/etc) and than change paths? like nginx vhost (/var/www/project/current/web instead of /var/www/project/web?) and in code if needed?


Hey Krzysiek,

Actually, it's not much complicate than moving an empty project to Ansistrano. You basically need to do the same Symfony framework stuff, like we do in this course, e.g. build assets, clear and warmup the cache, run migrations, etc. Well, sure, it depends on your project complexity, but I think if you watch this course - you will have the exact vision of how complex would be to start using Ansistrano on your project, though I think it's still not too much complex.

and yes, your thoughts sound good to me. Sure, you will have to tweak your Ngixn host to point to a new directory, though, I think you can even avoid this if you make "/var/www/project/web" as a symlink to /var/www/project/current/web. But sure, better is to tweak your Nginx host to avoid 2 symlinks. Anyway, I think we covered MOST cases in this tutorial, so I don't think you will have many unique to your project things when will move your existent project to Ansistrano.


Maki V. Avatar
Maki V. Avatar Maki V. | posted 5 years ago

Hey guys!

Just wanted to ask if you will be releasing a tutorial on deploying your symfony application onto your (multiple-server) infrastracture - since we are dealing with this in our company and it's quite a pain in the ass right now!

Thank you


Hey Milan,

Stay tuned, we'll answer your question a bit further in this course. Actually, thanks to the Ansible background, Ansistrano can handle multiple-server deployment as well. If you're wondering about it right now, take a look at: https://knpuniversity.com/s... . So we don't plan any releases on it because it's already released in this course ;)


1 Reply
Maki V. Avatar

Thank you so much! :)


You're welcome, Ansistrano really powerful due to Ansible :)


Default user avatar

Hi. I don't want to use Ansible for booting or provisioning my AWS EC2. Instead, I did that using the Console in AWS and I installed LAMP manually by ssh (https://docs.aws.amazon.com.... My server now is working but I wanted to know if I need to install more things. I was reading the playbook.yml file of this tutorial and I only could see that I need Composer. What other things do I need? I hope you can help me because it's my first Symphony deployment.


Hey Cesar,

Yes, you can totally provision your prod server by yourself, but it probably depends on what screencast you're on. So, for the start of this tutorial, you need to download the course code and go to the start/ directory, where you can find ansible/playbook.yml file. Look over it to find out what you need to install. You can also look at finish/ directory to see the difference of what you will need to have on your prod server to the end of tutorial, but going through the tutorial we'll guide you to install more tools if it's needed. For example, on this page: https://knpuniversity.com/s... - we need to install NodeJS and Yarn on your prod server. So here's a list of packages you need to install at the start of this course:
- nginx
- redis
- zip
- unzip
- git
- mysql-server
- php7.1-cli
- php7.1-curl
- php7.1-fpm
- php7.1-intl
- php7.1-mysql
- php7.1-xml
- composer

And also set up date.timezone in php.ini. So all of that I get from start/ansible/playbook.yml file of course code downloaded archive.


Default user avatar

Thanks Victor. I am in the first screencast of Ansistrano. So, I want to be sure that I am provisioning my server correctly. Can you tell me how can I check if my server has installed all the packages that you told me? I am using Amazon Linux in a EC2 instance. Sorry if my question is basic but this is my first time. I hope you can help me.


Hey Cesar,

Good question! I'd say run Ansible playbook... but you said you want to provision by yourself :) Seriously, running "ansible/playbook.yml" provision playbook you will see *what* was _changed_ (i.e. installed or updated) and _skipped_ (i.e. was already installed and up to date). So I'd recommend you to review your point of view.

Nevertheless, it's a bit tricky to check was it installed manually, because different packages have different approaches. For example, to check that Composer is installed and what version it has - run "composer --version" in console. To check PHP extensions - run "php -m | grep mysql" or any other extension you need instead of mysql. For Nginx - run "nginx -v", etc. I think you got the idea. Probably there's another, more proper, way to check some packages, but I don't know.


Default user avatar

Thanks for the tips Victor. They helped me to provision my server. I am thinking to buy your screencast of Ansible but I am not sure yet. I will see.


Hey Cesar,

You're welcome! Yes, sure, it depends on how much automation do you need. Btw, if you're interested in several tutorials I'd recommend you to look at our monthly subscription but it's up to you.

If you have other questions - just let us know.


Default user avatar

Hi Victor. At the end I have bought the Ansible tutorial for provisioning my server and it was a great purchase because it really saves me a lot of time. Now, I have provisioned my server and deployed my app using Ansible and Ansistrano. So, thank you for all your answers and suggestions!

Now, do you have any screencast where you explain how to configure an SSL in the Nginx server using Ansible? I want to put Let's Encrypt for having https. Please, let me know.


Hey Cesar,

I'm glad you like it! Ansible helps with my tasks a lot too ;)

What about configuring SSL - unfortunately, we do not have any screencasts about it yet, and probably do not have any plans on it in the nearest future. But, if you use AWS, you can take a look at AWS ELB, i.e. even if you use only one EC2 instance, you can configure ELB which will help you with SSL configuration - load balancer handle SSL for you. AFAIK, we do so for KnpU SSL certificate. But if you're not on AWS, then probably it's not an option for you.


Default user avatar
Default user avatar jian su | posted 5 years ago

came from Ansible course to here. My question is doesn't Ansible can do all of this features? why we need another tool like Ansistrano?


Yo jian su!

Great question :). And yea... Ansible *can* do all of these things. But, it's not really another tool: Ansistrano is just an Ansible *role*. So, instead of you creating all the tasks necessary to clone your repository, clear the cache, change the symlinks, etc, those tasks already live inside the Ansistrano role. You can see the tasks here: https://github.com/ansistra.... It's actually pretty simple - you could even "steal" tasks from this and use Ansible directly :).


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