Tutorial

How To Set Up Nginx Server Blocks (Virtual Hosts) on Ubuntu 14.04 LTS

How To Set Up Nginx Server Blocks (Virtual Hosts) on Ubuntu 14.04 LTS
Not using Ubuntu 14.04?Choose a different version or distribution.
Ubuntu 14.04

Introduction

When using the Nginx web server, server blocks (similar to the virtual hosts in Apache) can be used to encapsulate configuration details and host more than one domain off of a single server.

In this guide, we’ll discuss how to configure server blocks in Nginx on an Ubuntu 14.04 server.

Prerequisites

We’re going to be using a non-root user with sudo privileges throughout this tutorial. If you do not have a user like this configured, you can make one by following steps 1-4 in our Ubuntu 14.04 initial server setup guide.

You will also need to have Nginx installed on your server. If you want an entire LEMP (Linux, Nginx, MySQL, and PHP) stack on your server, you can follow our guide on setting up a LEMP stack in Ubuntu 14.04. If you only need Nginx, you can install it by typing:

sudo apt-get update
sudo apt-get install nginx

When you have fulfilled these requirements, you can continue on with this guide.

For demonstration purposes, we’re going to set up two domains with our Nginx server. The domain names we’ll use in this guide are example.com and test.com.

You can find a guide on how to set up domain names with DigitalOcean here. If you do not have two spare domain names to play with, use dummy names for now and we’ll show you later how to configure your local computer to test your configuration.

Step One — Set Up New Document Root Directories

By default, Nginx on Ubuntu 14.04 has one server block enabled by default. It is configured to serve documents out of a directory at:

/usr/share/nginx/html

We won’t use the default since it is easier to work with things in the /var/www directory. Ubuntu’s Nginx package does not use /var/www as its document root by default due to a Debian policy about packages utilizing /var/www.

Since we are users and not package maintainers, we can tell Nginx that this is where we want our document roots to be. Specifically, we want a directory for each of our sites within the /var/www directory and we will have a directory under these called html to hold our actual files.

First, we need to create the necessary directories. We can do this with the following command. The -p flag tells mkdir to create any necessary parent directories along the way:

  1. sudo mkdir -p /var/www/example.com/html
  2. sudo mkdir -p /var/www/test.com/html

Now that you have your directories created, we need to transfer ownership to our regular user. We can use the $USER environmental variable to substitute the user account that we are currently signed in on. This will allow us to create files in this directory without allowing our visitors to create content.

  1. sudo chown -R $USER:$USER /var/www/example.com/html
  2. sudo chown -R $USER:$USER /var/www/test.com/html

The permissions of our web roots should be correct already if you have not modified your umask value, but we can make sure by typing:

  1. sudo chmod -R 755 /var/www

Our directory structure is now configured and we can move on.

Step Two — Create Sample Pages for Each Site

Now that we have our directory structure set up, let’s create a default page for each of our sites so that we will have something to display.

Create an index.html file in your first domain:

  1. nano /var/www/example.com/html/index.html

Inside the file, we’ll create a really basic file that indicates what site we are currently accessing. It will look like this:

<html>
    <head>
        <title>Welcome to Example.com!</title>
    </head>
    <body>
        <h1>Success!  The example.com server block is working!</h1>
    </body>
</html>

Save and close the file when you are finished.

Since the file for our second site is basically going to be the same, we can copy it over to our second document root like this:

  1. cp /var/www/example.com/html/index.html /var/www/test.com/html/

Now, we can open the new file in our editor and modify it so that it refers to our second domain:

  1. nano /var/www/test.com/html/index.html
<html>
    <head>
        <title>Welcome to Test.com!</title>
    </head>
    <body>
        <h1>Success!  The test.com server block is working!</h1>
    </body>
</html>

Save and close this file when you are finished. You now have some pages to display to visitors of our two domains.

Step Three — Create Server Block Files for Each Domain

Now that we have the content we wish to serve, we need to actually create the server blocks that will tell Nginx how to do this.

By default, Nginx contains one server block called default which we can use as a template for our own configurations. We will begin by designing our first domain’s server block, which we will then copy over for our second domain and make the necessary modifications.

Create the First Server Block File

As mentioned above, we will create our first server block config file by copying over the default file:

  1. sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.com

Now, open the new file you created in your text editor with root privileges:

  1. sudo nano /etc/nginx/sites-available/example.com

Ignoring the commented lines, the file will look similar to this:

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.html index.htm;

    server_name localhost;

    location / {
        try_files $uri $uri/ =404;
    }
}

