Serving This Website


This site is served using nginx, an extremely capable, open-source tool that makes serving static content remarkably simple. I’m using the nginx-mainline package, which is what I would call their bleeding-edge version. On Arch run pacman -S nginx-mainline to install it.

After installing, you’ll need to get your configuration file set up. I just edit over my ssh session with vim, but you can do this however you see fit. With nginx-mainline, your configuration file will be located at /etc/nginx/nginx.conf. The directory structure will be slightly different than on Debian-based distributions, so keep that in mind while you search for help online.

nginx configuration files are simple and intuitive, and the default file they provide should offer direction. A minimal configuration for this site would look something like this:

worker_processes  1;

events {
    worker_connections  1024;
}

http {

  include            mime.types;
  default_type       application/octet-stream;
  sendfile           on;
  keepalive_timeout  65;

  server {
    server_name  devinadooley.com www.devinadooley.com;

    location / {
      root   /var/www/devinadooley.com;
      index  index.html index.htm;
    }

    # use the custom error page at /404.html
    error_page  404  /404.html;

    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
      root   /usr/share/nginx/html;
    }
  }
}

Even if you aren’t too familiar with nginx, you should be able to discern a bit of what is going on here. By nesting a block of server rules inside of an http block, we are directing nginx to serve the rules defined in the server block over the HTTP protocol. So, any time nginx is started or restarted, it will look at this configuration file and will attempt serve what is configured in this block over HTTP.

In this case, we declare a server block that accepts requests for devinadooley.com and www.devinadooley.com, as defined by the server_name. Requests for these routes will serve the files from the locations defined in this block. Our main files, those served at the top level location of /, will be located at – /var/www/devinadooley.com on the server. This means that /var/www/devinadooley.com/index.html corresponds to this site’s homepage.

Error pages can be configured if you wish, otherwise you can use the default error pages given by nginx. Here I’m using a custom 404.html file to serve when a 404 response is returned. The location /404.html means that the file will be located at the root of the server location /, i.e. /var/www/devinadooley.com/404.html. Rather than configure my own error pages in the 500 range, I’m simply using the /50x.html page provided by nginx by default. Since this file is located in a new location, it is required that the location be defined by the server block by providing the associated location.

Once you are confident in your configuration, enable and start the nginx daemon by running systemctl enable nginx and systemctl start nginx. If you see any errors in this process, or you suspect something went wrong, you can look for errors by tailing the server logs with journalctl -r.

This example should get you all the functionality you need for serving static content. However, people tend to distrust websites that do not support HTTPS, and I think it is worthwhile to keep what pages and resources your users request encrypted. With nginx, the typical way to do this is to change your existing server block to listen on port 443 (HTTPS) rather than port 80 (HTTP), and configure the certificate information for that block. Then, you create a new server block that acts as a reverse proxy, directing all requests to your domain over port 80 to port 443.

If you are like me and don’t wish to manage your certificates manually, you can use the certbot tool provided by Let’s Encrypt. It’s a fantastic tool that creates and renews your certificates with a straightforward command-line interface. The tool uses Let’s Encrypt as a certificate authority (CA), and gives your certificates a three month validity (a small price to pay for the convenience). The folks over at Let’s Encrypt also provide supplemental support for nginx that configures a reverse proxy for you. With certbot, the whole process for enabling SSL support for your domain should take less than 15 minutes.

Your flavor of Linux more than likely provides the certbot and certbot-nginx packages you’ll need to get up and running. On Arch, they can be installed by running pacman -S certbot certbot-nginx. Go ahead and run certbot --nginx and let the tool guide you through what nginx servers you would like to enable HTTPS for. When you are done your original server block should be configured to serve over HTTPS on port 443, and you should have a new server block which redirects HTTP traffic to the HTTPS server. Don’t forget to run systemctl restart nginx to update your nginx daemon.

To give an example of a more complete configuration, the nginx.conf file used by my server at the time of writing is given below. You’ll notice that I am also serving images from the subdomain images.devinadooley.com, and I am using the /nginx_status location to provide information to my monitoring tool monitorix. Outside of those differences, after using certbot your file should look roughly like this (although the tool does mess with indentation a bit in my experience).

worker_processes  1;

events {
  worker_connections  1024;
}

http {

  include            mime.types;
  default_type       application/octet-stream;
  sendfile           on;
  keepalive_timeout  65;

  server {
    server_name  devinadooley.com www.devinadooley.com;

    location / {
      root   /var/www/devinadooley.com;
      index  index.html index.htm;
    }

    error_page  404  /404.html;

    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
      root   /usr/share/nginx/html;
    }

    # used by monitorix to report nginx statistics
    location /nginx_status {
      stub_status on;
      access_log off;
      allow 127.0.0.1;
      deny all;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/devinadooley.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/devinadooley.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
  }

  server {
    server_name  images.devinadooley.com

    location / {
      root   /var/www/images.devinadooley.com;
    }

    error_page  404  /var/www/devinadooley.com/404.html;

    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
      root   /usr/share/nginx/html;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/devinadooley.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/devinadooley.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
  }


  server {
    if ($host = www.devinadooley.com) {
      return 301 https://$host$request_uri;
    } # managed by Certbot

    if ($host = devinadooley.com) {
      return 301 https://$host$request_uri;
    } # managed by Certbot

    listen       80;
    server_name  devinadooley.com www.devinadooley.com;
    return 404; # managed by Certbot
  }

  server {
    if ($host = images.devinadooley.com) {
      return 301 https://$host$request_uri;
    } # managed by Certbot

    listen       80;
    server_name  mages.devinadooley.com
    return 404; # managed by Certbot
  }


}