summaryrefslogtreecommitdiff
path: root/content/posts/switching-to-hugo-two/index.md
blob: 2b95f51281a191cbd4aa5723ed520751ab1cd8b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
+++
title = 'Switching To Hugo: Part Two'
description = 'The technical details of hosting my website.'
date = '2024-12-18T07:31:05-05:00'
draft = false
+++

*This post is part two in a two-part series on switching my website to
[Hugo](https://gohugo.io). It covers the technical details of hosting my
website. For an explanation as to why I made the switch, read
[part one](/posts/switching-to-hugo-one/).*

# Hosting my website
My website is hosted on [caddy](https://caddyserver.com), a popular HTTPS
server and reverse proxy. Caddy automatically obtains and renews TLS
certificates for my domains, which makes TLS certificate management a breeze.
The caddy server runs on one of my home servers, which itself runs NixOS.

## Configuring a web server on NixOS
[NixOS](https://nixos.org) allows for reproducible and declarative system
configurations, which makes the process of configuring and deploying a web
server quite trivial. One benefit of running my website on NixOS - aside from
the fact that NixOS is my distribution of choice - is that I can copy the
configuration down to any of my NixOS systems and have it work exactly the
same, regardless of the server it's running on. This alleviates the headache of
dependency management and reduces setup times down to just
`nixos-rebuild switch`, should I have the need to move my website to different
hardware. The [nix flake for my system
configurations](https://codeberg.org/tdback/nix-config) is tracked in a remote
repository with `git`, making configuration changes a single `git pull` away.

The following module defined in `modules/services/proxy/default.nix` enables
the caddy service using the `caddy` package found in
[nixpkgs](https://search.nixos.org/packages?channel=24.11&query=caddy),
and opens up both TCP ports 80 and 443 to accept inbound HTTP/S traffic.
```nix
{ pkgs, ... }:
{
  services.caddy = {
    enable = true;
    package = pkgs.caddy;
  };

  networking.firewall.allowTCPPorts = [ 80 443 ];
}
```

Then, in a separate module defined in `modules/services/web/default.nix`, I've
created a caddy virtual host entry for my domain name. By pairing the
`file_server` and `root` directives together in caddy, I can spin up a web
server and host the content found in `/var/www/tdback.net/` on the NixOS
server. I've also enabled both gzip and zstd support for compressing web server
responses.

```nix
{ ... }:
{
  services.caddy.virtualHosts = {
    "tdback.net".extraConfig = ''
      root * /var/www/tdback.net/
      encode zstd gzip
      file_server
    '';
  };
}
```

The server is made publicly accessible using [IPv6rs](https://ipv6.rs), which
is a wonderful service I plan to cover in future blog posts. A few DNS host A
and AAAA records are required to properly resolve queries for
https://tdback.net to my web server's IPv6 address (including requests made to
the server using IPv4!) but that's pretty much it in regards to the server
configuration.

## Writing and managing content
The following is a nix flake I've written to create a development environment
on my desktop for managing the content and generation of my website.

```nix
{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { ... }@inputs:
    inputs.flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import inputs.nixpkgs { inherit system; };
      in
      {
        devShells.default = pkgs.mkShell {
          buildInputs = with pkgs; [
            hugo
          ];

          shellHook = ''
            SITE="$HOME/projects/tdback.net"

            new-post() {
              hugo new "posts/$1/index.md"
              $EDITOR "$SITE/content/posts/$1/index.md"
            }

            del-post() {
              POST="$SITE/content/posts/$1"
              [ -d $POST ] && rm -r $POST
            }
          '';
        };
      });
}
```

When I run the command `nix develop` in my terminal, nix automatically creates
a new shell environment, pulls down the `hugo` command from the specific
revision of nixpkgs found in `flake.lock`, and defines the functions specified
in the `shellHook` attribute.

By storing this flake and my website's source code in a git repository, I can
clone the repo down to an entirely separate machine - for instance my laptop -
and have an entirely reproducible shell environment for working on my website.

I also have the added bonus of being able to completely blow away the temporary
shell environment when I exit out of the terminal or type `C-d` (the same as
`exit`). This means that `hugo` and any functions or environment variables
defined in the `shellHook` attribute are *only available when I'm in the
temporary shell environment*, thus reducing the clutter of programs, their
dependencies, environment variables, and function definitions.

## Deployment of the site
When I make a change to the website, the entire site can be regenerated and
deployed to the NixOS server by running the following one-liner:

```bash
hugo && rsync -avz --delete public/ hive:/var/www/tdback.net/
```

I've placed this command in a shell script to make deployments as simple as
typing `./deploy.sh`. This results in near-zero downtime between changes: a
simple refresh of the page on a client's device will load the newest version of
the site.

Happy hacking!