First, we need to look at the listen directives. Only one of our server blocks can have the default_server specification. This specifies which block should server a request if the server_name requested does not match any of the available server blocks.

We are eventually going to disable the default server block configuration, so we can place the default_server option in either this server block or in the one for our other site. I’m going to leave the default_server option enabled in this server block, but you can choose whichever is best for your situation.

The next thing we’re going to have to adjust is the document root, specified by the root directive. Point it to the site’s document root that you created:

root /var/www/example.com/html;

Note: Each Nginx statement must end with a semi-colon (;), so check each of your lines if you are running into problems.

Next, we want to modify the server_name to match requests for our first domain. We can additionally add any aliases that we want to match. We will add a www.example.com alias to demonstrate:

server_name example.com www.example.com;

When you are finished, your file will look something like this:

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /var/www/example.com/html;
    index index.html index.htm;

    server_name example.com www.example.com;

    location / {
        try_files $uri $uri/ =404;
    }
}

That is all we need for a basic configuration. Save and close the file to exit.

Create the Second Server Block File

Now that we have our initial server block configuration, we can use that as a basis for our second file. Copy it over to create a new file:

  1. sudo cp /etc/nginx/sites-available/example.com /etc/nginx/sites-available/test.com

Open the new file with root privileges in your editor:

  1. sudo nano /etc/nginx/sites-available/test.com

In this new file, we’re going to have to look at the listen directives again. If you left the default_server option enabled in the last file, you’ll have to remove it in this file. Furthermore, you’ll have to get rid of the ipv6only=on option, as it can only be specified once per address/port combination:

listen 80;
listen [::]:80;

Adjust the document root directive to point to your second domain’s document root:

root /var/www/test.com/html;

Adjust the server_name to match your second domain and any aliases:

server_name test.com www.test.com;

Your file should look something like this with these changes:

server {
    listen 80;
    listen [::]:80;

    root /var/www/test.com/html;
    index index.html index.htm;

    server_name test.com www.test.com;

    location / {
        try_files $uri $uri/ =404;
    }
}

When you are finished, save and close the file.

Step Four — Enable your Server Blocks and Restart Nginx

You now have your server blocks created, we need to enable them.

We can do this by creating symbolic links from these files to the sites-enabled directory, which Nginx reads from during startup.

We can create these links by typing:

  1. sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
  2. sudo ln -s /etc/nginx/sites-available/test.com /etc/nginx/sites-enabled/

These files are now in the enabled directory. However, the default server block file we used as a template is also enabled currently and will conflict with our file that has the default_server parameter set.

We can disable the default server block file by simply removing the symbolic link. It will still be available for reference in the sites-available directory, but it won’t be read by Nginx on startup:

  1. sudo rm /etc/nginx/sites-enabled/default

We also need to adjust one setting really quickly in the default Nginx configuration file. Open it up by typing:

  1. sudo nano /etc/nginx/nginx.conf

We just need to uncomment one line. Find and remove the comment from this:

server_names_hash_bucket_size 64;

Now, we are ready to restart Nginx to enable your changes. You can do that by typing:

  1. sudo service nginx restart

Nginx should now be serving both of your domain names.

Step Five — Set Up Local Hosts File (Optional)

If you have not been using domain names that you own and instead have been using dummy values, you can modify your local computer’s configuration to allow you to temporarily test your Nginx server block configuration.

This will not allow other visitors to view your site correctly, but it will give you the ability to reach each site independently and test your configuration. This basically works by intercepting requests that would usually go to DNS to resolve domain names. Instead, we can set the IP addresses we want our local computer to go to when we request the domain names.

Make sure you are operating on your local computer during these steps and not your VPS server. You will need to have root access, be a member of the administrative group, or otherwise be able to edit system files to do this.

If you are on a Mac or Linux computer at home, you can edit the file needed by typing:

  1. sudo nano /etc/hosts

If you are on Windows, you can find instructions for altering your hosts file here.

You need your server’s public IP address and the domains you want to route to the server. Assuming that my server’s public IP address is 111.111.111.111, the lines I would add to my file would look something like this:

127.0.0.1   localhost
127.0.0.1   guest-desktop
111.111.111.111 example.com
111.111.111.111 test.com

This will intercept any requests for example.com and test.com and send them to your server, which is what we want if we don’t actually own the domains that we are using.

Save and close the file when you are finished.

Step Six — Test your Results

Now that you are all set up, you should test that your server blocks are functioning correctly. You can do that by visiting the domains in your web browser:

