Configuring NGINX

As I mentioned in initial setup, I prefer to use nginx where possible. It's surprisingly easy to get set up in a relatively sophisticated fashion.

Server Block Configuration

Apache uses the term Virtual Hosts to refer to a method of hosting multiple domains on the same server. The function in nginx which amounts to the same thing, functionally, is called Server Blocks.

If you want to host several sites on the same server, your nginx.conf can get quite long. Some Linux distributions provide two directories (sites-available and sites-enabled) which hold configuration files. It's a convenient way to manage several websites on the same server. If you're only hosting one site on your server (or don't want to bother right now), you can just edit the server block within nginx.conf

# cd /usr/local/etc/nginx
# mkdir sites-available
# mkdir sites-enabled

Now edit nginx.conf. Cut the entire server section (in my case, it was from line 35 until the last curly brace), and paste it into a new file in sites-available/ called project-name.com (or whatever you want. It doesn't matter what you choose, but using the domain name of the project makes it easy to remember later).

In nginx.conf, in place of the server block, type:

include /usr/local/etc/nginx/sites-enabled/*;

Now it's time to do the actual setup of the server block. Open project-name in sites-available.

SEO Tip

It's best to choose to use either www.project-name.com, or simply project-name.com. It doesn't really matter which one you choose, but Google sees them as different websites. If you get two good links to one page, but one is www.project-name.com and the other is project-name.com, the Google index will contain two pages, each with 50% of the link juice. We'll set up a 301 (permanent) redirect to capture as much link juice as possible from incorrectly attributed links.

Set server_name to be whichever variation you choose. In the location block, set root to be whichever directory you want to work out of. I recommend /home/your-user/project-name. Now delete most of the rest of the file until it looks like this:

server {
    listen 80;
    server_name your-project.com;

    location / {
        root  /home/your-user/project-name;
        index index.html;
    }
}

Somewhat obviously, the listen directive tells nginx which port to listen on. Port 80 is the port that web browsers use by default. You can also specify an IP address to listen on, if you have multiple internet connections/NICs, by prepending one with a colon (i.e. 192.168.0.1:80). The server-name tells it what the site will be called in the requests it processes. location / is called a "location block", and tells nginx that these settings apply to everything following the / after your domain name.

The Flow Of Data

When someone types your-project.com into their browser, nginx will look in the directory specified by the root directive (/home/your-user/project-name in this case). index tells nginx which page to serve when someone types in that location to their address bar. So nginx gets the file /home/your-user/project-name/index.html and sends it to the user (their address bar will still read http://your-project.com, and not show index.html). If someone were to type www.your-project.com into their browser, it should return a 404 (Not Found).

Testing Your Configuration

Save the configuration file you're working on. If you type cat /usr/local/etc/nginx/sites-available/your-project into the terminal, it should return the text of the server block you just saved. If it doesn't, you have a problem somewhere, and need to address it before continuing.

Remember: earlier we added the line include /usr/local/etc/nginx/sites-enabled/*; to nginx.conf. We've been working in sites-available until now, so nginx won't find any of the instructions we've written. Fix that by creating a symbolic link to the configuration file in sites-enabled:

# cd /usr/local/etc/nginx/sites-enabled
# ln -s ../sites-available/your-project .

If that worked, cat /usr/local/etc/nginx/sites-enabled/your-project should return your configuration.

Using symbolic links is a good way to manage multiple sites on the same server, because it makes their configuration files portable and it's fast to find the details you're looking for. You can keep the information for several sites on your server, and enable or disable them by simply adding or deleting the configuration link and reloading the server.

The next step is to have nginx parse your configuration files and tell you if it finds any errors:

# nginx -t

If it says your syntax is ok and the test is successful, you're ready to continue. If there are issues, it will usually tell you the line number. Some common problems are:

Once your configuration passes nginx's parsing test, you're ready to start up the server. It's nice to run it as a system service, so add the line

nginx_enable="YES"

to the file /etc/rc.conf. At least sshd is probably enabled in rc.conf, so you should be able to confirm your formatting with that entry. After you've saved, you should be able to use service to control nginx:

# service nginx start

Configuring Your Hosts File

nginx is expecting requests addressed to your-project.com, though, so even if you type in the IP address of your server, it won't be able to serve the right pages. If you're ready to put your page up live, you can point your domain's A-record at the right IP, and it should work. If you're not quite ready to have it be publicly accessible, you can modify the hosts file on your home computer. Linux/FreeBSD/Mac OS X users can find their hosts file at /etc/hosts. Add an entry specifying the IP address of your server and the domain name you plan on using (make sure you replace this IP address with the right one):

192.168.0.1  your-project.com

Now that you have nginx started and the hosts file set up properly, you should be able to get some pages served from it, right? Well, we haven't actually given it any content to serve. Make a file called index.html in the root directory you specified in your config file, and put the following content into it:

<html>
  <h1>Hello World!</h1>
</html>

Now, when you go to your-project.com in your browser, you should see Hello World. Your server is up and running!

Capturing Link Juice

As mentioned in the SEO Tip above, in order to capture the link juice from incorrectly attributed links, we need to set up a 301 redirect to the correct address. Fortunately, nginx makes it really easy to do in just a few lines. In the same file, add another server block that looks like this:

server {
    listen       80;
    server_name  *.your-project.com;
    return       301 http://your-project.com$request_uri;
}

This block will take any traffic to a subdomain of your site, and send it to your-project.com. But what if you want to have a blog on your site at blog.your-project.com? nginx chooses the most precise match to a request, so you can just add a third server block like this:

server {
    listen 80;
    server_name blog.your-project.com;

    location / {
        root  /home/your-user/project-name/blog;
        index index.html;
    }
}

SEO Tip

Don't set up your blog URL like this. Because Google will see blog.your-project.com as a separate site, you lose link juice. There might be a use case where a subdomain is desirable, but you're probably better off with your-project.com/blog/.

Your bare-bones /usr/local/etc/nginx/sites-available/your-project configuration file should now look like this:

server {
    listen       80;
    server_name  *.your-project.com;
    return       301 http://your-project.com$request_uri;
}

server {
    listen 80;
    server_name your-project.com;

    location / {
        root  /home/your-user/project-name;
        index index.html;
    }
}

Reload your server with:

nginx -s reload

You will need to set up a hosts file entry for each subdomain you want to use to test, but if you then type www.your-project.com (or whatever you set up in /etc/hosts) into your browser, you should be redirected to your-project.com with the Hello World message.

Next Steps

I would recommend setting up error and access logs for each domain name. They will help troubleshoot problems that inevitably come up. Logging is still set up for /var/log, though, so if you only have one site, it's probably not necessary to set up a separate log.

There are lots of other optimizations that can be made, but most of the configuration will be project specific. Play around with options and see what happens.