How to Host a Static Website with Nginx

Static site generators are a fantastic way to manage a website. Static sites are faster and safer than dynamic sites. They can be easily generated by a wide variety of static site generators. My favorite is Hugo. Nginx is an ideal web server for serving these static files. In this tutorial we will set up a server and optimize it for serving our static site.

This server is going to be optimized for static sites. I recommend keeping your static websites and your dynamic websites on separate systems. In the long run, this separation will save time and frustration, VPSs are super cheap. I recommend Linode and I do so without an affiliate code.

This guide assumes that you already have a properly configured remote server. If you need help setting up a basic server, check out Setting Up a Basic Server with Ubuntu 16.04. This guide is intended for and has been tested on Ubuntu 16.04.


Install Nginx web server.

Controlling Nginx

The following commands will help you control Nginx.

This will start Nginx

To stop Nginx

To restart Nginx

To reload Nginx configurations.


Your server should be running a firewall. I recommend the Uncomplicated Firewall (UFW). If you need help with UFW, check out, A Guide to the Uncomplicated Firewall (UFW) for Linux. The following command will allow HTTP and HTTPs traffic.

Then we need to reload the firewall rules.

If you are using another firewall and don’t know how to allow HTTP or HTTPS traffic, then you should consider switching to UFW. Firewalls are too import to be convoluted. UFW allows mere mortals to create firewall rules.


At this point, we should verify that the server is operational. Visit your servers IP address in a web browser. You should be greeted by a generic Nginx info screen from the default site. If that does not happen then something when wrong.

Make a Dummy Site

I want to serve files from a directory within my home directory. This directory will be called www.

In this new directory we will make a dummy index.html page.

Inside just put anything. We don’t need actual html, just something kinda unique.

Now we need to change the www directory permissions. This will allow Nginx to access the files.

Nginx Configuration Directory

Let’s enter the directory containing the Nginx configuration files.

ls this directory to take a look around. In this tutorial we only care about a couple files and directories. The file nginx.conf is the central configuration file for our Nginx instance. The sites-available and sites-enabled directories contain the site specific configuration files.


It is a good practice to make backups of configuration files before editing them. Make a backup of of nginx.conf.

Now open up the primary Nginx configuration file and take look around.

First of all, lines starting with a # are comments and are ignored by Nginx. Directives need to end with a semicolon ;. Configuration is organized into blocks such as http, server, location. Nginx configuration files can also include other files. If l you look near the bottom of the http block you should see a line, include /etc/nginx/sites-enabled/*;. The configuration files in the sites-enabled will be included as part of the Nginx configuration. The sites-enabled will be where our website specific settings files will be. The nginx.conf will be where the server wide settings will be.


Enter the sites-available directory.

Generally speaking, the sites-available directory contains configuration files for individual websites. Let’s take a look at the default configuration file.

In this file you should see more blocks. Look for the server and location blocks. Exit nano and then copy this default file. Let’s make a new configuration file for a new website. I would name the new file for the domain you will be using. In my case that is

This will be the site specific configuration file for the website at Edit the file and change the values as appropriate.

Nginx needs to know a few things before it can actually start serving up web pages. Notice that our settings will live in a server block. We tell Nginx to listen for connections on port 80. That this server block is for the domain That the files to server are located at /home/jason/www.

Remember earlier when we talked about included configuration files? Configuration files in the sites-enabled directory will be included in our Nginx instance. Create a symbolic link for the configuration files we want to enable.

Then restart the Nginx server.

Check to see if the sites is up.

Which should return the contents of the index.html that we made earlier.

It works

At this point we have a working website. All you need now is to have your static site generator output to /home/jason/www. Anything in that folder will be served by the Nginx. The next few sections will cover various optional features and optimizations that you can choose.


Writing web logs takes resources. If you want to save these resources, disable logging. Open up the main Nginx configuration file.

Find the logging section.

Comment out the access_log and the error_log.

Client Side Caching

Telling our clients to cache resources like js, css, and images files can significantly improve performance. I like to use the a shortened version of the rules from H5BP’s server-configs-nginx.

These rules can be added to your site configuration file.

Is should look something similar to this.

Add the caching rules to the end of the block.


Compression should be already be activated by default on your server. We can save server resources and get higher compression levels with by pre-compressing our files. We will enable pre-compressed files by editing the main Nginx configuration file.

Find the section:

And just add gzip_static on;.

Then restart the Nginx server.

Our example index.html from earlier will not really benefit from compression. But, we will do it anyhow for the sake of the demonstration.

-v is for verbose, -k is for keeping the original file, -f is to overwrite any older zipped file with the same name, and — best is for the best compression. Your static site generator will probably have an option for pre-compression. Check the documentation.


Properly enabling encryption in your web server used to be terrible. Signed certificates were expensive and the setup was complicated. Our friends at the EFF and Let’s Encrypt fixed that. We are no longer beholden to the corrupt and frequently incompetent certificate authority cartel. Signed certificates are now available free from Let’s Encrypt. And the certbot program sets up the server for us.

Install certbot.

Run certbot.

This should bring up a dialog.

On my server I have a couple of sites. Select the site you would like to activate HTTPS for. After making your selection, certbot will do some work and then ask if you would like to redirect traffic to HTTPS.

I would choose to redirect. If all goes well, you will see a congratulations message.

Then restart the Nginx server.

Visit the site with your browser. If you chose to redirect you will automatically be sent to the HTTPS version of the site.

Certificates must be renewed or the will expire. The following command will do this. Add it to your crontab to run regularly.

Enable HTTP/2

HTTP/2 is a major improvement for the web. It can give you a large improvement in client performance. You will need to have enabled HTTS for HTTP/2. Open up the configuration file for

You will see certbot has done some editing. Find the listen line.

change that to:

Then restart the Nginx server.


You now have an web server optimized for serving static conten

You may remember me from such projects as The Seattle Podcasters Guild, The Talking Cryptocurrency Podcast, or some of my popular Python tutorials.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store