http://example.com

You should see a page that looks like this:

Nginx first server block

If you visit your second domain name, you should see a slightly different site:

http://test.com

Nginx second server block

If both of these sites work, you have successfully configured two independent server blocks with Nginx.

At this point, if you adjusted your hosts file on your local computer in order to test, you’ll probably want to remove the lines you added.

If you need domain name access to your server for a public-facing site, you will probably want to purchase a domain name for each of your sites. You can learn how to set them up to point to your server here.

Conclusion

You should now have the ability to create server blocks for each domain you wish to host from the same server. There aren’t any real limits on the number of server blocks you can create, so long as your hardware can handle the traffic.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products


Tutorial Series: Introduction to Nginx and LEMP on Ubuntu 14.04

This tutorial series helps sysadmins set up a new web server using the LEMP stack, focusing on Nginx setup with virtual blocks. This will let you serve multiple websites from one Droplet.

You’ll start by setting up your Ubuntu 14.04 server and end with multiple virtual blocks set up for your websites. An Nginx configuration guide is included at the end for reference.

About the authors

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
10 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
July 19, 2014

@gugaalves: Add a new virtualhost with the following config:

server {
    listen 80;
    server_name www.domain.com;

    return       301 http://domain.com$request_uri;
}

and restart nginx.

The article is great! BUT the soft links are set up incorrectly.

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/test.com /etc/nginx/sites-enabled/

This must be:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo ln -s /etc/nginx/sites-available/test.com /etc/nginx/sites-enabled/test.com

Cheers!

Hello!, First of all, Thanks for the tutorial.

I have a question about the reverse proxy. Is it posible to have 2 or more internal different servers for virtual hosting?

For example

I have one public address for web a server 8.8.8.8 And I have these names web1.example.com web2.example.com web3.example.com.

I have 3 internal web servers: web1.example.com -> 192.168.0.11 web2.example.com -> 192.168.0.12 web3.example.com -> 192.168.0.13

I have a ngix server with ip 192.168.0.10. I have a NAT table configured with 80 port and 443 port.

I want that if I write in my web browser web1.example.com I want to go to webserver 192.168.0.11 If I write in my web browser web2.example.com I want to go to webserver 192.168.0.12

Is it possible with ngix or is only for the same internal web server?

And My second question (if the first is posible) is about the SSL certificates, I want that for the web1.example.com a certificate (web1) I want taht for the web2.example.com another certificate (web2)

Is it posible?

Thanks a lot for the answers.

After following the;

We can disable the default server block file by simply removing the symbolic link. It will still be available for reference in the sites-available directory, but it won’t be read by Nginx on startup:

I lost connection to phpMyAdmin Access Location - that i set by following the tutorial: https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-phpmyadmin-with-nginx-on-an-ubuntu-14-04-server

And trying to find out how to edit the symbolic link to phpmyadmin. Any tips?

Small typo in “Create the Second Server Block File”:

server_name example.com www.example.com;

should be:

server_name test.com www.test.com;

Good article - just one nit-picky thing:

sudo service nginx restart is perfectly valid, but if you have a busy site, you might drop a couple of connections.

Safer, cleaner (and easier!) is to follow this tip I’ve been using since I found it on stackoverflow, which comes in very useful if you’re making lots of changes or experimenting and tweaking:

alias n='/etc/init.d/nginx configtest && sudo /etc/init.d/nginx reload'

from then on, just hit n and enter. Instance new config, tested and reloaded if it’s valid.

If you like the alias, just

sudo nano ~/.bash_aliases

add that alias line following the correct format and then

source ~/.bash_aliases

so you won’t need to reload the shell.

(I won’t delve into the whole /var/www vs /usr/share/nginx/html debate because I’m still not decided which is correct! )

Thanks!

First of all, thank you so much for taking the time to make this great tutorial, I really appreciate it!

I’m having a small problem. When I try to load my site, instead of serving the page, it actually downloads a file with the php code in it…if that makes sense?

One thing I did is create a brand new file for each of my sites instead of copying the default one, so there is literally just the server { } code and nothing else. Also, if I change my file from a php file to an html file, it serves the files as expected. I do have “index.php” added in the server { } code and I can’t think of any other reason why it’s not recognizing the php file.

Cheers, Andrew

how do I undo changes.

I broke all…

when I am on the step of restarting de ngnix…

Job for nginx.service failed because the control process exited with error code. See “systemctl status nginx.service” and “journalctl -xe” for details.

watt is this ???

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.