My Blog // Digital Archive

Thoughts, projects and technical notes

Showing entries with tag: #nixos Show all ×

I've just updated the backup strategy for my NixOS home server, switching from a simple daily script to an hourly one. It's not quite as elegant as the Mastodon instance my friend manages—where we have ZFS snapshots every 20 minutes—but I'm happy with this solution. And I have to say, I'm liking NixOS more and more. Without AI, it would be far too complicated for me to understand, but by now I can at least read the finished Nix files. I once considered switching the server to a standard Linux distribution, but as long as it works this well...

  1. /etc/nixos: The entire NixOS configuration (all .nix files).

  2. /opt/minecraft: All worlds and data for the Minecraft server.

  3. /opt/satisfactory: Save games and configuration for the Satisfactory server.

  4. /opt/Blog: The source code and content of the blog.

  5. /opt/ui: The Mastodon UI files.

  6. /opt/audiobookshelf: The audiobooks and the associated database.

Everything ends up on S3 storage mounted via RClone.

The NixOS Configuration


{ config, pkgs, ... }:

{
  # BorgBackup configuration
  services.borgbackup.jobs.hourly = {
    # Path to the repository in the S3 mount
    repo = "/opt/S3/Backup/NixOSHomeServer_Borg";

    # No password required
    encryption.mode = "none";

    # Compression for even more space savings
    compression = "auto,zstd";

    # The paths to be backed up
    paths = [
      "/etc/nixos"
      "/opt/minecraft"
      "/opt/satisfactory"
      "/opt/Blog"
      "/opt/ui"
      "/opt/audiobookshelf"
    ];

    # Hourly execution
    startAt = "hourly";

    # Automatically initialize repository if it's missing
    doInit = true;

    # Retention rules (Pruning)
    prune.keep = {
      within = "1d"; # All snapshots from the last 24h
      daily = 7;
      weekly = 4;
      monthly = 12;
    };
  };

  # Ensure the S3 mount is ready before Borg starts
  systemd.services.borgbackup-job-hourly = {
    requires = [ "rclone-s3-mount.service" ];
    after = [ "rclone-s3-mount.service" ];
  };
}

I've set up my own blog — primarily to get to know #NixOS better. Surprisingly, it was all quite straightforward.

WriteFreely is a great fit for this: minimalist, quick to set up, and without much bloat. Perfect for just getting started and learning something along the way. The configuration is pleasantly clear. Set a few options, prepare the directory, put a reverse proxy in front — done.

This is what my current NixOS configuration for it looks like:

{ config, pkgs, ... }:

{
  services.writefreely = {
    enable = true;
    host = "blog.burningboard.org"; 
    settings = {
      server = {
        port = 8080;
        min_log_level = "debug";
      };
      app = {
        host = "https://blog.burningboard.org";
        single_user = true;
        landing = "/read";
        wf_modesty = true;
        federation = true;
        public_stats = true;
        theme = "write";
      };
    };
    stateDir = "/opt/writefreely";
  };

  # Fix for ActivityPub key generation: Federation requires openssl
  systemd.services.writefreely.path = [ pkgs.openssl ];

  # Automatic creation of the data directory with the correct permissions
  systemd.tmpfiles.rules = [
    "d /opt/writefreely 0700 writefreely writefreely -"
  ];

  services.caddy.virtualHosts."blog.burningboard.org".extraConfig = ''
    reverse_proxy 127.0.0.1:8080 {
      header_up Host {host}
      header_up X-Real-IP {remote_host}
      header_up X-Forwarded-For {remote_host}
      header_up X-Forwarded-Proto {scheme}
    }
  '';
}

That's essentially it. NixOS makes it really easy to configure such services cleanly and keep them reproducible.