I've been using a RamNode VPS for over 3 years now. It's extremely low-end, having only 128MB of RAM, so something as lightweight and fast as Nginx was perfect to host my static website.

At the time I was new to provisioning a web server from scratch and ended up doing a lot of things just to get to a working state. Over time it's evolved as I learnt new tricks, leaving a mess in the process.

This seems to be a problem with any project in both the cyber and physical world. As you create more of something, you need to decide where to put them and reorganise everything else. Making it refactoring essentially.

Anyway, for this article I'm strictly talking about directory structures and where to put files used by a web server. No matter which web server you're using, the solution probably applies equally.


Setup

Nginx, as I'm using it requires these types of files:

  • Configuration - e.g. nginx.conf
  • Logs - e.g. access.log, error.log
  • Assets - e.g. HTML, CSS, JavaScript files
  • Proxy Cache - If you want to proxy a request but don't want to hit the origin with every request.

Before my changes, this is the mess it was in:

  • /etc/nginx/ - Configuration. Default location when installing Nginx via YUM.

    • /etc/nginx/nginx.conf
    • /etc/nginx/conf.d/{server}.conf - Server-specific configuration. server being the subdomain of jahed.io
    • /etc/nginx/includes/{name}.include.conf - Common partial configurations such as adding CORS headers.
  • /var/log/nginx - Logs

  • /srv/www/{folder} - Assets. folder being arbitrary so I could serve different files for different Nginx servers

  • /srv/cache/{zone_name} - Proxy Cache

A lot of these are default locations and I was essentially overriding defaults with my own configuration. So when Nginx updates, it'll dump new files in the default directories which may cause issues.

There's also a lack of conventions.:

  1. /srv shouldn't contain cache data as they're temporary.
  2. includes can mean anything.
  3. Assets being place in folder makes it hard to know what's using it.
  4. server doesn't map directly to an Nginx server_name so if I have 2 servers, abc.jahed.io and abc.something.com, they'll conflict.

Solution

The nginx command doesn't have to be run using the defaults. Using the -p and -c flags we can launch a server with any given "prefix" and "configuration" respectively. The defaults being /etc/nginx and nginx.conf.

Here's the new structure I came up with:

  • /etc/www/nginx - Configuration

    • /etc/www/nginx/servers/{server_name} - Server-specific configuration. Where server_name corresponds to the Nginx server_name
    • /etc/www/nginx/partials/_{name}.conf - Common partial configurations. Such as adding CORS headers.
  • /var/log/www/nginx - Logs

  • /srv/www/{server_name} - Server-specific assets.

  • /var/tmp/www/{zone_name} - Proxy Cache

All web-related files are now prefixed with www no matter where they are in the hierarchy. This makes it obvious what they're used for. So if I introduce another web-related service that isn't using Nginx, it'll still fall under the www prefix. It also means the files are bound to the service they provide as well as the applications they're used in, rather than just the latter.

To cover my previous list of problems:

  1. Cached data now goes in /var/tmp as they're temporary; being constantly updated as caches are renewed and expired. /var/tmp files, unlike /tmp aren't cleared on system reboots.
  2. Following conventions from static site generators and other tools, partials are now indicated using an underscore prefix (_).
  3. Assets are now in directories named after the Nginx server_name they're being used by.
  4. Server-specific configuration is now named by server_name

That's essentially all there is to it. I'm pretty happy with this approach. Of course, I'm bound to change some things as time goes on but the foundations seem solid.


Related links

Comments