Luke Vuksta

A New Website!

Hello, and welcome to the site! After owning this domain for a number of years, I have finally decided to put something here other than email and matrix servers.

Tech choices

I wanted two things - simple updates of my site and easy deployments. I am a big fan of Nix, and broadly tend to use it to manage builds for all of my projects these days, plus I already have a NixOS server running that is easy to deploy Nix flakes to. That solves builds and deployments, but what about site generation? After some research, I landed on Zola - a single binary static site generator that supports everything I want, and allows for hot reloading during development.

Zola Theme

Zola supports theming via simply pulling in a theme. I chose to use prairie.

Applying the Theme

The usual recommendation is to clone a git repository to the themes directory, but I wanted to see if I could manage the theme's version via the flake.lock lockfile. Here is my solution to this:

{
  description = "Personal site for luke.vuksta.com";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";

    flake-parts.url = "github:hercules-ci/flake-parts";

    zola-theme = {
      url = "github:jbutterwick/prairie";
      flake = false;
    };
  };

  outputs =
    inputs@{ flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } {
      systems = [
        "x86_64-linux"
        "aarch64-linux"
      ];

      perSystem =
        {
          config,
          self',
          inputs',
          pkgs,
          system,
          ...
        }:
        let
          static-site-source = pkgs.symlinkJoin {
            name = "static-site-source";
            paths = [
              ./source
              (pkgs.runCommand "theme" { } ''
                mkdir -p $out/themes
                ln -s ${inputs.zola-theme} $out/themes/prairie
              '')
            ];
          };

          static-site = pkgs.stdenv.mkDerivation {
            name = "static-site";
            src = static-site-source;
            nativeBuildInputs = [ pkgs.zola ];
            buildPhase = ''
              tmp=$(mktemp -d)
              cp -rL ./ $tmp
              chmod -R u+w $tmp
              cd $tmp
              zola build --output-dir $out
            '';
            dontInstall = true;
          };
        in
        {
          packages = {
            inherit static-site-source static-site;
          };

          apps = {
            zola-serve = {
              type = "app";
              program = toString (
                pkgs.writeShellScript "zola-serve" ''
                  if [ ! -f "$PWD/flake.nix" ]; then
                    echo "error: must be run from the flake root"
                    exit 1
                  fi

                  theme_link="$PWD/source/themes/prairie"
                  tmp=$(mktemp -d)
                  trap "rm -r $theme_link $tmp" EXIT

                  cp -rL ${inputs.zola-theme} $theme_link
                  chmod -R u+w $theme_link

                  ${pkgs.zola}/bin/zola --root "$PWD/source" serve --output-dir $tmp --force
                ''
              );
            };
          };

          devShells.default = pkgs.mkShell {
            buildInputs = with pkgs; [
              zola
            ];
          };
        };
    };
}

The ideas here are as follows:

  • Expose static-site-source such that the source nix creates can be inspected in the flake results directory by simply running nix build .#static-site-source.
  • Expose static-site such that flake outputs can easily be used on a NixOS machine.
  • Create a zola-zerve application such that simply running nix run .#zola-serve -L will serve the webpage for development with hot reloading, retrieving the versioned theme through Nix instead of cloning it.

This makes it as easy as doing the following on my server to host the site:

...
      virtualHosts."${name-domain}" = {
        enableACME = true;
        forceSSL = true;
        listen = [
          {
            addr = primary_ipv4;
            port = 80;
            ssl = false;
          }
          {
            addr = primary_ipv4;
            port = 443;
            ssl = true;
          }
          {
            addr = "[${primary_ipv6}]";
            port = 80;
            ssl = false;
          }
          {
            addr = "[${primary_ipv6}]";
            port = 443;
            ssl = true;
          }
        ];

        locations."/" = {
          root = "${inputs.luke-static-site.packages.x86_64-linux.static-site}";
          tryFiles = "$uri $uri/ /index.html";
        };
      };
...

And to update the site, all I need to do is push changes to my git repository, run nix flake update luke-static-site on my server, and rebuild!