In my previous post I wrote about turning Hugo aliases into Firebase redirects. Now — let’s convert them into a Nginx map file, and have Nginx redirect based on that file.

This time we need to output all our aliases to a text file, so we define a new output in our Hugo configuration file — in my case config.toml

[outputs]
  home = ["HTML", "RSS", "REDIR"]

[outputFormats.REDIR]
  baseName = "redirects"
  isPlainText = true
  mediaType = "text/plain"
  notAlternative = true

Then we create the layout file, layouts/index.redir.txt

{{- range $p := .Site.Pages -}}
{{- range .Aliases -}}
{{- printf "%s %s;\n" . $p.RelPermalink -}}
{{- end -}}
{{- end -}}

Now when we generate our site, we get a redirects.txt listing all our aliases in Nginx map style. I currently only have one, so my file looks like this:

/2021/01/optiplex-9010-sff-bios-battery/ /2021/01/optiplex-9010-sff-cmos-battery/;

Next we need to get Nginx to actually read this map file, and redirect. This is an example of a simple Nginx site config:

map_hash_bucket_size 256; # see http://nginx.org/en/docs/hash.html

map $request_uri $new_uri {
    include /var/www/html/blog/redirects.txt;
}

server {
    listen 80;
    server_name blog.cavelab.dev;
    root /var/www/html/blog;

    if ($new_uri) {
      return 301 $new_uri;
    }   

    location / { 
      add_header Cache-Control "public, max-age=3600";
    }

    error_page 404 /404.html;
}
You need to modify this to match your environment and settings.

The only thing that remains now is to reload Nginx after the redirects.txt file has been deployed. I do this in the deploy step in my Drone SSH pipeline:

- name: deploy
  commands:
  - rsync -ah --delete --stats public/ cirrus:/var/www/html/blog
  - ssh cirrus -f "sudo systemctl reload nginx"

But wait! Reloading Nginx requires privilege escalation — sudo. We need to enable the deployment user to do this without requiring a password. We can do this with visudo:

$ sudo visudo

# add this at the end
deployer ALL=(ALL) NOPASSWD: /bin/systemctl reload nginx
You need to change deployer to the username that deploys in your environment.

Done! 😄

The next time you build and deploy your Hugo site, the map file will be updated and Nginx reloaded. Turning your aliases into proper redirects 😃