Nginx Multi and Single Site Configuration (Static Sites)

Written by Christophe Limpalair on 09/08/2015

After reading this guide you will be able to serve one or more sites, from a single server, using Nginx.

How do you do that? Turns out it's quite simple once you get the hang of it.

Sites Configuration

Note: this guide assumes your Nginx directory is in /etc/nginx, which is the default when using apt-get install. It could also be in /usr/local/nginx, or /usr/local/etc/nginx

There are two directories that we need to keep in mind when configuring Nginx to serve our sites. The first is /etc/nginx/sites-available/ and the second is /etc/nginx/sites-enabled/.

A typical and recommended method is to have your site configurations in sites-available, and then create a symbolic link to sites-enabled. This makes it easy to take down sites or put them up, because only configurations in sites-enabled actually get used.

If you haven't modified any of the default Nginx settings and you've installed with apt-get install nginx, then you will have a default configuration in sites-available. I recommend you open that up and read through the comments.

But for now, let's create a new one:

vim /etc/nginx/sites-available/scaleyourcode.conf


Let's start out simple:

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

server_name scaleyourcode.com www.scaleyourcode.com;

location / {
root /usr/share/nginx/scaleyourcode;
index index.html index.htm;
}
}


listen 80;
The first two lines listen on port 80, with the second line being for IPv6.

If you want HTTPS, you'd have a server directive for port 80 that redirects to https:, and below that server directive you would create another server directive that listens for port 443. More on that here.

You can also add default_server right after the port number. You can only have one default.

server_name
This directive makes your site available via the server name. In our case, http://scaleyourcode.com or http://www.scaleyourcode.com.

Keep in mind that if you don't actually own the domain or just want to test, you need to add this domain name to your hosts file. I'll show you this in just a little bit.

location /
This is where things get interesting.

Once Nginx decides which server processes a request, it tests the URI specified in the request's header against the parameters of our location directives. I'll show you a few examples to explain this better. First let me explain what's going on inside of this location block.

root
The root directive tells Nginx where to search for a file.

Nginx appends the request URI to the path specified in the root directive.

Let's say someone types http://scaleyourcode.com/test.html. Nginx will look for test.html in /usr/share/nginx/scaleyourcode/. If it doesn't find anything, it returns a 404.

index index.html index.htm;
This is our index directive, and this is where we can tell Nginx what index file to look for.

Let's say someone types http://scaleyourcode.com/

Nginx will look for an index.html first in /usr/share/nginx/scaleyourcode/. If it doesn't find anything, it will look for index.htm before returning a 404.

More examples

To better explain location directives, lets walk through more examples.

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

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

server_name scaleyourcode.com www.scaleyourcode.com;

location / {}

location ~ \.(gif|jpg|jpeg|png)$ {
root /usr/uploads/images;
}

location /videos {
root /usr/uploads/videos;
}
}


The root and index directives are pulled out of the location block. This means that root directive should be used by default, unless another is specified in the location directive.

location ~ \.(gif|jpg|jpeg|png)$
I've also added a location block that uses regular expressions to match URIs ending with gif, jpg, jpeg, or png.

For example, let's say someone types http://scaleyourcode.com/2015/main.jpg. Nginx will look in /usr/uploads/images/2015/main.jpg

A regex needs to be preceded with ~. If the URI doesn't match one of these extensions, Nginx defaults back to the previous matching block. Nginx also first checks location prefix strings. If there is a match, then the regular expression is checked on that location block.



location /videos
I've added a third location directive that looks for /videos.

You may be confused as to how Nginx decides whether to check the location / vs location /videos. It checks the longest prefix first, then falls back if there is no match.

Other useful settings

We've covered the essential settings, but there are a few more that you might find useful.

location = /favicon.ico { access_log off; log_not_found off;}


This could go anywhere -- below your other location blocks for example. If you're starting out without a favicon, it doesn't make sense to write in the access log and not found log for every single visitor.

access_log /srv/usr/nginx/logs/access.log;
error_log /srv/usr/nginx/logs/error.log;


This, of course, tells Nginx where to save access and error logs. You could also have different logging paths for different location directives.

Prefer not to log these? Turn them off just like we did for our favicon.ico.

error_page  404  /404.html;
error_page 500 502 503 504 /50x.html;


Specify a custom 404 error page with this setting.

Enable your new site

Once you have finished configuring your site, save the file and complete the following steps:

1) Create a symlink to /sites-enabled/
2) Create your root directory and add your site's files
3) (optional) Add your server_name to your /etc/hosts if you don't own the domain name or if you're just testing
4) Reload Nginx

Step #1


This step is easy, but remember to use the absolute path! If you don't it won't point to the right file.

sudo ln -s /etc/nginx/sites-available/scaleyourcode.conf /etc/nginx/sites-enabled/


Now you can edit the file in sites-available and all your changes will be reflected in sites-enabled.

Want to take this site down in the future? All you have to do is

rm /etc/nginx/sites-enabled/scaleyourcode.conf


This won't delete the file in sites-available, just sites-enabled. See how easy that is?

Step #2


If you haven't already, make sure your root directive is pointing to an existing directory.

sudo mkdir /usr/share/nginx/scaleyourcode

vim /usr/share/nginx/scaleyourcode/index.html


Step #3 (optional)


Add your server_name(s) to your /etc/hosts file. Remember you don't need to do this if you own your domain name.

sudo vim /etc/hosts


Below the other 127.0.0.1 lines, add yours:

127.0.0.1	localhost	test.com www.test.com


Don't forget to add ports if you are listening on anything other than 80.

Reload Nginx


All you have to do is reload Nginx and you are good to go.

sudo service nginx restart


What now?

First of all, if you run into any issues, don't hesitate to leave a comment.

Second, I recommend that you play around with various configurations to see how they work. Documentation is a good place to start.

Next up, I'm going to show you how to set up dynamic site configurations. So if you have a PHP, Ruby app, or anything else that generates different results depending on queries and such, sit tight for that. Don't want to wait? I already have a Complete Guide to Install and Configure Nginx + PHP-FPM.

Thanks for reading!