When I want to create a new application or a site, I need to edit nginx configuration: create a new site, add or remove security headers, proxify application, etc. But we make mistakes all the time. And there were a few cases when I wanted to rollback some changes, but I forgot what I'd changed. So, I decided to store these configuration files inside a git repository.

First thing I've attempted to do was to google some articles about best practices. All I found were these options:

  1. Place a repository anywhere in the system (usually, in a home directory) and include that directory in nginx.conf.
  2. Create a git repository inside nginx directory.
  3. Place a repository anywhere in the system and use a deploy script to copy files.

Placing a repository anywhere and using an include

First option doesn't seem to me like a good decision security-wise. I'm sure there is a reason for default files to be editable only by superuser.

Repository in /etc/nginx

I've decided to implement a second option. It's a simple and quick approach where you only have to git init inside /etc/nginx and you are all set. First disadvantage was that you either have to run git as a superuser to make a commit or to change an owner of the .git directory to yourself. It was alright until I had to reconfigure the server from the ground up. You can't clone a repository into a non-empty directory. I found a few workarounds for that problem, but thought that I had to do some changes to that workflow.

Placing a repository anywhere and using a deploy script

The next thing I've done was to move configuration repository out of /etc/nginx to some other place. Then, I've created a script to deploy and apply my changes. All it does is checks for superuser rights, rsync's files from the repository, compiles my custom error pages (I hate default ones) and reloads nginx.

And to simplify adding or editing configuration files, I've created a node.js script that watches for changes executes the above-mentioned script on each change.

One note here is that you can't just use node.js method fs.watch with recursive option. I had to use node-watch module from npm.

Closing words

Overall, now I'm using the third approach, placing a repository anywhere and utilizing a deploy script. This approach minimizes possible security issues and still allows to easily edit configuration while preserving history of edits.

Image by Yancy Min from Unsplash.