Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Virtual Host Setup

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $9.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

There is one more immediate problem: the document root of the project is /var/www/project/current/web. But... you might remember that our Nginx virtual host points to /var/www/project/web. This needs to change to /var/www/project/current/web.

That's easy to do: we could just edit this file right now! But since we provisioned our server with Ansible, let's make this change to our provision playbook... so that we feel super cool and responsible.

Sharing Provision Variables

First, in deploy.yml, add a new vars_files key. Load a file called vars/vars.yml:

---
- hosts: aws
vars_files:
- ./vars/vars.yml
... lines 6 - 18

This very small file holds two variables that point to where the project lives:

---
project_deploy_dir: /var/www/project
server_document_root: /var/www/project/web

These are used by the provision playbook: playbook.yml. The first tells it where to create the directory. And the second - server_document_root - is used to set the document root in the Nginx virtual host!

Before we change that variable, go back to deploy.yml. Now that we're including vars.yml here, we can use the project_deploy_dir variable:

---
- hosts: aws
... lines 3 - 6
vars:
... line 8
ansistrano_deploy_to: "{{ project_deploy_dir }}" # Base path to deploy to.
... lines 10 - 18

This doesn't change anything: it just kills some duplication.

Updating the Document Root

Back in vars.yml, we need to change server_document_root. But hold on! Let's get fancy! Ansistrano has a variable called ansistrano_current_dir. This is the name of the symlinked directory and - as we know - it defaults to current. Put this inside vars.yml and set it to current:

---
project_deploy_dir: /var/www/project
ansistrano_current_dir: current # Softlink name. You should rarely changed it.
... lines 4 - 6

This won't change how Ansistrano works. But now, we can safely use that variable here. Set server_document_root to "{{ project_deploy_dir }}/{{ ansistrano_current_dir }}/web":

---
project_deploy_dir: /var/www/project
ansistrano_current_dir: current # Softlink name. You should rarely changed it.
server_document_root: "{{ project_deploy_dir }}/{{ ansistrano_current_dir }}/web"
... lines 5 - 6

I love it! After all these changes, well, we didn't actually change our deploy playbook at all. But we did change the provision playbook.

Find your local terminal and re-provision the server:

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

This will take a few minutes to finish... but all it's really doing is changing the virtual host to point to /var/www/project/current/web. If you're not using Ansible to provision, change this however you want!

Done! Move back to your server and open the Nginx config!

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

Got it! The root is set to the correct spot:

# /etc/nginx/sites-available/mootube.example.com.conf
server {
    // ...
    root /var/www/project/current/web;
    // ...
}

Try out the Site

The ultimate goal is to get our site working at mootube.example.com. In the real world, you would configure a DNS record and point it to the server. With AWS, you can do that with their Route 53 service.

But since this is a fake domain, we need to cheat. Open up /etc/hosts:

sudo vim /etc/hosts

Near the bottom, put the IP address to our server - I'll copy it from hosts.ini - and point this to mootube.example.com:

# /etc/hosts
# ...
54.162.54.206 mootube.example.com

At this point, our code is on the server and the Nginx virtual host is pointing to it. We have the absolute basics finished! Find your browser, and try the site! http://mootube.example.com.

It works! I'm just kidding - it's totally a 500 error: we're still missing a few steps.

To see what the exact error is, go to the server and check the logs. In the virtual host, you can see that the error_log config is set to /var/log/nginx/mootube.example.com_error.log:

# /etc/nginx/sites-available/mootube.example.com.conf
server {
    # ...
    error_log /var/log/nginx/mootube.example.com_error.log;
    access_log /var/log/nginx/mootube.example.com_access.log;
}

Tail that file: sudo tail and then the path:

sudo tail /var/log/nginx/mootube.example.com_error.log

Ah! Look closely:

Failed opening required vendor/autoload.php

Of course! We have not run composer install yet. In fact, we also haven't configured our database credentials or any file permissions. All we've done is put our code on the server. But... that is pretty awesome: we already have a system that deploys in a very cool way: creating a new releases/ directory and symlinking that to current/. Our deploy is missing some steps, but it's already pretty awesome.

But before we finish it, let's talk about deploy keys so that we can deploy private repositories.

Leave a comment!

2
Login or Register to join the conversation
Default user avatar

Hi again. For this tutorial you provisioned your server with Nginx. There is a reason for not using Apache? Sorry if my question is silly but I don't know much about servers. I usually use a LAMP stack to deploy normal PHP code without Symfony. It's more a curiosity than a problem because I can install Nginx but I want to know why use that instead of Apache.

Reply

Hey Cesar,

Good question! Well, there's no any significant difference - both are good *real* we servers with good history and ready for production. But, Nginx gives better results under huge load than Apache, so most big websites use it instead, or use both Nginx and Apache in conjunction. But if you're good at Apache and have a small simple website - you probably won't see the difference at all, so feel free to choose what you know the best.

Cheers!

Reply
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
userVoice