about summary refs log tree commit diff
path: root/configurations
diff options
context:
space:
mode:
authorAzat Bahawi <azat@bahawi.net>2024-05-01 03:36:55 +0300
committerAzat Bahawi <azat@bahawi.net>2024-05-01 03:36:55 +0300
commit9a20404924fda2587ce4f9769f75369799f34643 (patch)
treea953941a22d6c031e67b267e35a11db72bdd25e3 /configurations
parent2024-04-29 (diff)
2024-05-01
Diffstat (limited to 'configurations')
-rw-r--r--configurations/default.nix96
-rw-r--r--configurations/eonwe/default.nix312
-rw-r--r--configurations/iso/default.nix26
-rw-r--r--configurations/manwe/default.nix76
-rw-r--r--configurations/manwe/mailserver/default.nix113
-rw-r--r--configurations/manwe/webserver.nix109
-rw-r--r--configurations/melian/default.nix106
-rw-r--r--configurations/test-headful/default.nix20
-rw-r--r--configurations/test-headless/default.nix14
-rw-r--r--configurations/varda/default.nix62
-rw-r--r--configurations/yavanna/default.nix32
11 files changed, 966 insertions, 0 deletions
diff --git a/configurations/default.nix b/configurations/default.nix
new file mode 100644
index 0000000..1c1bda0
--- /dev/null
+++ b/configurations/default.nix
@@ -0,0 +1,96 @@
+inputs:
+with inputs.self.lib;
+let
+  mkConfiguration =
+    name:
+    {
+      modules ? [ ],
+      configuration ? ./${name},
+      this ? my.configurations.${name},
+    }:
+    nameValuePair name (nixosSystem {
+      inherit (this) system;
+      modules =
+        modules
+        ++ attrValues inputs.self.nixosModules
+        ++ attrValues inputs.nix-topology.nixosModules
+        ++ optional (configuration != null) (import configuration);
+      specialArgs = {
+        inherit inputs this;
+        inherit (inputs.self) lib;
+      };
+    });
+in
+mapAttrs' mkConfiguration (
+  let
+    mkTest = this: {
+      modules = with inputs; [
+        "${nixpkgs}/nixos/modules/profiles/qemu-guest.nix"
+        nixpkgs.nixosModules.notDetected
+      ];
+      inherit this;
+    };
+  in
+  {
+    test-headless = mkTest {
+      hostname = "test-headless";
+      system = "x86_64-linux";
+      isHeadless = true;
+      isHeadful = false;
+    };
+
+    test-headful = mkTest {
+      hostname = "test-headful";
+      system = "x86_64-linux";
+      isHeadless = false;
+      isHeadful = true;
+    };
+
+    iso = {
+      this = {
+        hostname = "iso";
+        system = "x86_64-linux";
+        isHeadless = false;
+        isHeadful = false;
+      };
+      modules = [
+        "${inputs.nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix"
+      ];
+    };
+
+    eonwe.modules = with inputs; [
+      nixos-hardware.nixosModules.common-cpu-amd
+      nixos-hardware.nixosModules.common-cpu-amd-pstate
+      nixos-hardware.nixosModules.common-gpu-amd
+      nixos-hardware.nixosModules.common-pc-ssd
+      nixpkgs.nixosModules.notDetected
+    ];
+
+    melian.modules = with inputs; [
+      nixos-hardware.nixosModules.common-pc-laptop-ssd
+      nixos-hardware.nixosModules.lenovo-thinkpad-t480
+      nixpkgs.nixosModules.notDetected
+    ];
+
+    manwe.modules = with inputs; [
+      "${nixpkgs}/nixos/modules/profiles/qemu-guest.nix"
+      nixos-hardware.nixosModules.common-cpu-amd
+      nixos-hardware.nixosModules.common-pc-ssd
+      nixpkgs.nixosModules.notDetected
+    ];
+
+    varda.modules = with inputs; [
+      "${nixpkgs}/nixos/modules/profiles/qemu-guest.nix"
+      nixos-hardware.nixosModules.common-cpu-amd
+      nixos-hardware.nixosModules.common-pc-ssd
+      nixpkgs.nixosModules.notDetected
+    ];
+
+    yavanna.modules = with inputs; [
+      "${nixpkgs}/nixos/modules/profiles/qemu-guest.nix"
+      nixos-hardware.nixosModules.common-cpu-intel
+      nixos-hardware.nixosModules.common-pc-hdd
+      nixpkgs.nixosModules.notDetected
+    ];
+  }
+)
diff --git a/configurations/eonwe/default.nix b/configurations/eonwe/default.nix
new file mode 100644
index 0000000..1904cdb
--- /dev/null
+++ b/configurations/eonwe/default.nix
@@ -0,0 +1,312 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+with lib;
+{
+  imports = attrValues (modulesIn ./.);
+
+  nixfiles.modules = {
+    ark.enable = true;
+
+    wireguard.client.enable = true;
+
+    syncthing.enable = true;
+
+    openssh.server.enable = true;
+
+    android.enable = true;
+    beets.enable = true;
+    bluetooth.enable = true;
+    games = {
+      lutris.enable = true;
+      minecraft.client.enable = true;
+      steam.enable = true;
+      steam-run.quirks.blackIsleStudios = true;
+    };
+    libvirtd.enable = true;
+    incus.enable = true;
+    mpd.enable = true;
+    qutebrowser.enable = true;
+  };
+
+  hm = {
+    home.packages = with pkgs; [
+      anki
+      gzdoom
+      iaito
+      kdenlive
+      krita
+      obs-studio
+      openmw
+      openttd
+      qbittorrent
+      qolibri
+      qzdl
+      radeontop
+      vcmi
+      vesktop
+      vial
+      wacomtablet
+      xonotic
+    ];
+
+    programs = {
+      beets.settings.directory = mkForce "/mnt/udata/music";
+
+      mpv = {
+        profiles =
+          let
+            mapShaders = shaders: map (args: toString (pkgs.fetchurl args)) shaders;
+            cfl-prediction = mapShaders [
+              {
+                url = "https://raw.githubusercontent.com/Artoriuz/glsl-chroma-from-luma-prediction/471c65dd3915d39e7ef69957ab63e006125fbb88/CfL_Prediction.glsl";
+                sha256 = "sha256-Mgb1KqF1EPPzR3SCVr9S4XzVmZkYEEFIHSp59RZ9wq8=";
+              }
+            ];
+            ravu-lite-ar-r4 = mapShaders [
+              {
+                url = "https://raw.githubusercontent.com/bjin/mpv-prescalers/b3f0a59d68f33b7162051ea5970a5169558f0ea2/compute/ravu-lite-ar-r4.hook";
+                sha256 = "sha256-gyBAv/Sf75CobVUugeTOhy54B9z8iIoJSJgnLopfMsY=";
+              }
+            ];
+            ssimdownscaler = mapShaders [
+              {
+                url = "https://gist.githubusercontent.com/igv/36508af3ffc84410fe39761d6969be10/raw/575d13567bbe3caa778310bd3b2a4c516c445039/SSimDownscaler.glsl";
+                sha256 = "sha256-AEq2wv/Nxo9g6Y5e4I9aIin0plTcMqBG43FuOxbnR1w=";
+              }
+            ];
+          in
+          {
+            # TODO Profile conditionals on width are not working.
+            "qhd-downscale" = {
+              dscale = "lanczos";
+              linear-downscaling = false;
+              glsl-shaders-append = ssimdownscaler;
+            };
+
+            "qhd-upscale" = {
+              glsl-shaders-append = cfl-prediction ++ ravu-lite-ar-r4;
+            };
+          };
+
+        config = {
+          profile = "gpu-hq";
+          vo = "gpu-next";
+          gpu-api = "vulkan";
+          hwdec = "auto";
+
+          deband = true;
+          deband-iterations = 4;
+          deband-threshold = 35;
+          deband-range = 16;
+          deband-grain = 5;
+
+          temporal-dither = true;
+          dither-depth = "auto";
+          dither = "fruit";
+
+          interpolation = true;
+          video-sync = "display-resample";
+          tscale = "oversample";
+
+          target-prim = "auto";
+          target-trc = "auto";
+          vf = "format=colorlevels=full:colormatrix=auto";
+          video-output-levels = "full";
+
+          glsl-shaders-append = map (text: toString (pkgs.writeText "shader.hook" text)) [
+            ''
+              //!HOOK LUMA
+              //!BIND HOOKED
+              #define STRENGTH 48.0
+              float mod289(float x)  { return x - floor(x / 289.0) * 289.0; }
+              float permute(float x) { return mod289((34.0*x + 1.0) * x); }
+              float rand(float x)    { return fract(x / 41.0); }
+              vec4 hook()  {
+                  vec3 _m = vec3(HOOKED_pos, 1.0) + vec3(1.0);
+                  float h = permute(permute(permute(_m.x)+_m.y)+_m.z);
+                  vec4 noise;
+                  noise.x = rand(h);
+                  return HOOKED_tex(HOOKED_pos) + vec4(STRENGTH/8192.0) * (noise - 0.5);
+              }
+            ''
+            ''
+              //!HOOK CHROMA
+              //!BIND HOOKED
+              #define STRENGTH 48.0
+              float mod289(float x)  { return x - floor(x / 289.0) * 289.0; }
+              float permute(float x) { return mod289((34.0*x + 1.0) * x); }
+              float rand(float x)    { return fract(x / 41.0); }
+              vec4 hook()  {
+                  vec3 _m = vec3(HOOKED_pos, 0.5) + vec3(1.0);
+                  float h = permute(permute(permute(_m.x)+_m.y)+_m.z);
+                  vec4 noise;
+                  noise.x = rand(h); h = permute(h);
+                  noise.y = rand(h);
+                  return HOOKED_tex(HOOKED_pos) + vec4(STRENGTH/8192.0) * (noise - 0.5);
+              }
+            ''
+          ];
+        };
+      };
+    };
+
+    services = {
+      mpd.musicDirectory = mkForce "/mnt/udata/music";
+
+      xsettingsd.settings."Xft/DPI" = "93";
+    };
+  };
+
+  services = {
+    smartd = {
+      enable = true;
+      notifications.mail = {
+        enable = true;
+        sender = "admin+smartd@${my.domain.shire}";
+        recipient = "admin+smartd@${my.domain.shire}";
+      };
+    };
+
+    openssh.settings = {
+      KbdInteractiveAuthentication = mkForce true;
+      PasswordAuthentication = mkForce true;
+    };
+
+    udev.packages = with pkgs; [ vial ];
+
+    xserver.wacom.enable = true;
+  };
+
+  # Usually stuff that is going to be compiled on this machine is going to have
+  # parallelisation support enabled, so we will make sure that all cores are
+  # utilised and limit the job queue to one.
+  nix.settings = {
+    max-jobs = 1;
+    cores = 32;
+  };
+
+  # Required[1] for using ZFS kernel modules with "unsupported" kernels.
+  #
+  # [1]: https://github.com/NixOS/nixpkgs/pull/121113#issuecomment-830003344
+  # [1]: https://github.com/NixOS/nixpkgs/pull/230498#issuecomment-1551328615
+  nixpkgs.config.allowBroken = true;
+
+  boot = {
+    kernelPackages = pkgs.linuxPackages_xanmod_latest;
+
+    kernelParams = [
+      # Silence benign MCE errors:
+      # ```
+      # mce: [Hardware Error]: CPU 1: Machine Check: 0 Bank 29: ffffffffffffffff
+      # mce: [Hardware Error]: TSC 0 MISC ff1fffffffffffff SYND ffffffffffffffff IPID ffffffffffffffff
+      # mce: [Hardware Error]: PROCESSOR 2:a60f12 TIME 1669988017 SOCKET 0 APIC 2 microcode a601201
+      # ```
+      "mce=nobootlog"
+      # This disables[1] User Mode Instruction Protection (UMIP)[2]. This is
+      # required for some games to run via Wine.
+      #
+      # [1]: https://docs.kernel.org/x86/cpuinfo.html
+      # [2]: https://en.wikichip.org/wiki/x86/umip
+      "clearcpuid=514"
+    ];
+
+    # https://wiki.archlinux.org/title/improving_performance#Watchdogs
+    blacklistedKernelModules = [ "sp5100_tco" ];
+
+    # The boot drive is Samsung SSD 980 PRO 2TB.
+    initrd.kernelModules = [ "nvme" ];
+
+    # These pools were configured manually with a specific mountpoint.
+    zfs.extraPools = [
+      "udata"
+      "vdata"
+    ];
+  };
+
+  # Filesystem creation:
+  # ```
+  # mkfs.vfat -F 32 -l nixos-boot /dev/nvmeXnYpZ
+  #
+  # zpool create
+  # -o ashift=12
+  # -o autotrim=on
+  # -O acltype=posixacl
+  # -O xattr=sa
+  # -O compression=zstd
+  # -O mountpoint=none
+  # nixos
+  # /dev/nvmeXnYpZ
+  #
+  # zfs create
+  # nixos/root
+  #
+  # zfs create
+  # -o encryption=aes-256-gcm
+  # -o keyformat=passphrase
+  # -o mountpoint=legacy
+  # nixos/root/ark
+  #
+  # zfs create
+  # -o mountpoint=legacy
+  # nixos/root/nix
+  # ```
+  #
+  # physical structure (backside):
+  # [ 1 ] [ 2 ] [ 3 ]
+  # 1: disk/by-id/ata-WDC_WD20SPZX-22UA7T0_WD-WXP2E3163YW6
+  # 2: disk/by-id/ata-WDC_WD20SPZX-22UA7T0_WD-WXN2E312R5HP
+  # 3: disk/by-id/ata-WDC_WD20SPZX-22UA7T0_WD-WXP2E311E6P2
+  #
+  # physical structure (mobo M.2):
+  # [ 1 ]
+  # [ 2 ]
+  # 1: disk/by-id/nvme-Samsung_SSD_980_PRO_2TB_S69ENF0R872526A
+  # 2: disk/by-id/nvme-Samsung_SSD_980_PRO_2TB_S69ENX0T807723X
+  fileSystems = {
+    "/" = {
+      device = "none";
+      fsType = "tmpfs";
+      options = [
+        "size=8G"
+        "mode=755"
+      ];
+    };
+
+    "/boot" = {
+      device = "/dev/disk/by-uuid/1363-02E6";
+      fsType = "vfat";
+    };
+
+    "/nix" = {
+      device = "nixos/root/nix";
+      fsType = "zfs";
+      options = [ "noatime" ];
+    };
+
+    ${config.ark.path} = {
+      device = "nixos/root/ark";
+      fsType = "zfs";
+      neededForBoot = true; # Required by impermanence.
+    };
+
+    # Required[1] when using impermanence with agenix. Filesystem itself is
+    # defined as an `ark.directory` in `nixos/common/users.nix`.
+    #
+    # [1]: https://github.com/ryantm/agenix/issues/45#issuecomment-847852593
+    # [1]: https://github.com/nix-community/impermanence/issues/22
+    # [1]: https://github.com/NixOS/nixpkgs/pull/86967#pullrequestreview-667929259
+    "/home/${my.username}" = {
+      depends = [ config.ark.path ];
+      neededForBoot = true;
+    };
+  };
+
+  # No swap space is declared here because the system already has 128Gb of RAM.
+  # I've only manage to hit around 100Gb mark when running large
+  # computations/compiling something big. Pretty sure that a hefty chunk of it
+  # was just cache and it wouldn't make me get to OOM situations.
+}
diff --git a/configurations/iso/default.nix b/configurations/iso/default.nix
new file mode 100644
index 0000000..7277e88
--- /dev/null
+++ b/configurations/iso/default.nix
@@ -0,0 +1,26 @@
+{ lib, ... }:
+with lib;
+{
+  secrets = mkForce { };
+
+  nixfiles.modules = {
+    common.networking.onlyDefault = true;
+    git.client.enable = true;
+    gnupg.enable = true;
+    openssh = {
+      client.enable = true;
+      server = {
+        enable = true;
+        port = 22;
+      };
+    };
+  };
+
+  hm.programs.git.signing.signByDefault = mkForce false;
+
+  programs.mtr.enable = true;
+
+  services.getty.autologinUser = mkForce my.username;
+
+  nixpkgs.config.allowBroken = true;
+}
diff --git a/configurations/manwe/default.nix b/configurations/manwe/default.nix
new file mode 100644
index 0000000..3707440
--- /dev/null
+++ b/configurations/manwe/default.nix
@@ -0,0 +1,76 @@
+{ config, lib, ... }:
+with lib;
+{
+  imports = attrValues (modulesIn ./.);
+
+  nixfiles.modules = {
+    nsd = {
+      enable = true;
+      fqdn = "ns1.${config.networking.domain}";
+    };
+    unbound.enable = true;
+
+    wireguard.server.enable = true;
+
+    acme.enable = true;
+
+    monitoring.enable = true;
+
+    postgresql.enable = true;
+    clickhouse.enable = true;
+
+    git.server = {
+      enable = true;
+      domain = "git.${my.domain.azahi}";
+    };
+
+    matrix.dendrite = {
+      enable = true;
+      domain = my.domain.azahi;
+    };
+    murmur.enable = true;
+    radicale.enable = true;
+    rss-bridge.enable = true;
+    shadowsocks.enable = true;
+    soju = {
+      enable = true;
+      domain = my.domain.azahi;
+    };
+    vaultwarden.enable = true;
+    ntfy.enable = true;
+    plausible.enable = true;
+  };
+
+  boot = {
+    loader.grub = {
+      enable = true;
+      device = "/dev/sda";
+    };
+
+    initrd.availableKernelModules = [
+      "virtio_pci"
+      "virtio_scsi"
+    ];
+  };
+
+  fileSystems = {
+    "/" = {
+      device = "/dev/sda2";
+      fsType = "xfs";
+      options = [ "noatime" ];
+    };
+
+    "/boot" = {
+      device = "/dev/sda1";
+      fsType = "xfs";
+      options = [ "noatime" ];
+    };
+  };
+
+  swapDevices = [ { device = "/dev/sda3"; } ];
+
+  zramSwap = {
+    enable = true;
+    memoryPercent = 25;
+  };
+}
diff --git a/configurations/manwe/mailserver/default.nix b/configurations/manwe/mailserver/default.nix
new file mode 100644
index 0000000..cc8b41d
--- /dev/null
+++ b/configurations/manwe/mailserver/default.nix
@@ -0,0 +1,113 @@
+{
+  config,
+  inputs,
+  lib,
+  ...
+}:
+with lib;
+{
+  imports = [ inputs.mailserver.nixosModule ] ++ attrValues (modulesIn ./.);
+
+  ark.directories = with config.mailserver; [
+    "/var/lib/dovecot"
+    "/var/lib/postfix"
+    config.security.dhparams.params.dovecot2.path
+    dkimKeyDirectory
+    mailDirectory
+    sieveDirectory
+  ];
+
+  secrets = with config.mailserver; {
+    dkim-key-azahi-cc = {
+      file = "${inputs.self}/secrets/dkim-key-azahi-cc";
+      path = "${dkimKeyDirectory}/${my.domain.azahi}.${dkimSelector}.key";
+      owner = config.services.opendkim.user;
+      inherit (config.services.opendkim) group;
+    };
+    dkim-key-rohan-net = {
+      file = "${inputs.self}/secrets/dkim-key-rohan-net";
+      path = "${dkimKeyDirectory}/${my.domain.rohan}.${dkimSelector}.key";
+      owner = config.services.opendkim.user;
+      inherit (config.services.opendkim) group;
+    };
+    dkim-key-gondor-net = {
+      file = "${inputs.self}/secrets/dkim-key-gondor-net";
+      path = "${dkimKeyDirectory}/${my.domain.gondor}.${dkimSelector}.key";
+      owner = config.services.opendkim.user;
+      inherit (config.services.opendkim) group;
+    };
+    dkim-key-shire-net = {
+      file = "${inputs.self}/secrets/dkim-key-shire-net";
+      path = "${dkimKeyDirectory}/${my.domain.shire}.${dkimSelector}.key";
+      owner = config.services.opendkim.user;
+      inherit (config.services.opendkim) group;
+    };
+  };
+
+  nixfiles.modules = {
+    acme.enable = true;
+    redis.enable = true;
+  };
+
+  mailserver =
+    let
+      cert = config.certs.${my.domain.shire};
+    in
+    {
+      enable = true;
+
+      # Disable potentially insecure[1] STARTTLS connections. SSL-only connections
+      # are still enabled by default.
+      #
+      # [1]: https://www.rfc-editor.org/rfc/rfc3207#section-6
+      enableImap = false;
+      enablePop3 = false;
+      enableSubmission = false;
+
+      fqdn = config.networking.domain;
+      domains = with my.domain; [
+        azahi
+        gondor
+        rohan
+        shire
+      ];
+
+      localDnsResolver = false;
+
+      certificateScheme = "manual";
+      certificateFile = "${cert.directory}/fullchain.pem";
+      keyFile = "${cert.directory}/key.pem";
+
+      lmtpSaveToDetailMailbox = "no";
+
+      redis = with config.services.redis.servers.default; {
+        address = bind;
+        inherit port;
+        password = requirePass;
+      };
+    };
+
+  services = {
+    fail2ban.jails = {
+      dovecot = {
+        enabled = true;
+        settings.mode = "aggressive";
+      };
+      postfix = {
+        enabled = true;
+        settings.mode = "aggressive";
+      };
+    };
+
+    # https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/issues/275#note_1746383655
+    dovecot2.sieve.extensions = [ "fileinto" ];
+
+    # https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/issues/241
+    redis.servers.rspamd.enable = mkForce false;
+  };
+
+  systemd.services.rspamd = {
+    requires = mkForce [ "redis-default.service" ];
+    after = mkForce [ "redis-default.service" ];
+  };
+}
diff --git a/configurations/manwe/webserver.nix b/configurations/manwe/webserver.nix
new file mode 100644
index 0000000..95a0b0b
--- /dev/null
+++ b/configurations/manwe/webserver.nix
@@ -0,0 +1,109 @@
+{
+  inputs,
+  lib,
+  libNginx,
+  libPlausible,
+  ...
+}:
+with lib;
+{
+  nixfiles.modules.nginx = {
+    enable = true;
+    virtualHosts =
+      with my.domain;
+      {
+        # TODO Start using this.
+        # "start.local" = {
+        #   root = pkgs.hiccup;
+        #   locations = {
+        #     "/".tryFiles = "$uri $uri/ /index.html";
+        #     "~* ^.+config.json$".extraConfig = let
+        #       config = pkgs.writeText "config.json" (generators.toJSON {} {
+        #         version = "2.0";
+        #         id = "default";
+        #         title = "Demo Config";
+        #         url = "./configs/config.json";
+        #         featured = [
+        #           {
+        #             name = "GitHub";
+        #             background = "/assets/card.png";
+        #             link = "https://github.com/ashwin-pc/hiccup";
+        #           }
+        #         ];
+        #         categories = [
+        #           {
+        #             title = "Category 1";
+        #             links = [
+        #               {
+        #                 name = "Link 1";
+        #                 link = "https://example.com";
+        #               }
+        #             ];
+        #           }
+        #           {
+        #             title = "Category 2";
+        #             links = [
+        #               {
+        #                 name = "Link 1";
+        #                 link = "https://example.com";
+        #               }
+        #             ];
+        #           }
+        #           {
+        #             title = "Category 3";
+        #             links = [
+        #               {
+        #                 name = "Link 1";
+        #                 link = "https://example.com";
+        #               }
+        #             ];
+        #           }
+        #           {
+        #             title = "Category 4";
+        #             links = [
+        #               {
+        #                 name = "Link 1";
+        #                 link = "https://example.com";
+        #               }
+        #             ];
+        #           }
+        #         ];
+        #       });
+        #     in ''
+        #       alias ${config};
+        #     '';
+        #   };
+        #   enableACME = false;
+        #   forceSSL = false;
+        # };
+        ${shire}.locations."/".return = "301 https://www.youtube.com/watch?v=dQw4w9WgXcQ";
+        "git.${shire}".locations."/".return = "301 https://git.${azahi}";
+        "bitwarden.${shire}".locations."/".return = "301 https://vaultwarden.${shire}";
+        ${azahi} = {
+          serverAliases = [
+            "frodo.${gondor}"
+            "frodo.${rohan}"
+          ];
+          locations."/" = {
+            root = inputs.azahi-cc;
+            extraConfig = libNginx.config.appendHead [ (libPlausible.htmlPlausibleScript { domain = azahi; }) ];
+          };
+        };
+      }
+      // (
+        let
+          frodo = "301 https://frodo.";
+        in
+        {
+          ${gondor}.locations."/".return = concatStrings [
+            frodo
+            gondor
+          ];
+          ${rohan}.locations."/".return = concatStrings [
+            frodo
+            rohan
+          ];
+        }
+      );
+  };
+}
diff --git a/configurations/melian/default.nix b/configurations/melian/default.nix
new file mode 100644
index 0000000..0805b4a
--- /dev/null
+++ b/configurations/melian/default.nix
@@ -0,0 +1,106 @@
+{ lib, pkgs, ... }:
+with lib;
+{
+  nixfiles.modules = {
+    wireguard.client.enable = true;
+
+    syncthing.enable = true;
+
+    bluetooth.enable = true;
+
+    throttled.enable = true;
+
+    android.enable = true;
+  };
+
+  hardware.trackpoint = {
+    enable = true;
+    speed = 500;
+    sensitivity = 250;
+  };
+
+  powerManagement =
+    let
+      modprobe = getExe' pkgs.kmod "modprobe";
+    in
+    {
+      enable = true;
+
+      # This fixes an issue with not being able to suspend or wake up from
+      # suspend due to a kernel bug[1] which is still not fixed.
+      #
+      # I guess this can also be fixed differently[2], which does look a lot nicer
+      # but I'm just too lazy.
+      #
+      # [1]: https://bbs.archlinux.org/viewtopic.php?id=270964
+      # [1]: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/522998
+      # [1]: https://bugs.launchpad.net/ubuntu/+source/pm-utils/+bug/562484/comments/3
+      # [1]: https://gist.github.com/ioggstream/8f380d398aef989ac455b93b92d42048
+      # [2]: https://linrunner.de/tlp/settings/runtimepm.html
+      powerDownCommands = "${modprobe} -r xhci_pci";
+      powerUpCommands = "${modprobe} xhci_pci";
+    };
+
+  services = {
+    thinkfan = {
+      enable = true;
+      settings = {
+        sensors = [
+          {
+            hwmon = "/sys/class/hwmon";
+            name = "coretemp";
+            indices = [ 1 ];
+          }
+        ];
+        fans = [ { tpacpi = "/proc/acpi/ibm/fan"; } ];
+        levels = [
+          [
+            "level auto"
+            0
+            50
+          ]
+          [
+            "level disengaged"
+            50
+            32767
+          ] # This could annoy some people but IDGAF.
+        ];
+      };
+    };
+
+    fwupd.enable = true;
+  };
+
+  boot.initrd.luks.devices."root" = {
+    device = "/dev/disk/by-uuid/c1b46f24-eec0-47d2-a142-75ddfd7bb218";
+    allowDiscards = true;
+    bypassWorkqueues = true;
+  };
+
+  fileSystems = {
+    "/" = {
+      device = "/dev/disk/by-uuid/bb8b09dc-cc67-47e5-8280-532b17a9e62a";
+      fsType = "xfs";
+      options = [ "noatime" ];
+    };
+
+    "/boot" = {
+      device = "/dev/disk/by-uuid/1083-C8A0";
+      fsType = "vfat";
+    };
+  };
+
+  # NOTE This makes hibernation pretty much impossible because the partition is
+  # encrypted.
+  swapDevices = [
+    {
+      device = "/swapfile";
+      size = 8 * 1024;
+    }
+  ];
+
+  zramSwap = {
+    enable = true;
+    memoryPercent = 25;
+  };
+}
diff --git a/configurations/test-headful/default.nix b/configurations/test-headful/default.nix
new file mode 100644
index 0000000..f1da389
--- /dev/null
+++ b/configurations/test-headful/default.nix
@@ -0,0 +1,20 @@
+{ lib, ... }:
+with lib;
+{
+  nixfiles.modules = {
+    dwm.enable = false;
+    kde.enable = true;
+    xmonad.enable = false;
+  };
+
+  boot.loader.systemd-boot.enable = true;
+  fileSystems."/".device = "/dev/null";
+
+  documentation = {
+    enable = mkForce false;
+    man = {
+      enable = mkForce false;
+      man-db.enable = mkForce false;
+    };
+  };
+}
diff --git a/configurations/test-headless/default.nix b/configurations/test-headless/default.nix
new file mode 100644
index 0000000..ef3d223
--- /dev/null
+++ b/configurations/test-headless/default.nix
@@ -0,0 +1,14 @@
+{ lib, ... }:
+with lib;
+{
+  nixfiles.modules = {
+    endlessh-go.enable = mkForce false;
+    node-exporter.enable = mkForce false;
+    promtail.enable = mkForce false;
+  };
+
+  boot.loader.systemd-boot.enable = true;
+  fileSystems."/".device = "/dev/null";
+
+  documentation.enable = mkForce false;
+}
diff --git a/configurations/varda/default.nix b/configurations/varda/default.nix
new file mode 100644
index 0000000..c8ecef2
--- /dev/null
+++ b/configurations/varda/default.nix
@@ -0,0 +1,62 @@
+{ lib, ... }:
+with lib;
+{
+  imports = attrValues (modulesIn ./.);
+
+  nixfiles.modules = {
+    wireguard.client.enable = true;
+
+    acme.enable = true;
+
+    k3s.enable = true;
+  };
+
+  boot = {
+    loader = {
+      efi.canTouchEfiVariables = true;
+
+      systemd-boot = {
+        enable = true;
+        configurationLimit = 10;
+      };
+    };
+
+    initrd.availableKernelModules = [
+      "virtio_pci"
+      "virtio_scsi"
+    ];
+
+    # https://github.com/NixOS/nixpkgs/issues/89025
+    # https://forum.netcup.de/administration-of-a-server-vserver/vserver-server-kvm-server/p67571-icmpv6-ra-ndisc-router-discovery-failed-to-add-default-route/#post67571
+    # https://superuser.com/questions/33196/how-to-disable-autoconfiguration-on-ipv6-in-linux
+    kernel.sysctl = {
+      "net.ipv6.conf.all.autoconf" = 0;
+      "net.ipv6.conf.all.accept_ra" = 0;
+    };
+  };
+
+  fileSystems = {
+    "/" = {
+      device = "/dev/disk/by-uuid/b07e8273-915a-424c-8c55-cdc2bd482f49";
+      fsType = "xfs";
+      options = [ "noatime" ];
+    };
+
+    "/boot" = {
+      device = "/dev/disk/by-uuid/03FD-B6C0";
+      fsType = "vfat";
+    };
+  };
+
+  swapDevices = [
+    {
+      device = "/swapfile";
+      size = 4 * 1024;
+    }
+  ];
+
+  zramSwap = {
+    enable = true;
+    memoryPercent = 25;
+  };
+}
diff --git a/configurations/yavanna/default.nix b/configurations/yavanna/default.nix
new file mode 100644
index 0000000..2d52f53
--- /dev/null
+++ b/configurations/yavanna/default.nix
@@ -0,0 +1,32 @@
+_: {
+  nixfiles.modules = {
+    wireguard.client.enable = true;
+
+    syncthing.enable = true;
+
+    acme.enable = true;
+
+    rtorrent.enable = true;
+    lidarr.enable = true;
+    jackett.enable = true;
+  };
+
+  boot.loader.grub = {
+    enable = true;
+    device = "/dev/sda";
+    configurationLimit = 5;
+  };
+
+  fileSystems."/" = {
+    device = "/dev/sda2";
+    fsType = "ext4";
+    options = [ "noatime" ];
+  };
+
+  swapDevices = [ { device = "/dev/sda3"; } ];
+
+  zramSwap = {
+    enable = true;
+    memoryPercent = 25;
+  };
+}

Consider giving Nix/NixOS a try! <3