home | section main page


NixOS Configuration

Table of Contents

1. Introduction

This is my NixOS configuration. It is a part of my monorepo, and this file automatically tangles to all the under the nix/ directory in my monorepo git repository. My monorepo also stores my website, as my website stores my elfeed and emacs configurations. Additionally, I want to track my emacs configuration with my Nix configuration. Having them in one repository means that my emacs configuration is pinned to my flake.

Hence, my monorepo serves a dual purpose, as do many of the files within my monorepo. They are often data files used in my configuration (i.e. emacs, elfeed, org-roam, agenda, journal, etc…) and they are webpages as well. This page is one such example of this concept.

2. Configurables

We start with some configurable variables (you can change these if you want to use this configuration yourself):

let
  # I'm ret2pop! What's your name?
  internetName = "ret2pop";
in
{
  # Name of spontaneity box
  remoteHost = "${internetName}.net";

  # Your internet name
  internetName = internetName;

  # Name of your organization
  orgHost = "nullring.xyz";

  # Hostnames of my systems
  hostnames = [
    "affinity"
    "continuity"
    "spontaneity"
    "installer"
  ];
}

3. Flake.nix

The flake is the entry point of the NixOS configuration. Here, I have a list of all the systems that I use with all the modules that they use. My NixOS configuration is heavily modularized, so that adding new configurations that add modifications is made simple. Additionally I have implemented integration tests for my systems in an automated way (it'll do integration tests for services that are enabled), with nix flake check. I have implemented also git hooks which help with CI.

and now for the main flake:

{
  description = "Emacs centric configurations for a complete networked system";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    nur.url = "github:nix-community/NUR";
    sops-nix.url = "github:Mic92/sops-nix";

    scripts.url = "github:ret2pop/scripts";
    wallpapers.url = "github:ret2pop/wallpapers";
    sounds.url = "github:ret2pop/sounds";
    deep-research.url = "github:ret2pop/ollama-deep-researcher";
    impermanence.url = "github:nix-community/impermanence";

    nix-topology = {
      url = "github:oddlama/nix-topology";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    home-manager = {
      url = "github:nix-community/home-manager/release-25.05";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    disko = {
      url = "github:nix-community/disko";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    lanzaboote = {
      url = "github:nix-community/lanzaboote/v0.4.1";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    nixos-dns = {
      url = "github:Janik-Haag/nixos-dns";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    git-hooks = {
      url = "github:cachix/git-hooks.nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = {
      self,
      nixpkgs,
      home-manager,
      nur,
      disko,
      lanzaboote,
      sops-nix,
      nix-topology,
      nixos-dns,
      deep-research,
      impermanence,
      git-hooks,
      ...
  }
    @attrs:
      let
        vars = import ./flakevars.nix;
        system = "x86_64-linux";

        pkgs = import nixpkgs { inherit system; };
        generate = nixos-dns.utils.generate nixpkgs.legacyPackages."${system}";

        dnsConfig = {
          inherit (self) nixosConfigurations;
          extraConfig = import ./dns/default.nix;
        };

        rpiCheck = hostname: (builtins.match "rpi-.*" hostname) != null;
        noRpi = builtins.filter (hostname: (! rpiCheck hostname));
        noInstaller = builtins.filter (hostname: (hostname != "installer"));
        filterHosts = noInstaller (noRpi vars.hostnames);

        mkHostModules = hostname:
          if (hostname == "installer") then ([
            (./. + "/systems/${hostname}/default.nix")
            { networking.hostName = "${hostname}"; }
            nix-topology.nixosModules.default
          ]) else (if (rpiCheck hostname) then [
            (./. + "/systems/${hostname}/default.nix")
            disko.nixosModules.disko
            home-manager.nixosModules.home-manager
            sops-nix.nixosModules.sops
            lanzaboote.nixosModules.lanzaboote
          ] else [
            {
              environment.systemPackages = with nixpkgs.lib; [
                deep-research.packages."${system}".deep-research
              ];
            }
            impermanence.nixosModules.impermanence
            nix-topology.nixosModules.default
            lanzaboote.nixosModules.lanzaboote
            disko.nixosModules.disko
            home-manager.nixosModules.home-manager
            sops-nix.nixosModules.sops
            nixos-dns.nixosModules.dns
            {
              nixpkgs.overlays = [ nur.overlays.default ];
              home-manager.extraSpecialArgs = attrs // {
                systemHostName = "${hostname}";
              };
              networking.hostName = "${hostname}";
            }
            (./. + "/systems/${hostname}/default.nix")
          ]);

        # function that generates all systems from hostnames
        mkConfigs = map (hostname:
          let
            hostSystem = if (rpiCheck hostname) then "aarch64-linux" else system;
          in
            {
              name = "${hostname}";
              value = nixpkgs.lib.nixosSystem {
                system = hostSystem;
                specialArgs = attrs // {
                  isIntegrationTest = false;
                  monorepoSelf = null;
                };
                modules = mkHostModules hostname;
              };
            });

        mkDiskoFiles = map (hostname: {
          name = "${hostname}";
          value = self.nixosConfigurations."${hostname}".config.monorepo.vars.diskoSpec;
        });

        mkBuildChecks = map (hostname: {
          name = "${hostname}-build-check";
          value = {
            enable = true;
            name = "${hostname}-vm-build";
            description = "Ensure ${hostname} can build";
            stages = [ "pre-merge-commit" ];
            entry = "${pkgs.writeShellScript "${hostname}-check" ''
#!/usr/bin/env bash
set -e
set -o pipefail
trap "echo -e '\nHook interrupted by user. Aborting merge!'; exit 1" INT TERM
echo "Running Nix integration tests..."

BRANCH=$(git branch --show-current)
if [ "$BRANCH" != "main" ]; then
  exit 0
fi
echo "Merge to main detected. Building VM for ${hostname}..."
if nix build .#nixosConfigurations.${hostname}.config.system.build.vm --no-link; then
    echo "Build succeeded."
    exit 0
else
    echo "Build failed! Aborting."
    exit 1
fi
''}";
            pass_filenames = false;
            always_run = true;
          };
        });

        hostToServices = (hostname:
          let
            super = self.nixosConfigurations."${hostname}".config;
          in
            [
              {
                serviceName = "nginx";
                enabled = super.services.nginx.enable;
              }
              {
                serviceName = "sshd";
                enabled = super.services.openssh.enable;
              }
              {
                serviceName = "git-daemon";
                enabled = super.services.gitDaemon.enable;
              }
              {
                serviceName = "tor";
                enabled = super.services.tor.enable;
              }
            ]);

        _mkServiceTestScripts = hostname: services: builtins.concatStringsSep "\n" (builtins.map (service:
          (if service.enabled then ''
${hostname}.succeed("systemctl is-active ${service.serviceName}")
'' else "")) services);

        mkServiceTestScripts = hostname: _mkServiceTestScripts hostname (hostToServices hostname);

        mkIntegrationTests = builtins.map (hostname: 
          let
            lib = nixpkgs.lib;
            hostPkgs = self.nixosConfigurations."${hostname}".pkgs;
            hardwareConfig = ./systems/${hostname}/hardware-configuration.nix;
          in
            {
              name = "integration-test-${hostname}";
              value = hostPkgs.testers.runNixOSTest {
                name = "services-test-${hostname}";
                nodes = {
                  "${hostname}" = { ... }: {
                    _module.args = attrs // { isIntegrationTest = true; };
                    imports = mkHostModules hostname ++ [
                      "${nixpkgs}/nixos/modules/misc/nixpkgs/read-only.nix"
                      {
                        nixpkgs.pkgs = lib.mkVMOverride hostPkgs;
                        nixpkgs.config = lib.mkForce {};
                        systemd.services.systemd-networkd-wait-online.enable = lib.mkForce false;
                        systemd.services.NetworkManager-wait-online.enable = lib.mkForce false;
                        nixpkgs.overlays = lib.mkForce [];
                      }
                    ];
                    disabledModules = [ 
                      ./modules/nixpkgs-options.nix
                    ]
                    ++ lib.optional (builtins.pathExists hardwareConfig) hardwareConfig;
                  };
                };
                testScript = ''
${hostname}.start()
${hostname}.wait_for_unit("default.target")
${hostname}.succeed('printf "smoke"')
${mkServiceTestScripts hostname}
'';
              };
            }
        );

        integrationTests = builtins.listToAttrs (mkIntegrationTests filterHosts);
        pre-commit-check = git-hooks.lib.${system}.run {
          src = ./.;
          hooks = builtins.listToAttrs (mkBuildChecks filterHosts) // {
            statix.enable = false;
            deadnix.enable = true;
            prevent-direct-main-commits = {
              enable = true;
              name = "Prevent direct commits to main";
              description = "Blocks commits to main unless they are merge commits";
              pass_filenames = false;
              entry = "${pkgs.writeShellScript "block-main-commits" ''
BRANCH=$(git branch --show-current)
GIT_DIR=$(git rev-parse --git-dir)
if [ "$BRANCH" = "main" ] && [ ! -f "$GIT_DIR/MERGE_HEAD" ]; then
  echo "Direct commits to 'main' are blocked."
  echo "Please commit to a feature branch and merge it into main."
  exit 1
fi
              ''}";
            };
          };
        };
      in
        {
          lib = {
            inherit mkHostModules;
          };

          checks."${system}" = integrationTests // {
            inherit pre-commit-check;
          };

          nixosConfigurations = builtins.listToAttrs (mkConfigs vars.hostnames);
          evalDisko = builtins.listToAttrs (mkDiskoFiles (noInstaller vars.hostnames));

          topology."${system}" = import nix-topology {
            pkgs = import nixpkgs {
              inherit system;
              overlays = [ nix-topology.overlays.default ];
            };
            modules = [
              ./topology/default.nix
              { nixosConfigurations = self.nixosConfigurations; }
            ];
          };

          devShell."${system}" = with pkgs; mkShell {
            buildInputs = [
              fira-code
              statix
              deadnix
              (python3.withPackages (ps: with ps; [
                octodns
                octodns-providers.cloudflare
                octodns-providers.bind
              ]))
            ];
            shellHook = ''
${pre-commit-check.shellHook}
git config branch.main.mergeoptions "--no-ff"

CURRENT_HOST="$(hostname)"

TARGET_USER_RAW=$(nix eval .#nixosConfigurations."$CURRENT_HOST".config.home-manager.users --apply "u: builtins.head (builtins.attrNames u)" --raw 2>/dev/null)

TARGET_USER=$(echo "$TARGET_USER_RAW" | xargs)
SOPS_BASE=$(nix eval .#nixosConfigurations."$CURRENT_HOST".config.home-manager.users."$TARGET_USER".sops.defaultSymlinkPath --raw 2>/dev/null)

if [ -n "$SOPS_BASE" ] && [ -f "$SOPS_BASE/cloudflare-dns" ]; then
  export CLOUDFLARE_TOKEN="$(cat "$SOPS_BASE/cloudflare-dns" | tr -d '\n')"
  echo "Authenticated via sops-nix for host: $CURRENT_HOST"
else
  echo "Could not resolve sops path for $CURRENT_HOST or secret is missing. Set CLOUDFLARE_TOKEN manually."
fi

alias update-dns="octodns-sync --config-file ${self.packages."${system}".octodns} --doit --force"
alias fake-update-dns="octodns-sync --config-file ${self.packages."${system}".octodns} --force "
alias gprune='git branch --merged | grep -v -E "^\*|main|master|dev" | xargs -r git branch -d'
'';
          };

          packages."${system}" = {
            zoneFiles = generate.zoneFiles dnsConfig;
            octodns = generate.octodnsConfig {
              inherit dnsConfig;

              config = {
                providers = {
                  cloudflare = {
                    class = "octodns_cloudflare.CloudflareProvider";
                    token = "env/CLOUDFLARE_TOKEN";
                  };
                  config = {
                    check_origin = false;
                  };
                };
              };
              zones = {
                "${vars.remoteHost}." = nixos-dns.utils.octodns.generateZoneAttrs [ "cloudflare" ];
                "${vars.orgHost}." = nixos-dns.utils.octodns.generateZoneAttrs [ "cloudflare" ];
              };
            };
          };
        };
}

Note that the configurations are automatically generated with he mkConfigs function, and the final disko output is automatically generated with mkDiskoFiles.

4. Sops Configuration

In order to use the sops configuration, you must change the age public key to the one that you own:

keys:
  - &primary age165ul43e8rc0qwzz2f2q9cw02psm2mkudsrwavq2e0pxs280p64yqy2z0dr
  - &vps age1acpuyy2qnduyxzwvusd8urr6a78e3f37ylhvh2pngyqytf5r8ans5vkest
creation_rules:
  - path_regex: secrets/secrets.yaml$
    key_groups:
      - age:
        - *primary

  - path_regex: secrets/vps_secrets.yaml$
    key_groups:
      - age:
        - *vps

  - path_regex: secrets/common_secrets.yaml$
    key_groups:
      - age:
        - *primary
        - *vps

also note that you will have to write your own secrets.yaml file, with an entry called mail, which is used for the imaps and smtps password.

5. Nix DNS

{
  defaultTTL = 120;
}

6. Nix Topology

Nix Topology generates a nice graph of all my hosts. You can view this graph by running nix build .#topology.x86_64-linux.config.output.

{ config, ... }:
let
  inherit
    (config.lib.topology);
in
{
  nodes = {
    spontaneity = {
      interfaces.wan.network = "remote";
    };
    installer = {
      interfaces.lan.network = "home";
    };
    affinity = {
      interfaces.lan = {
        network = "home";
        physicalConnections = [
          {
            node = "spontaneity";
            interface = "wan";
          }
          {
            node = "installer";
            interface = "lan";
          }
        ];
      };
    };
    continuity = {
      interfaces.lan = {
        network = "home";
        physicalConnections = [
          {
            node = "spontaneity";
            interface = "wan";
          }
          {
            node = "affinity";
            interface = "lan";
          }
        ];
      };
    };
  };
  networks = {
    home = {
      name = "Home Network";
      cidrv4 = "192.168.1.1/24";
    };
    remote = {
      name = "Remote Network";
      cidrv4 = "144.202.27.169/32";
    };
  };
}

7. Modules

7.1. Vars

Variables used for regular configuration in your system default.nix file. The options are largely self-documenting.

{ config, lib, ... }:
let
  vars = import ../flakevars.nix;
in
{
  options.monorepo.vars = {
    device = lib.mkOption {
      type = lib.types.str;
      default = "/dev/sda";
      example = "/dev/nvme0n1";
      description = "device that NixOS is installed to";
    };

    internetName = lib.mkOption {
      type = lib.types.str;
      default = "${vars.internetName}";
      example = "myinternetname";
      description = "Internet name to be used for internet usernames";
    };

    sshKey = lib.mkOption {
      type = lib.types.str;
      default = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICts6+MQiMwpA+DfFQxjIN214Jn0pCw/2BDvOzPhR/H2 preston@continuity-dell";
      example = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICts6+MQiMwpA+DfFQxjIN214Jn0pCw/2BDvOzPhR/H2 preston@continuity-dell";
      description = "Admin public key for managing multiple configurations";
    };

    dkimKey = lib.mkOption {
      type = lib.types.str;
      default = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsC9GpfjvQlldPrHAC7Yt+ZF0aduUIVV4j2+KUkF0j6NsrpOgvU6COWKQSod/B/qyPBLWf+w5P5YiJ9XnOgw6Db/I9C67eusEHnV/cbvokXLQjSBvXee1OEdrT9i+6iUgDeGWP4CrD1DcwvXzAcCI9exy3yALHVlbkyYvi0KAYofs8dVQ3JCwSCMlol71lA6ULJ2zbCIWeSOv9/C6QZ5HOIeeoFLesX6O/YvF4FYxWbSHy244TXYuczQKuayjKgD6e8gIT5WJRQj8IAWOQ2podWw6hSuB3Ig+ekoOfnl5ivJGOMbAzFTj8FtbS4ncyidLU1kIOeuLfiILeDDLlIeYTwIDAQAB";
      example = "string_after_p=";
      description = "dkim key to put in host record for email";
    };

    repoName = lib.mkOption {
      type = lib.types.str;
      default = "monorepo";
      example = "myreponame";
      description = "Name of this repository";
    };

    projects = lib.mkOption {
      type = lib.types.listOf lib.types.str;
      default = [
        "monorepo"
        "nullerbot"
      ];
      example = [
        "project1"
        "project2"
        "project3"
      ];
      description = "Names of repos that will have mailing lists";
    };

    fileSystem = lib.mkOption {
      type = lib.types.str;
      default = "ext4";
      example = "btrfs";
      description = "filesystem to install with disko";
    };

    diskoSpec = lib.mkOption {
      type = lib.types.attrs;
      description = "retains a copy of the disko spec for reflection";
    };

    fullName = lib.mkOption {
      type = lib.types.str;
      default = "Preston Pan";
      example = "John Doe";
      description = "Full Name";
    };

    userName = lib.mkOption {
      type = lib.types.str;
      default = "preston";
      example = "myUser";
      description = "system username";
    };

    gpgKey = lib.mkOption {
      type = lib.types.str;
      default = "AEC273BF75B6F54D81343A1AC1FE6CED393AE6C1";
      example = "1234567890ABCDEF...";
      description = "GPG key fingerprint";
    };

    remoteHost = lib.mkOption {
      type = lib.types.str;
      default = "${vars.remoteHost}";
      example = "example.com";
      description = "Address to push to and pull from for website and git repos";
    };

    orgHost = lib.mkOption {
      type = lib.types.str;
      default = "${vars.orgHost}";
      example = "orgname.org";
      description = "Domain name of your organization, points to same VPS as remoteHost";
    };

    email = lib.mkOption {
      type = lib.types.str;
      default = "${vars.internetName}@${vars.orgHost}";
      example = "example@example.org";
      description = "Admin email address";
    };

    timeZone = lib.mkOption {
      type = lib.types.str;
      default = "America/Vancouver";
      example = "America/Chicago";
      description = "Linux timezone";
    };

    ntfySecret = lib.mkOption {
      type = lib.types.str;
      default = "ntfy";
      example = "ntfy-env";
      description = "Name of Ntfy secret for notification handling";
    };

    ntfyUrl = lib.mkOption {
      type = lib.types.str;
      default = "ntfy.${config.monorepo.vars.remoteHost}";
      example = "ntfy.nullring.xyz";
      description = "Name of ntfy server";
    };

    monitors = lib.mkOption {
      type = lib.types.listOf lib.types.str;
      default = [
        "HDMI-A-1"
        "eDP-1"
        "DP-2"
        "DP-3"
        "DP-4"
        "LVDS-1"
      ];
      example = [];
      description = "Monitors that waybar will use";
    };
  };
}

7.2. Default Profile

Again, these are self documenting variables that you may see used below. These are to be used under default.nix in the systems folder.

{ lib, config, pkgs, ... }:
let
  dirContents = builtins.readDir ./.;
  files = lib.filterAttrs (name: type: type == "regular" && lib.hasSuffix ".nix" name && name != "default.nix") dirContents;
in
{
  imports = lib.mapAttrsToList (name: _: ./. + "/${name}") files;

  options = {
    monorepo = {
      profiles = {
        cuda.enable = lib.mkEnableOption "Enables CUDA support";
        documentation.enable = lib.mkEnableOption "Enables documentation on system.";
        secureBoot.enable = lib.mkEnableOption "Enables secure boot. See sbctl.";
        pipewire.enable = lib.mkEnableOption "Enables pipewire low latency audio setup";
        tor.enable = lib.mkEnableOption "Enables tor along with torsocks";

        server = {
          enable = lib.mkEnableOption "Enables server services";
          interface = lib.mkOption { type = lib.types.str; default = "eth0"; };
          ipv4 = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; };
          ipv6 = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; };
          gateway = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; };
        };

        ttyonly.enable = lib.mkEnableOption "TTY only, no xserver";
        grub.enable = lib.mkEnableOption "Enables grub instead of systemd-boot";
        workstation.enable = lib.mkEnableOption "Enables workstation services";
        desktop.enable = lib.mkEnableOption "Enables everything common to desktops";
        impermanence.enable = lib.mkEnableOption "Enables imperamanence";
        home.enable = lib.mkEnableOption "Enables home profiles";
      };
    };
  };

  config = {
    environment.systemPackages = lib.mkIf config.monorepo.profiles.documentation.enable ((with pkgs; [
      linux-manual
      man-pages
      man-pages-posix
      iproute2
      silver-searcher
      ripgrep
    ]) ++
    (if (config.monorepo.vars.fileSystem == "btrfs") then with pkgs; [
      btrfs-progs
      btrfs-snap
      btrfs-list
      btrfs-heatmap
    ] else []));

    boot.loader.grub = lib.mkIf config.monorepo.profiles.grub.enable {
      enable = true;
    };

    assertions = [
      {
        assertion = !(config.monorepo.profiles.workstation.enable && config.monorepo.profiles.server.enable);
        message = ''
You can't enable both workstation and server profile together. Please select only one.
'';
      }
      {
        assertion = !(config.monorepo.profiles.desktop.enable && config.monorepo.profiles.server.enable);
        message = ''
You can't enable both desktop and server profile together. Please select only one.
'';
      }
    ];
    monorepo = {
      profiles = {
        desktop.enable = lib.mkDefault config.monorepo.profiles.workstation.enable;
        documentation.enable = lib.mkDefault true;
        pipewire.enable = lib.mkDefault true;
        tor.enable = lib.mkDefault true;
        impermanence.enable = lib.mkDefault false;
        server.enable = lib.mkDefault false;
        ttyonly.enable = lib.mkDefault config.monorepo.profiles.server.enable;
        home.enable = lib.mkDefault config.monorepo.profiles.desktop.enable;
      };
    };
  };
}

7.3. Secrets

This uses sops in order to declaratively create the secrets on my system by unencrypting the yaml file specified. Yes, this is safe to include in the repo. TODO clean up secrets, move them to relevant places.

{ config, ... }:
{
  sops = {
    defaultSopsFile = if config.monorepo.profiles.server.enable
                      then ../secrets/vps_secrets.yaml
                      else ../secrets/secrets.yaml;


    templates = if config.monorepo.profiles.server.enable then {
      "matterbridge" = {
        owner = "matterbridge";
        content = ''
[irc.myirc]
Server="127.0.0.1:6667"
Nick="bridge"
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
UseTLS=false

[telegram.mytelegram]
Token="${config.sops.placeholder.telegram_token}"
RemoteNickFormat="<({PROTOCOL}){NICK}> "
MessageFormat="HTMLNick :"
QuoteFormat="{MESSAGE} (re @{QUOTENICK}: {QUOTEMESSAGE})"
QuoteLengthLimit=46
IgnoreMessages="^/"

[discord.mydiscord]
Token="${config.sops.placeholder.discord_token}"
Server="Null Identity"
AutoWebHooks=true
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
PreserveThreading=true

[[gateway]]
name="gateway1"
enable=true

[[gateway.inout]]
account="irc.myirc"
channel="#nullring"

[[gateway.inout]]
account="discord.mydiscord"
channel="ID:996282946879242262"

[[gateway.inout]]
account="telegram.mytelegram"
channel="-5290629325"
'';
      };
    } else {};

    age = {
      keyFile = "/home/${config.monorepo.vars.userName}/.config/sops/age/keys.txt";
    };

    secrets = if config.monorepo.profiles.desktop.enable then {
      mail = {
        format = "yaml";
      };
      cloudflare-dns = {
        format = "yaml";
      };
      digikey = {
        format = "yaml";
      };
      dn42 = {
        format = "yaml";
      };
    } else {
      znc = {
        format = "yaml";
      };

      znc_password_salt = {
        format = "yaml";
      };

      znc_password_hash = {
        format = "yaml";
      };

      matrix_bridge = {
        format = "yaml";
      };

      mail_password = {
        format = "yaml";
        owner = "maddy";
      };

      mail_monorepo_password_pi = {
        format = "yaml";
        owner = "public-inbox";
      };

      mautrix_env = {
        format = "yaml";
      };

      telegram_token = {
        format = "yaml";
      };

      discord_token = {
        format = "yaml";
      };

      mpd_password = {
        format = "yaml";
        owner = "nginx";
      };
    };
  };
}

7.4. X11

My Xorg configuration is used as a backup for when wayland applications don't work. Note that using this configuration is extremely inefficient and my i3 configuration is unoptimized. Still, it is suitable for using Krita.

{ config, ... }:
{
  services.xserver = {
    enable = (! config.monorepo.profiles.ttyonly.enable);
    displayManager = {
      startx.enable = (! config.monorepo.profiles.ttyonly.enable);
    };

    desktopManager = {
      runXdgAutostartIfNone = true;
    };

    videoDrivers = (if config.monorepo.profiles.cuda.enable then [ "nvidia" ] else []);
  };
}

You should add your own video drivers in a custom machine configuration.

7.5. Containers

In order to run docker/podman containers, I need this file:

{ lib, ... }:
{
  virtualisation = {
    oci-containers = {
      backend = "podman";
      containers = {};
    };
    containers.enable = lib.mkDefault false;
    podman = {
      enable = lib.mkDefault false;
      dockerCompat = true;
      defaultNetwork.settings.dns_enabled = true;
    };
  };
}

7.6. Pipewire

My low latency pipewire configuration is used for music production, as well as for regular desktop usage. Pipewire is much better than pulseaudio because it supports jack with the same underlying interface and it breaks significantly less often.

{ lib, config, ... }:
{
  services.pipewire = {
    enable = lib.mkDefault config.monorepo.profiles.pipewire.enable;
    alsa = {
      enable = lib.mkDefault config.monorepo.profiles.pipewire.enable;
      support32Bit = true;
    };
    pulse.enable = lib.mkDefault config.monorepo.profiles.pipewire.enable;
    jack.enable = lib.mkDefault config.monorepo.profiles.pipewire.enable;
    wireplumber.enable = lib.mkDefault config.monorepo.profiles.pipewire.enable;
    extraConfig = {
      pipewire."92-low-latency" = {
        "context.properties" = {
          "default.clock.rate" = 48000;
          "default.clock.quantum" = 512;
          "default.clock.min-quantum" = 512;
          "default.clock.max-quantum" = 1024;
        };
        pipewire-pulse."92-low-latency" = {
          "context.properties" = [
            {
              name = "libpipewire-module-protocol-pulse";
              args = { };
            }
          ];
          "pulse.properties" = {
            "pulse.min.req" = "32/48000";
            "pulse.default.req" = "32/48000";
            "pulse.max.req" = "32/48000";
            "pulse.min.quantum" = "32/48000";
            "pulse.max.quantum" = "32/48000";
          };
          "stream.properties" = {
            "node.latency" = "32/48000";
            "resample.quality" = 1;
          };
        };
      };
    };
  };
}

7.7. SSH

My SSH daemon configuration.

{ config, lib, ... }:
{
  services.openssh = {
    enable = true;
    settings = {
      PasswordAuthentication = false;
      AllowUsers = [ config.monorepo.vars.userName "git" ];
      PermitRootLogin = "no";
      KbdInteractiveAuthentication = false;
    };
  };
  networking.firewall.allowedTCPPorts = lib.mkIf config.services.openssh.enable [ 22 ];
}

7.8. Tor

This is my tor configuration, used for my cryptocurrency wallets and whatever else I want it to do.

{ config, lib, ... }:
{
  services.tor = {
    enable = lib.mkDefault config.monorepo.profiles.tor.enable;
    openFirewall = true;
    client = {
      enable = lib.mkDefault config.monorepo.profiles.tor.enable;
      socksListenAddress = {
        IsolateDestAddr = true;
        addr = "127.0.0.1";
        port = 9050;
      };
      dns.enable = true;
    };
    torsocks = {
      enable = lib.mkDefault config.monorepo.profiles.tor.enable;
      server = "127.0.0.1:9050";
    };
  };
}

7.9. Kubo IPFS

I use IPFS for my website and also for my ISOs for truly declarative and deterministic configuration. NixOS might be moving to IPFS for binary cache distribution and package distribution soon, and I'm waiting on that.

{ config, lib, ... }:
{
  services.kubo = {
    enable = lib.mkDefault config.monorepo.profiles.workstation.enable;
    autoMount = false;
    enableGC = true;
    settings = {
      Addresses.API = [
        "/ip4/127.0.0.1/tcp/5001"
      ];
      Bootstrap = [
        "/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu"
        "/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm"
      ];
      Datastore = {
        StorageMax = "20GB";
      };
    };
  };
}

7.10. TODO i2pd

I use i2p for some p2p connections. We enable it with the server profile:

{ lib, ... }:
{
  services.i2pd = {
    enable = lib.mkDefault false;
    address = "0.0.0.0";
    inTunnels = {
    };
    outTunnels = {
    };
  };
}

7.11. TODO Icecast

This is an internet radio which will host a ton of music.

{ lib, ... }:
{
  services.icecast = {
    enable = lib.mkDefault false;
    listen.address = "0.0.0.0";
    extraConfig = ''
<mount type="default">
  <public>0</public>
  <intro>/stream.m3u</intro>
  <max-listener-duration>3600</max-listener-duration>
  <authentication type="url">
    <option name="mount_add" value="http://auth.example.org/stream_start.php"/>
  </authentication>
  <http-headers>
    <header name="foo" value="bar" />
  </http-headers>
</mount>
'';
  };
}

7.12. IRC

A great protocol. It's the most widely usable by any netizen, as it is just pure plaintext and the operating costs are trivial.

7.12.1. NgIRCD

I run my own IRC server to bridge with my Matrix server and my discord guild.

{ lib, config, ... }:
{
  services.ngircd = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    config = ''
[Global]
  Name = ${config.monorepo.vars.orgHost}
  Info = NullRing IRC Instance
  Listen = ::,0.0.0.0
  MotdFile = /etc/motd.txt
  Network = NullRing
  Ports = 6667
[Options]
  PAM = no
[SSL]
  CertFile = /var/lib/acme/${config.monorepo.vars.orgHost}/fullchain.pem
  CipherList = HIGH:!aNULL:@STRENGTH:!SSLv3
  KeyFile = /var/lib/acme/${config.monorepo.vars.orgHost}/key.pem
  Ports = 6697
'';
  };

  environment.etc."motd.txt" = {
    source = ../data/motd.txt;
    mode = "644";
    user = "ngircd";
    group = "ngircd";
  };

  networking.firewall.allowedTCPPorts = if (config.services.ngircd.enable == true) then [
    6697
    6667
  ] else [];
}

7.12.2. MOTD

I also have a MOTD file that I want to add, which displays when users connect to the server:

Welcome to the NullRing experience!
The main channel is #nullring; we're glad to have you!

Rules:
1. Don't be annoying.
2. No illegal content.
And if you're here to have constructive, philisophical and theoretical
conversations, this is the place for you!

7.12.3. ZNC

I want to be able to create some sort of identity persistence on IRC for users:

{ lib, config, ... }:
{
  services.znc = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    openFirewall = true;
    confOptions = {
      useSSL = true;
      passBlock = ''
<Pass password>
  Method = sha256
  Hash = d4abdd69aa24de69693885c5bd83a4a0e9ee989e1a69a905041b0dad9abc06ea
  Salt = sDY,?H5AxC-!gH3a.:)D
</Pass>
'';
      modules = [
        "partyline"
        "webadmin"
        "adminlog"
        "log"
      ];
      networks = {
        "libera" = {
          server = "irc.libera.chat";
          port = 6697;
          useSSL = true;
          modules = [ "simple_away" ];
        };
        "nullring" = {
          server = "${config.monorepo.vars.orgHost}";
          port = 6697;
          useSSL = true;
          modules = [ "simple_away" "log" ];
        };
      };
    };
  };
}

Note that the password hash and whatnot is completely random so there is almost no point to cracking it with hashcat.

7.13. Conduit

This is a modern matrix server that is meant to be lightweight while still federating and hosting the same protocol. There is also a configuration for lk-jwt and livekit which is important for configuring p2p calls in matrix.

{ config, lib, ... }:
let
  livekitListenPort = 8443;
  # secrets.yaml
  livekit_secret = "livekit_secret";
  conduit_secret = "conduit_secrets";
in
{
  sops.secrets = lib.mkIf config.services.matrix-conduit.enable {
    "${livekit_secret}" = lib.mkIf config.services.livekit.enable {
      format = "yaml";
      mode = "0444";
    };

    "${conduit_secret}" = {
      format = "yaml";
    };
  };

  services.matrix-conduit = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    secretFile = "/run/secrets/${conduit_secret}";
    settings.global = {
      server_name = "matrix.${config.monorepo.vars.orgHost}";
      trusted_servers = [
        "matrix.org"
        "nixos.org"
        "conduit.rs"
      ];
      address = "0.0.0.0";
      port = 6167;
      allow_registration = false;
    };
  };


  services.livekit = {
    enable = lib.mkDefault (config.services.matrix-conduit.enable || config.services.matrix-synapse.enable);
    keyFile = "/run/secrets/${livekit_secret}";
    settings = {
      port = 7880;
      turn = {
        enabled = true;
        domain = "livekit.${config.monorepo.vars.orgHost}";
        cert_file = "/var/lib/acme/livekit.${config.monorepo.vars.orgHost}/fullchain.pem";
        key_file = "/var/lib/acme/livekit.${config.monorepo.vars.orgHost}/key.pem";
        tls_port = 5349;
        udp_port = 3478;
      };

      rtc = {
        use_external_ip = true;
        tcp_port = 7881;
        udp_port = 7882;
        port_range_start = 50000;
        port_range_end = 60000;
      };
    };
  };

  services.lk-jwt-service = {
    enable = lib.mkDefault config.services.livekit.enable;
    port = 6495;
    livekitUrl = "wss://livekit.${config.monorepo.vars.orgHost}";
    keyFile = "/run/secrets/${livekit_secret}";
  };

  # TODO: split into conduit and livekit
  networking.firewall.allowedTCPPorts = lib.mkIf config.services.matrix-conduit.enable [ 8448 7881 5349 livekitListenPort ];

  # this is fine though
  networking.firewall.allowedUDPPorts = lib.mkIf config.services.livekit.enable [ 7882 3478 ];
  networking.firewall.allowedUDPPortRanges = lib.mkIf config.services.livekit.enable [
    { from = 49152; to = 65535; }
  ];

  networking.domains.subDomains."matrix.${config.monorepo.vars.orgHost}" = lib.mkIf config.services.matrix-conduit.enable {};
  networking.domains.subDomains."livekit.${config.monorepo.vars.orgHost}" = lib.mkIf config.services.livekit.enable {};

  services.nginx.virtualHosts."matrix.${config.monorepo.vars.orgHost}" = lib.mkIf config.services.matrix-conduit.enable {
    enableACME = lib.mkDefault config.monorepo.profiles.server.enable;
    forceSSL = true;
    listen = [
      {
        addr = "0.0.0.0";
        port = 443;
        ssl = true;
      }
      {
        addr = "[::]";
        port = 443;
        ssl = true;
      }
      {
        addr = "0.0.0.0";
        port = 8448;
        ssl = true;
      }
      {
        addr = "[::]";
        port = 8448;
        ssl = true;
      }
    ];
    locations."/_matrix/" = {
      proxyPass = "http://127.0.0.1:${toString config.services.matrix-conduit.settings.global.port}";
      extraConfig = ''
            proxy_set_header Host $host;
            proxy_buffers 32 16k;
            proxy_read_timeout 5m;
          '';
    };

    locations."= /.well-known/matrix/server" = {
      extraConfig = ''
      default_type application/json;
      add_header Content-Type application/json;
      add_header Access-Control-Allow-Origin *;
    '';

      return = ''200 '{"m.server": "matrix.${config.monorepo.vars.orgHost}:443"}' ''; 
    };

    locations."/.well-known/matrix/client" = {
      extraConfig = ''
    default_type application/json;
    add_header Access-Control-Allow-Origin *;
  '';

      return = "200 '{\"m.homeserver\": {\"base_url\": \"https://matrix.${config.monorepo.vars.orgHost}\"}, \"org.matrix.msc4143.rtc_foci\": [{\"type\": \"livekit\", \"livekit_service_url\": \"https://matrix.${config.monorepo.vars.orgHost}:${toString livekitListenPort}\"}]}'";
    };

    extraConfig = ''
          merge_slashes off;
        '';
  };


  services.nginx.virtualHosts."matrix.${config.monorepo.vars.orgHost}-livekit" = lib.mkIf config.services.livekit.enable {
    serverName = "matrix.${config.monorepo.vars.orgHost}";
    listen = [
      { 
        addr = "0.0.0.0"; 
        port = livekitListenPort;
        ssl = true; 
      }
      {
        addr = "[::]";
        port = livekitListenPort;
        ssl = true;
      }
    ];
    addSSL = true;
    enableACME = false;
    forceSSL = false;
    useACMEHost = "matrix.${config.monorepo.vars.orgHost}";

    locations."/" = {
      proxyPass = "http://127.0.0.1:${toString config.services.lk-jwt-service.port}"; 
      proxyWebsockets = true;
      extraConfig = ''
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
    '';
    };
  };

  services.nginx.virtualHosts."livekit.${config.monorepo.vars.orgHost}" = lib.mkIf config.services.livekit.enable {
    enableACME = true;
    forceSSL = true;
    locations."/" = {
      proxyPass = "http://127.0.0.1:${toString config.services.livekit.settings.port}";
      proxyWebsockets = true;
      extraConfig = ''
            proxy_read_timeout 3600s;
            proxy_send_timeout 3600s;

            # Standard headers for LiveKit
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";

            # --- CORS CONFIGURATION START ---
            # 1. Allow all origins (including app.element.io)
            add_header 'Access-Control-Allow-Origin' '*' always;

            # 2. Allow specific methods (POST is required for /sfu/get)
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;

            # 3. Allow headers (Content-Type is crucial for JSON)
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;

            # 4. Handle the OPTIONS preflight request immediately
            if ($request_method = 'OPTIONS') {
               add_header 'Access-Control-Allow-Origin' '*' always;
               add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
               add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
               add_header 'Access-Control-Max-Age' 1728000;
               add_header 'Content-Type' 'text/plain; charset=utf-8';
               add_header 'Content-Length' 0;
               return 204;
                }
            # --- CORS CONFIGURATION END ---
          '';
    };
  };
}

7.14. TODO GoToSocial

This is a basic ActivityPub server.

{ lib, config, ... }:
{
  services.gotosocial = {
    enable = lib.mkDefault false;
    setupPostgresqlDB = true;
    settings = {
      application-name = "Nullring GoToSocial Instance";
      host = "gotosocial.${config.monorepo.vars.orgHost}";
      protocol = "https";
      bind-address = "127.0.0.1";
      port = 8080;
    };
  };
}

7.15. TODO matrix-appservice-irc

{ ... }:
{
  # enable = lib.mkDefault config.monorepo.profiles.server.enable;
  # registrationUrl = "localhost";

  # settings = {
  #   homeserver.url = "https://matrix.nullring.xyz";
  #   homserver.domain = "matrix.nullring.xyz";
  # };
}

7.16. Gitolite

{ lib, config, ... }:
{
  services.gitolite = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    description = "My Gitolite User";
    adminPubkey = config.monorepo.vars.sshKey;
  };
}

7.17. Matterbridge

I want to connect IRC to discord with matterbridge.

{ lib, config, ... }:
{
  services.matterbridge = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    configPath = "${config.sops.templates.matterbridge.path}";
  };
}

7.17.1. Mautrix

I use this bridge to bridge myself from Matrix to Discord and vise versa, because Matterbridge is not maintained very well and therefore does not support conduit at the moment. Note that this is not fully declarative and requires that you add /var/lib/mautrix-discord/discord-registration.yaml as an appservice to conduit.

{ lib, config, ... }:
{
  services.mautrix-discord = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    environmentFile = "/run/secrets/mautrix_env";
    settings = {
      bridge = {
        animated_sticker = {
          args = {
            fps = 25;
            height = 320;
            width = 320;
          };
          target = "webp";
        };
        autojoin_thread_on_open = true;
        avatar_proxy_key = "generate";
        backfill = {
          forward_limits = {
            initial = {
              channel = 0;
              dm = 0;
              thread = 0;
            };
            max_guild_members = -1;
            missed = {
              channel = 0;
              dm = 0;
              thread = 0;
            };
          };
        };
        cache_media = "unencrypted";
        channel_name_template = "{{if or (eq .Type 3) (eq .Type 4)}}{{.Name}}{{else}}#{{.Name}}{{end}}";
        command_prefix = "!discord";
        custom_emoji_reactions = true;
        delete_guild_on_leave = true;
        delete_portal_on_channel_delete = false;
        delivery_receipts = false;
        direct_media = {
          allow_proxy = true;
          enabled = false;
          server_key = "generate";
        };
        displayname_template = "{{if .Webhook}}Webhook{{else}}{{or .GlobalName .Username}}{{if .Bot}} (bot){{end}}{{end}}";
        double_puppet_allow_discovery = true;
        double_puppet_server_map = { };
        embed_fields_as_tables = true;
        enable_webhook_avatars = true;
        encryption = {
          allow = false;
          allow_key_sharing = false;
          appservice = false;
          default = false;
          delete_keys = {
            delete_fully_used_on_decrypt = false;
            delete_on_device_delete = false;
            delete_outbound_on_ack = false;
            delete_outdated_inbound = false;
            delete_prev_on_new_session = false;
            dont_store_outbound = false;
            periodically_delete_expired = false;
            ratchet_on_decrypt = false;
          };
          msc4190 = false;
          plaintext_mentions = false;
          require = false;
          rotation = {
            disable_device_change_key_rotation = false;
            enable_custom = false;
            messages = 100;
            milliseconds = 604800000;
          };
          verification_levels = {
            receive = "unverified";
            send = "unverified";
            share = "cross-signed-tofu";
          };
        };
        federate_rooms = true;
        guild_name_template = "{{.Name}}";
        login_shared_secret_map = { };
        management_room_text = {
          additional_help = "";
          welcome = "Hello, I'm a Discord bridge bot.";
          welcome_connected = "Use `help` for help.";
          welcome_unconnected = "Use `help` for help or `login` to log in.";
        };
        message_error_notices = true;
        message_status_events = false;
        mute_channels_on_create = false;
        permissions = {
          "@${config.monorepo.vars.internetName}:matrix.${config.monorepo.vars.orgHost}" = "admin";
          "*" = "user";
        };
        portal_message_buffer = 128;
        prefix_webhook_messages = true;
        private_chat_portal_meta = "default";
        provisioning = {
          debug_endpoints = false;
          prefix = "/_matrix/provision";
          shared_secret = "generate";
        };
        public_address = null;
        resend_bridge_info = false;
        restricted_rooms = false;
        startup_private_channel_create_limit = 5;
        sync_direct_chat_list = false;
        use_discord_cdn_upload = true;
        username_template = "discord_{{.}}";
      };

      appservice = {
        address = "http://localhost:29334";
        hostname = "0.0.0.0";
        port = 29334;
        id = "discord";
        bot = {
          username = "discordbot";
          displayname = "Discord bridge bot";
          avatar = "mxc://maunium.net/nIdEykemnwdisvHbpxflpDlC";
        };
        ephemeral_events = true;
        async_transactions = false;
        database = {
          type = "sqlite3";
          uri = "file:${config.services.mautrix-discord.dataDir}/mautrix-discord.db?_txlock=immediate";
          max_open_conns = 20;
          max_idle_conns = 2;
          max_conn_idle_time = null;
          max_conn_lifetime = null;
        };
        as_token = "$MAUTRIX_DISCORD_APPSERVICE_AS_TOKEN";
        hs_token = "$MAUTRIX_DISCORD_APPSERVICE_HS_TOKEN";
      };

      dataDir = "/var/lib/mautrix-discord";
      homeserver = {
        async_media = false;
        message_send_checkpoint_endpoint = null;
        ping_interval_seconds = 0;
        software = "standard";
        status_endpoint = null;
        websocket = false;
        domain = "matrix.${config.monorepo.vars.orgHost}";
        address = "http://localhost:6167";
      };
    };
  };
}

7.18. Ollama

Use ollama for serving large language models to my other computers.

{ config, lib, pkgs, ... }:
{
  # services.open-webui.enable = lib.mkDefault (!config.monorepo.profiles.server.enable);
  services.ollama = {
    enable = lib.mkDefault config.monorepo.profiles.desktop.enable;
    package = if (config.monorepo.profiles.cuda.enable) then pkgs.ollama-cuda else pkgs.ollama-vulkan;
    loadModels = if (config.monorepo.profiles.cuda.enable) then [
      "qwen3:30b"
      "qwen3-coder:latest"
      "qwen2.5-coder:latest"
      "gemma3:12b-it-qat"
    ] else [
      "qwen3:0.6b"
      "qwen2.5-coder:0.5b"
    ];
    host = "0.0.0.0";
    openFirewall = true;
  };
}

7.19. Bitcoind

{ config, lib, ... }:
{
  services.bitcoind."${config.monorepo.vars.userName}" = {
    enable = lib.mkDefault config.monorepo.profiles.workstation.enable;
    prune = 10000;
  };
}

7.20. Git Server

I run my own git server in order to have a mirror in case github goes down.

{ config, lib, ... }:
{
  services.gitDaemon = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    exportAll = true;
    basePath = "${config.users.users.git.home}";
  };
  networking.firewall.allowedTCPPorts = lib.mkIf config.services.gitDaemon.enable [
    9418
  ];
}

7.21. Ntfy

I want to have notifications on my phone, and run my own server to do this.

{ pkgs, lib, config, ... }:
let
  serverName = "${config.monorepo.vars.ntfyUrl}";
  port = 2586;
  ntfySecret = config.monorepo.vars.ntfySecret;
in
{
  sops.secrets."${ntfySecret}" = lib.mkIf config.services.ntfy-sh.enable {
    format = "yaml";
    owner = "ntfy-sh";
    sopsFile = ../secrets/common_secrets.yaml;
  };

  services.ntfy-sh = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    settings = {
      base-url = "https://${serverName}";
      listen-http = "127.0.0.1:${toString port}";
      envrionmentFile = "/run/secrets/${ntfySecret}";
      auth-file = "/var/lib/ntfy-sh/user.db";
      auth-default-access = "deny-all";
      enable-login = true;
    };
  };

  services.nginx.enable = config.services.ntfy-sh.enable;

  systemd.services.ntfy-sh = lib.mkIf config.services.ntfy-sh.enable {
    serviceConfig = {
      EnvironmentFile = "/run/secrets/${ntfySecret}";
    };
    postStart = lib.mkForce ''
      # 1. Wait for the server to initialize the database
      echo "Waiting for ntfy auth database to appear..."
      TIMEOUT=30
      while [ ! -f /var/lib/ntfy-sh/user.db ]; do
        sleep 1
        TIMEOUT=$((TIMEOUT-1))
        if [ $TIMEOUT -le 0 ]; then
          echo "Timed out waiting for database creation!"
          exit 1
        fi
      done

      echo "Database found. Configuring admin user..."

      # 2. Define the username
      ADMIN_USER="ret2pop"

      # 3. Check if user exists, create if missing
      # We pipe the password twice because 'ntfy user add' asks for confirmation
      if ! ${pkgs.ntfy-sh}/bin/ntfy user list | grep -q "$ADMIN_USER"; then
        echo "Creating admin user $ADMIN_USER..."
        printf "$ADMIN_PASSWORD\n$ADMIN_PASSWORD" | \
          ${pkgs.ntfy-sh}/bin/ntfy user add --role=admin "$ADMIN_USER"
        echo "User created."
      else
        echo "Admin user already exists."
      fi
    '';
  };

  networking.domains.subDomains."${serverName}" = lib.mkIf config.services.ntfy-sh.enable {};
  services.nginx.virtualHosts."${serverName}" = lib.mkIf config.services.ntfy-sh.enable {
    serverName = "${serverName}";
    enableACME = true;
    forceSSL = true;
    locations."/" = {
      proxyPass = "http://127.0.0.1:${toString port}";
      proxyWebsockets = true;
      extraConfig = ''
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
'';
    };
  };
}

7.22. Nginx

These are all my virtual hosts. For many of these servers we have to have a reverse proxy in order to expose the locally running instances to the outside world under a domain.

{ pkgs, config, lib, monorepoSelf ? null, ... }:
{
  services.nginx = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    user = "nginx";
    recommendedGzipSettings = true;
    recommendedOptimisation = true;
    recommendedBrotliSettings = true;
    recommendedTlsSettings = true;
    recommendedProxySettings = false;
    virtualHosts = {
      "${config.monorepo.vars.remoteHost}" = lib.mkIf (monorepoSelf != null) {
        serverName = "${config.monorepo.vars.remoteHost}";
        serverAliases = [ "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" ];
        root = "${monorepoSelf.packages.${pkgs.system}.website}";
        addSSL = true;
        enableACME = true;
        locations."/" = {
          extraConfig = ''
add_header Cache-Control "no-cache, must-revalidate";
expires off;
    '';
        };

        locations."~* \\.(?:woff2|ttf|otf|eot|woff|ico|css|js|gif|jpe?g|png|svg|mp3|mp4|iso|webmanifest)$" = {
          extraConfig = ''
add_header Cache-Control "public, max-age=31536000, immutable";
access_log off;
    '';
        };
        extraConfig = ''
include ${monorepoSelf.packages.${pkgs.system}.website}/csp_header.conf;
rewrite ^/graph_view/?(.*)$ https://graph.${config.monorepo.vars.remoteHost}/$1 permanent;
'';
      };

      # the port comes from ssh tunnelling
      "music.${config.monorepo.vars.remoteHost}" = lib.mkIf config.monorepo.profiles.server.enable {
        addSSL = true;
        enableACME = true;
        basicAuthFile = config.sops.secrets."mpd_password".path;
        locations."/" = {
          proxyPass = "http://localhost:8000";
          extraConfig = ''
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 36000s;
'';
        };
      };

      "${config.monorepo.vars.orgHost}" = {
        serverName = "${config.monorepo.vars.orgHost}";
        root = "/var/www/nullring/";
        addSSL = true;
        enableACME = true;
      };

      "graph.${config.monorepo.vars.remoteHost}" = lib.mkIf (monorepoSelf != null) {
        serverName = "graph.${config.monorepo.vars.remoteHost}";
        root = "${monorepoSelf.packages.${pkgs.system}.website}";
        addSSL = true;
        enableACME = true;
        locations."/" = {
          extraConfig = "rewrite ^/$ /graph_view/index.html break;";
        };

        extraConfig = ''
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; object-src 'none';";
  '';
      };
    };
  };

  networking.firewall.allowedTCPPorts = lib.mkIf config.services.nginx.enable [ 80 443 ];

  networking.domains.subDomains = lib.mkIf config.services.nginx.enable {
    "${config.monorepo.vars.remoteHost}" = {};
    "${config.monorepo.vars.orgHost}" = {};
    "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" = {};
    "music.${config.monorepo.vars.remoteHost}" = {};
    "graph.${config.monorepo.vars.remoteHost}" = {};
  };
}

7.23. CGit Interface

I have this cgit interface in order to integrate with public-inbox.

{ lib, config, ... }:
let
  serverName = "git.${config.monorepo.vars.orgHost}";
in
{
  services.cgit."my-projects" = {
    enable = lib.mkDefault config.services.gitDaemon.enable;
    scanPath = "${config.users.users.git.home}"; 
    settings = {
      root-title = "Nullring Git Server";
      root-desc = "Projects and cool things";
      enable-commit-graph = 1;
      enable-log-filecount = 1;
      enable-log-linecount = 1;
      enable-index-owner = 0;
      clone-prefix = "https://${serverName}";
      enable-tree-linenumbers = 1;
      strict-export = "git-daemon-export-ok";
    };
    gitHttpBackend = {
      enable = true;
      checkExportOkFiles = true;
    };
    nginx = {
      virtualHost = "${serverName}";
    };
  };

  networking.domains.subDomains."${serverName}" = lib.mkIf config.services.cgit."my-projects".enable {};
  services.nginx.virtualHosts."${serverName}" = lib.mkIf config.services.cgit."my-projects".enable {
    forceSSL = true;
    enableACME = true;
  };
}

7.24. Nvidia

I have an Nvidia GPU on my computer.

{ config, lib, pkgs, ... }:
{
  hardware = {
    graphics.extraPackages = (if config.monorepo.profiles.cuda.enable
                              then with pkgs; [
                                libva-vdpau-driver
                                libvdpau-va-gl
                                nvidia-vaapi-driver
                              ] else []);

    nvidia = {
      modesetting.enable = lib.mkDefault config.monorepo.profiles.cuda.enable;
      powerManagement = {
        enable = lib.mkDefault config.monorepo.profiles.cuda.enable;
        finegrained = false;
      };
      open = config.monorepo.profiles.cuda.enable;
      package = config.boot.kernelPackages.nvidiaPackages.stable;
      nvidiaSettings = false;
    };
  };
}

7.25. CUDA

I need CUDA on some computers because I run local LLMs.

{ config, pkgs, ... }:
{
  environment.systemPackages = (if config.monorepo.profiles.cuda.enable then with pkgs; [
  cudatoolkit
  cudaPackages.cudnn
  cudaPackages.libcublas
  linuxPackages.nvidia_x11
  ] else []);
}

7.26. Maddy

There is a non declarative part of setting dkims and spf.

{ lib, config, options, ... }:
let
  emailServerName = "mail.${config.monorepo.vars.orgHost}";
  serverName = "list.${config.monorepo.vars.orgHost}";
  password_path = "mail_monorepo_password";
in
{
  sops = lib.mkIf config.services.maddy.enable {
    secrets = {
      "${password_path}" = {
        format = "yaml";
        owner = "maddy";
      };
    };
    templates = lib.mkIf config.services.public-inbox.enable {
      "public-inbox-netrc" = {
        owner = "public-inbox";
        group = "public-inbox";
        mode = "0400";
        content = (builtins.concatStringsSep "\n" (builtins.map (x: "machine ${emailServerName} login ${x}@${config.monorepo.vars.orgHost} password ${config.sops.placeholder."mail_monorepo_password_pi"}") config.monorepo.vars.projects)) + ''
machine ${emailServerName} login discussion@${config.monorepo.vars.orgHost} password ${config.sops.placeholder."mail_monorepo_password_pi"}'';
      };
    };
  };

  services.maddy = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    openFirewall = true;
    hostname = "${config.monorepo.vars.orgHost}";
    primaryDomain = "mail.${config.monorepo.vars.orgHost}";
    localDomains = [
      "$(primary_domain)"
      "${config.monorepo.vars.orgHost}"
    ];
    tls = {
      loader = "file";
      certificates = [
        {
          keyPath = "/var/lib/acme/mail.${config.monorepo.vars.orgHost}/key.pem";
          certPath = "/var/lib/acme/mail.${config.monorepo.vars.orgHost}/fullchain.pem";
        }
      ];
    };
    config = builtins.replaceStrings [
      "imap tcp://0.0.0.0:143"
      "submission tcp://0.0.0.0:587"
    ] [
      "imap tls://0.0.0.0:993 tcp://0.0.0.0:143"
      "submission tls://0.0.0.0:465 tcp://0.0.0.0:587"
    ] options.services.maddy.config.default;

    ensureAccounts = (builtins.map (x: "${x}@${config.monorepo.vars.orgHost}") config.monorepo.vars.projects) ++ [
      "${config.monorepo.vars.internetName}@${config.monorepo.vars.orgHost}"
      "discussion@${config.monorepo.vars.orgHost}"
    ];
    ensureCredentials = lib.genAttrs config.services.maddy.ensureAccounts (_: {
      passwordFile = "/run/secrets/${password_path}";
    }) // {
      "${config.monorepo.vars.internetName}@${config.monorepo.vars.orgHost}" = {
        passwordFile = "/run/secrets/mail_password";
      };
    };
  };

  systemd.tmpfiles.rules = [
    "C+ /var/lib/public-inbox/style.css 0644 public-inbox public-inbox - ${../data/public-inbox.css}"
  ];
  systemd.services.public-inbox-httpd = if config.monorepo.profiles.server.enable then {
    preStart = ''
    # Copy or link the file. 
    # Using 'cp' is often safer for sandboxed services than linking to the store. Lol.
    cp -f ${../data/public-inbox.css} /var/lib/public-inbox/style.css
    chmod 644 /var/lib/public-inbox/style.css
  '';

    serviceConfig = {
      BindPaths = [ 
        "/var/lib/public-inbox" 
        "${config.users.users.git.home}"
      ];
      ReadOnlyPaths = [ "/var/lib/public-inbox/style.css" ];
      ReadWritePaths = [ "/var/lib/public-inbox" ];
    };
  } else {};

  systemd.services.public-inbox-watch = if config.services.public-inbox.enable then {
    after = [ "sops-nix.service" ];
    confinement.enable = lib.mkForce false;
    preStart = ''
      mkdir -p /var/lib/public-inbox/.tmp
      chmod 0700 /var/lib/public-inbox/.tmp
      ln -sfn ${config.sops.templates."public-inbox-netrc".path} /var/lib/public-inbox/.netrc
    '';
    environment = {
      PUBLIC_INBOX_FORCE_IPV4 = "1";
      NETRC = config.sops.templates."public-inbox-netrc".path;
      HOME = "/var/lib/public-inbox";
      TMPDIR = "/var/lib/public-inbox/.tmp";
    };

    serviceConfig = {
      RestrictSUIDSGID = lib.mkForce false;
      ReadWritePaths = [ "/var/lib/public-inbox" ];
      RestrictAddressFamilies = lib.mkForce [ "AF_UNIX" "AF_INET" "AF_INET6" ];
      PrivateNetwork = lib.mkForce false;
      SystemCallFilter = lib.mkForce [];
      RootDirectory = lib.mkForce "";

      CapabilityBoundingSet = lib.mkForce [ "~" ];
      UMask = lib.mkForce "0022";
      ProtectSystem = lib.mkForce false;
    };
  } else {};

  services.public-inbox = {
    enable = lib.mkDefault config.services.maddy.enable;
    settings = {
      coderepo = lib.genAttrs config.monorepo.vars.projects (name: {
        dir = "${config.users.users.git.home}/${name}.git";
        # works even if no cgit server running here, this is just the default
        cgitUrl = "https://git.${config.monorepo.vars.orgHost}/${name}.git";
      });
      publicinbox.css = ["/var/lib/public-inbox/style.css"];
      publicinbox.wwwlisting = "all";
    };
    http = {
      enable = true;
      port = 9090;
    };
    inboxes = lib.genAttrs config.monorepo.vars.projects (name: {
      description = "discussion of the ${name} project.";
      address = [ "${name}@${config.monorepo.vars.orgHost}" ];
      inboxdir = "/var/lib/public-inbox/${name}";
      url = "https://list.${config.monorepo.vars.orgHost}/${name}";
      watch = [ "imaps://${name}${config.monorepo.vars.orgHost}@${emailServerName}/INBOX" ];
      coderepo = [ "${name}" ];
    }) // {
      "discussion" = {
        description = "Main Nullring Discussion Mailing List";
        address = [ "discussion@${config.monorepo.vars.orgHost}" ];
        inboxdir = "/var/lib/public-inbox/discuss";
        url = "https://${serverName}/discussion";
        watch = [ "imaps://discussion%40${config.monorepo.vars.orgHost}@${emailServerName}/INBOX" ];
      };
    };
  };

  networking.domains.baseDomains."${config.monorepo.vars.orgHost}" = lib.mkIf config.services.maddy.enable {
    mx.data = [
      {
        preference = 10;
        exchange = "${emailServerName}";
      }
    ];
  };

  networking.domains.subDomains = lib.mkIf config.services.maddy.enable {
    "${serverName}" = {};
    "${emailServerName}" = {};
    "_dmarc.${config.monorepo.vars.orgHost}" = {
      txt = {
        data = "v=DMARC1; p=none";
      };
    };
    "default._domainkey.${config.monorepo.vars.orgHost}" = {
      txt = {
        data = "v=DKIM1; k=rsa; p=${config.monorepo.vars.dkimKey}";
      };
    };
  };

  networking.firewall.allowedTCPPorts = lib.mkIf config.services.maddy.enable [
    143
    465
    587
    993
  ];

  services.nginx.virtualHosts."${serverName}" = lib.mkIf config.services.public-inbox.enable {
    forceSSL = true;
    enableACME = true;
    locations."/" = {
      proxyPass = "http://localhost:${toString config.services.public-inbox.http.port}";
      extraConfig = ''
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
        '';
    };
  };

  services.nginx.virtualHosts."${emailServerName}" = lib.mkIf config.services.maddy.enable {
    serverName = "${emailServerName}";
    root = "/var/www/dummy";
    addSSL = true;
    enableACME = true;
  };

}

7.26.1. Public Inbox CSS

This is a minimal stylesheet for public inbox so that I don't get eye cancer while reading it.

:root {
  --bg: #f8f9fa;
  --fg: #2e3440;
  --link: #5e81ac;
  --link-hover: #81a1c1;
  --border: #d8dee9;
  --card-bg: #ffffff;
  --meta-fg: #4c566a; /* Darker gray for better legibility */
  --btn-fg: #ffffff;
  --max-width: 780px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1a1b26;
    --fg: #a9b1d6;
    --link: #7aa2f7;
    --link-hover: #bb9af7;
    --border: #414868; /* Distinct border for dark mode */
    --card-bg: #1f2335;
    --meta-fg: #9aa5ce; /* Brighter gray for dark mode */
    --btn-fg: #1a1b26;
  }
}

span.q {
  color: var(--meta-fg);
  font-style: italic;
}

body {
  background-color: var(--bg);
  color: var(--fg);
  line-height: 1.6;
  max-width: var(--max-width);
  margin: 3rem auto;
  padding: 0 1.5rem;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  /* Keep this for smoother rendering on macOS/iOS */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* 1. Global Link Fixes */
body a, body a:visited {
  color: var(--link);
}

/* 2. Card Styling */
body pre {
  white-space: pre-wrap;
  background: var(--card-bg);
  padding: 2rem;
  border-radius: 12px;
  border: 1px solid var(--border);
  margin-bottom: 2.5rem;
}

/* 3. Header Cleanup */
body pre b:first-of-type {
  font-weight: 700;
  color: var(--link);
  font-size: 1.1rem;
  display: block;
  margin-bottom: 0.5rem;
}

/* 4. Fixing the "Permalink" label on documentation */
/* We target links ending in / but EXCLUDE system paths like help or mirror */
body pre a[href$="/"]:not([href*="_/"]):not([href*="new.atom"]) {
  font-size: 0;
  text-decoration: none;
  margin-right: 10px;
}

body pre a[href$="/"]:not([href*="_/"]):not([href*="new.atom"]):after {
  content: "permalink";
  font-size: 11px;
  font-weight: bold;
  color: var(--fg); /* Use main text color for high contrast */
  background: var(--bg);
  border: 1px solid var(--link); /* Use link color for the border */
  padding: 4px 10px;
  border-radius: 4px;
  display: inline-block;
}

/* 5. Fixing the "Raw" button contrast */
body pre a[href$="/raw"] {
  font-size: 0;
  text-decoration: none;
}

body pre a[href$="/raw"]:after {
  content: "raw";
  font-size: 11px;
  font-weight: bold;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--link);
  padding: 4px 10px;
  border-radius: 4px;
  display: inline-block;
}

/* Hover effect for ghost buttons: solid color shift */
body pre a[href$="/"]:hover:after,
body pre a[href$="/raw"]:hover:after {
  background: var(--link);
  color: var(--btn-fg);
}

/* 6. The Reply Button (Primary Action) */
body pre a[href$="#R"], body pre a[href$="#R"]:visited {
  font-size: 0;
  text-decoration: none;
}

body pre a[href$="#R"]:after {
  content: "REPLY";
  font-size: 12px;
  font-weight: bold;
  padding: 6px 20px;
  background: var(--link);
  color: var(--btn-fg);
  border-radius: 6px;
  display: inline-block;
  margin-left: 10px;
}

/* 7. Hide clutter */
body pre a[href^="#r"], body pre a[href^="#r"] + b, body hr {
  display: none;
}

/* Fix: Mathematically outscore the header rule to keep link text inline */
body pre a[href] b:first-of-type {
  display: inline;
  font-size: inherit;
  margin-bottom: 0;
  color: inherit;
}

7.27. Fail2Ban

This is a service that bans bots that try to sign in on my server.

{ lib, config, ... }:
{
  services.fail2ban = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    # Ban IP after 5 failures for 1 hour
    maxretry = 5;
    bantime = "1h";
    banaction = "iptables-allports";
    banaction-allports = "iptables-allports";
  };
}

7.28. Impermanence

This is my impermanence profile, which removes all files on reboot except for the ones listed below.

{ lib, config, ... }:
{
  assertions = [
    {
      assertion = (! (config.monorepo.profiles.impermanence.enable && (! (config.monorepo.vars.fileSystem == "btrfs"))));
      message = "Impermanence requires btrfs filesystem.";
    }
  ];

  boot.initrd.postResumeCommands = (if config.monorepo.profiles.impermanence.enable then lib.mkAfter ''
    mkdir /btrfs_tmp
    mount -t btrfs -n -o subvol=/ /dev/mapper/crypted /btrfs_tmp
    if [[ -e /btrfs_tmp/root ]]; then
        mkdir -p /btrfs_tmp/old_roots
        timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/root)" "+%Y-%m-%-d_%H:%M:%S")
        mv /btrfs_tmp/root "/btrfs_tmp/old_roots/$timestamp"
    fi

    delete_subvolume_recursively() {
        IFS=$'\n'
        for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
            delete_subvolume_recursively "/btrfs_tmp/$i"
        done
        btrfs subvolume delete "$1"
    }

    for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +30); do
        delete_subvolume_recursively "$i"
    done

    btrfs subvolume create /btrfs_tmp/root
    umount -n /btrfs_tmp
  '' else "");

  boot.initrd.luks.devices = (if (config.monorepo.vars.fileSystem == "btrfs") then {
    crypted = {
      device = "/dev/disk/by-partlabel/disk-main-luks";
    };
  } else {});

  fileSystems = if (config.monorepo.profiles.impermanence.enable) then {
    "/persistent" = {
      neededForBoot = true;
    };
    "/home" = {
      neededForBoot = true;
    };
  } else {};

  environment.persistence."/persistent" = {
    enable = config.monorepo.profiles.impermanence.enable;
    hideMounts = true;
    directories = [
      "/var/log"
      "/var/lib/bluetooth"
      "/var/lib/nixos"
      "/var/lib/systemd/coredump"
      "/etc/NetworkManager/system-connections"
    ];
    files = [
      "/etc/machine-id"
      { file = "/var/keys/secret_file"; parentDirectory = { mode = "u=rwx,g=,o="; }; }
    ];
    users."${config.monorepo.vars.userName}" = {
      directories = [
        "Downloads"
        "music"
        "Pictures"
        "Documents"
        "Videos"
        "Monero"
        "org"
        "monorepo"
        "soundfont"
        "website_html"
        "ardour"
        "audacity"
        "img"
        "email"
        "projects"
        "secrets"

        ".emacs.d"
        ".elfeed"
        ".electrum"
        ".mozilla"
        ".bitmonero"
        ".config"
        ".crypto"
        { directory = ".gnupg"; mode = "0700"; }
        { directory = ".ssh"; mode = "0700"; }
        { directory = ".local/share/keyrings"; mode = "0700"; }
        ".local/share/direnv"
      ];
      files = [
        ".emacs"
      ];
    };
  };
}

7.29. Nixpkgs

{ lib, config, isIntegrationTest, ... }:
{
  nixpkgs = lib.mkIf (! isIntegrationTest) {
    hostPlatform = lib.mkDefault "x86_64-linux";
    config = {
      allowUnfree = true;
      cudaSupport = lib.mkDefault config.monorepo.profiles.cuda.enable;
    };
    config.permittedInsecurePackages = [
      "python3.13-ecdsa-0.19.1"
      "olm-3.2.16"
    ];
  };
}

7.30. Main Configuration

This is the backbone of the all the NixOS configurations, with all these options being shared because they enhance security.

{ config, pkgs, lib, ... }:
let
  userGroups = [
    "nginx"
    "git"
    "ircd"
    "ngircd"
    "conduit"
    "livekit"
    "matterbridge"
    "maddy"
    "ntfy-sh"
    "public-inbox"
    "plugdev"
  ];
  allDomains = 
    (lib.attrNames config.networking.domains.baseDomains) ++ 
    (lib.attrNames config.networking.domains.subDomains);

  # 2. Generate BOTH possible outcomes in advance
  prodHosts = map (dom: "${config.monorepo.profiles.server.ipv4} ${dom}") allDomains;
  vmHosts = map (dom: "127.0.0.1 ${dom}") allDomains;
in
{
  environment.etc."wpa_supplicant.conf".text = ''
country=CA
'';
  systemd.tmpfiles.rules = [
    "d /srv/git 0755 git git -"
  ];

  zramSwap = lib.mkIf config.monorepo.profiles.desktop.enable {
    enable = true;
    algorithm = "zstd";
    memoryPercent = 50;
  };

  # Shim for testing
  virtualisation.vmVariant = {
    sops.validateSopsFiles = false;
    disko.devices = lib.mkForce {};

    virtualisation.forwardPorts = lib.mkIf config.monorepo.profiles.server.enable [
      { from = "host"; host.port = 10443; guest.port = 443; }
      { from = "host"; host.port = 9080; guest.port = 80; }
    ];

    virtualisation.useNixStoreImage = false;

    virtualisation.sharedDirectories.sops-keys = {
      source = "/home/preston/.config/sops/age";
      target = "/home/preston/.config/sops/age";
    };

    networking.extraHosts = lib.mkForce (lib.concatStringsSep "\n" vmHosts);
    networking.defaultGateway = lib.mkForce null;

    networking.interfaces.eth0.useDHCP = lib.mkForce true;

    fileSystems."/" = lib.mkForce {
      device = "/dev/disk/by-label/nixos";
      fsType = "ext4";
    };
    systemd.services.sops-nix = {
      unitConfig.RequiresMountsFor = "/home/preston/.config/sops/age";
    };

    security.acme.defaults.server = lib.mkForce "https://127.0.0.1:14000/dir";
  };

  documentation = {
    enable = lib.mkDefault config.monorepo.profiles.documentation.enable;
    man.enable = lib.mkDefault config.monorepo.profiles.documentation.enable;
    dev.enable = lib.mkDefault config.monorepo.profiles.documentation.enable;
  };

  environment = {
    etc = {
      securetty.text = ''
        # /etc/securetty: list of terminals on which root is allowed to login.
        # See securetty(5) and login(1).
      '';
    };
  };


  systemd.network.enable = lib.mkDefault config.monorepo.profiles.server.enable;
  systemd.network.networks."40-${config.monorepo.profiles.server.interface}" = lib.mkIf config.monorepo.profiles.server.enable {
    matchConfig.Name = "${config.monorepo.profiles.server.interface}";
    networkConfig = {
      IPv6AcceptRA = true;
      IPv6PrivacyExtensions = false;
    };
    ipv6AcceptRAConfig = {
      UseAutonomousPrefix = false;
    };
  };

  systemd = {
    services.NetworkManager-wait-online.enable = false;
    coredump.enable = false;
    network.config.networkConfig.IPv6PrivacyExtensions = "kernel";
    tmpfiles.settings = {
      "restrictetcnixos"."/etc/nixos/*".Z = {
        mode = "0000";
        user = "root";
        group = "root";
      };
    };
  };


  boot = {
    supportedFilesystems = {
      btrfs = true;
      ext4 = true;
    };

    extraModprobeConfig = ''
  options snd-usb-audio vid=0x1235 pid=0x8200 device_setup=1
  options rtw88_core disable_lps_deep=y power_save=0 disable_aspm_l1ss=y
  options rtw88_pci disable_msi=y disable_aspm=y
  options rtw_core disable_lps_deep=y
  options rtw_pci disable_msi=y disable_aspm=y
  options rtw89_core disable_ps_mode=y
  options rtw89_pci disable_aspm_l1=y disable_aspm_l1ss=y disable_clkreq=y
  options iwlwifi 11n_disable=8 uapsd_disable=1 bt_coex_active=0 disable_11ax=1 power_save=0
'';
    extraModulePackages = [ ];

    initrd = {
      availableKernelModules = [
        "xhci_pci"
        "ahci"
        "usb_storage"
        "sd_mod"
        "nvme"
        "sd_mod"
        "ehci_pci"
        "rtsx_pci_sdmmc"
        "usbhid"
      ];

      kernelModules = [ ];
    };

    lanzaboote = {
      enable = config.monorepo.profiles.secureBoot.enable;
      pkiBundle = "/var/lib/sbctl";
    };

    loader = {
      systemd-boot.enable = lib.mkForce ((! config.monorepo.profiles.grub.enable) && (! config.monorepo.profiles.secureBoot.enable));
      efi.canTouchEfiVariables = lib.mkForce (! config.monorepo.profiles.grub.enable);
    };

    kernelModules = [
      "snd-seq"
      "snd-rawmidi"
      "xhci_hcd"
      "kvm_intel"
      "af_packet"
      "ccm"
      "ctr"
      "cmac"
      "arc4"
      "ecb"
      "michael_mic"
      "gcm"
      "sha256"
      "sha384"
    ];

    kernelParams = [
      "cfg80211.reg_alpha2=CA"
      "usbcore.autosuspend=-1"
      "pcie_aspm=off"
      "pci=noaer"
      "page_alloc.shuffle=1"
      "slab_nomerge"

      # madaidan
      "pti=on"
      "randomize_kstack_offset=on"
      "vsyscall=none"

      # cpu
      "spectre_v2=on"
      "spec_store_bypass_disable=on"
      "tsx=off"
      "l1tf=full,force"
      "kvm.nx_huge_pages=force"

      # hardened
      "extra_latent_entropy"

      # mineral
      "quiet"
    ];

    blacklistedKernelModules = [
      "netrom"
      "rose"

      "adfs"
      "affs"
      "bfs"
      "befs"
      "cramfs"
      "efs"
      "erofs"
      "exofs"
      "freevxfs"
      "f2fs"
      "hfs"
      "hpfs"
      "jfs"
      "minix"
      "nilfs2"
      "ntfs"
      "omfs"
      "qnx4"
      "qnx6"
      "sysv"
      "ufs"
    ];

    kernel.sysctl = if config.monorepo.profiles.server.enable then {
      "net.ipv6.conf.${config.monorepo.profiles.server.interface}.autoconf" = 0;
      "net.ipv6.conf.${config.monorepo.profiles.server.interface}.accept_ra" = 1; 
    } else {
      "kernel.ftrace_enabled" = false;
      "net.core.bpf_jit_enable" = false;
      "kernel.kptr_restrict" = 2;

      # madaidan
      "kernel.smtcontrol" = "on";
      "vm.swappiness" = 1;
      "vm.unprivileged_userfaultfd" = 0;
      "dev.tty.ldisc_autoload" = 0;
      "kernel.kexec_load_disabled" = 1;
      "kernel.sysrq" = 4;
      "kernel.perf_event_paranoid" = 3;

      # net
      "net.ipv4.ip_forward" = 1;
      "net.ipv4.icmp_echo_ignore_broadcasts" = true;
    };
  };

  networking = {
    interfaces = lib.mkIf config.monorepo.profiles.server.enable {
      "${config.monorepo.profiles.server.interface}" = {
        ipv4.addresses = [
          {
            address = config.monorepo.profiles.server.ipv4;
            prefixLength = 24;
          }
        ];
        ipv6.addresses = [
          {
            address = config.monorepo.profiles.server.ipv6;
            prefixLength = 64;
          }
        ];
        useDHCP = lib.mkForce false;
      };
    };

    defaultGateway = lib.mkIf config.monorepo.profiles.server.enable config.monorepo.profiles.server.gateway;
    useDHCP = false;
    tempAddresses = lib.mkIf config.monorepo.profiles.server.enable "disabled";
    extraHosts = lib.mkIf config.monorepo.profiles.server.enable (lib.concatStringsSep "\n" prodHosts);

    domains = lib.mkIf config.monorepo.profiles.server.enable {
      enable = true;
      baseDomains = {
        "${config.monorepo.vars.remoteHost}" = {
          a.data = config.monorepo.profiles.server.ipv4;
          aaaa.data = config.monorepo.profiles.server.ipv6;
        };
        "${config.monorepo.vars.orgHost}" = {
          a.data = config.monorepo.profiles.server.ipv4;
          aaaa.data = config.monorepo.profiles.server.ipv6;
          txt = {
            data = "v=spf1 ip4:${config.monorepo.profiles.server.ipv4} ip6:${config.monorepo.profiles.server.ipv6} -all";
          };
        };
      };
    };


    nameservers = [ "8.8.8.8" "1.1.1.1"];
    dhcpcd.enable = (! config.monorepo.profiles.server.enable);
    networkmanager = {
      enable = lib.mkForce (! config.monorepo.profiles.server.enable); # rpis need network
      wifi = {
        powersave = false;
      };
      ensureProfiles = {
        profiles = {
          home-wifi = {
            connection = {
              id = "TELUS6572";
              permissions = "";
              type = "wifi";
            };
            ipv4 = {
              dns-search = "";
              method = "auto";
            };
            ipv6 = {
              addr-gen-mode = "stable-privacy";
              dns-search = "";
              method = "auto";
            };
            wifi = {
              mac-address-blacklist = "";
              mode = "infrastructure";
              ssid = "TELUS6572";
            };
            wifi-security = {
              auth-alg = "open";
              key-mgmt = "wpa-psk";
              # when someone actually steals my internet then I will be concerned.
              # This password only matters if you actually show up to my house in real life.
              # That would perhaps allow for some nasty networking related shenanigans.
              # I guess we'll cross that bridge when I get there.
              psk = "b4xnrv6cG6GX";
            };
          };
        };
      };
    };
    firewall = {
      allowedTCPPorts = [ 22 11434 ];
      allowedUDPPorts = [ ];
    };
  };

  hardware = {
    wirelessRegulatoryDatabase = true;
    enableAllFirmware = true;
    cpu.intel.updateMicrocode = true;
    graphics.enable = ! config.monorepo.profiles.ttyonly.enable;

    bluetooth = {
      enable = lib.mkDefault config.monorepo.profiles.desktop.enable;
      powerOnBoot = lib.mkDefault config.monorepo.profiles.desktop.enable;
    };
  };

  services = {
    pulseaudio.enable = ! config.monorepo.profiles.pipewire.enable;
    chrony = {
      enable = true;
      enableNTS = true;
      servers = [ "time.cloudflare.com" "ptbtime1.ptb.de" "ptbtime2.ptb.de" ];
    };

    jitterentropy-rngd.enable = true;
    resolved.settings.Resolve.DNSSEC = true;
    usbguard.enable = false;
    dbus.apparmor = "enabled";

    # Misc.
    udev = {
      extraRules = '''';
      packages = if config.monorepo.profiles.workstation.enable then with pkgs; [ 
        platformio-core
        platformio-core.udev
        openocd
      ] else [];
    };

    printing.enable = lib.mkDefault config.monorepo.profiles.workstation.enable;
    udisks2.enable = (! config.monorepo.profiles.ttyonly.enable);
  };

  programs = {
    nix-ld.enable = true;
    zsh.enable = true;
    ssh.enableAskPassword = false;
  };

  security = {
    acme = {
      acceptTerms = true;
      defaults.email = "${config.monorepo.vars.internetName}@gmail.com";
    };
    apparmor = {
      enable = true;
      killUnconfinedConfinables = true;
      packages = with pkgs; [
        apparmor-profiles
      ];
    };

    pam.loginLimits = [
      { domain = "*"; item = "nofile"; type = "-"; value = "32768"; }
      { domain = "*"; item = "memlock"; type = "-"; value = "32768"; }
    ];
    rtkit.enable = true;

    lockKernelModules = true;
    protectKernelImage = true;

    allowSimultaneousMultithreading = true;
    forcePageTableIsolation = true;

    tpm2 = {
      enable = true;
      pkcs11.enable = true;
      tctiEnvironment.enable = true;
    };

    auditd.enable = true;
    audit.enable = true;
    chromiumSuidSandbox.enable = (! config.monorepo.profiles.ttyonly.enable);
    sudo.enable = true;
  };

  xdg.portal = {
    enable = (! config.monorepo.profiles.ttyonly.enable);
    wlr.enable = (! config.monorepo.profiles.ttyonly.enable);
    extraPortals = with pkgs; if (! config.monorepo.profiles.ttyonly.enable) then [
      xdg-desktop-portal-gtk
      xdg-desktop-portal
      xdg-desktop-portal-hyprland
    ] else [];
    config.common.default = "*";
  };

  environment.etc."gitconfig".text = ''
  [init]
  defaultBranch = main
  '';
  environment.extraInit = ''
  umask 0022
  '';
  environment.systemPackages = with pkgs; [
    restic
    sbctl
    gitFull
    git-lfs
    git-lfs-transfer
    vim
    curl
    nmap
    exiftool
    (writeShellScriptBin "new-repo"
      ''
  #!/bin/bash
  cd ${config.users.users.git.home}
  git init --bare "$1"
  vim "$1/description"
  chown -R git:git "$1"
  ''
    )
  ];

  users.groups = lib.genAttrs userGroups (_: lib.mkDefault {});

  users.users = lib.genAttrs userGroups (name: {
    isSystemUser = lib.mkDefault true;
    group = "${name}";
    extraGroups = [ "acme" "nginx" ];
  }) // {
    conduit = {
      isSystemUser = lib.mkDefault true;
      group = "conduit";
      extraGroups = [];
    };
    matterbridge = {
      isSystemUser = lib.mkDefault true;
      group = "matterbridge";
      extraGroups = [];
    };

    public-inbox = {
      isSystemUser = lib.mkDefault true;
      group = "public-inbox";

      extraGroups = [ "acme" "nginx" "git" ];
    };

    ircd = {
      isSystemUser = lib.mkDefault true;
      group = "ircd";
      home = "/home/ircd";
    };

    nginx = {
      group = "nginx";
      isSystemUser = lib.mkDefault true;
      extraGroups = [ "acme" ];
    };

    root.openssh.authorizedKeys.keys = [
      config.monorepo.vars.sshKey
    ];

    git = {
      isSystemUser = true;
      home = "/srv/git";
      shell = "/bin/sh";
      group = "git";
      openssh.authorizedKeys.keys = [
        config.monorepo.vars.sshKey
        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIEF+mcL9nDkzVhCYyYWCIrP+b6oRiiaV509jywbD0Vq nix-on-droid@localhost"
        "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCedJm0yYB0qLah/Y7PqLVgNh6qp+yujssGtuR05KbZLzSnsLUjUMObMyjFB9xTKrSGDqyoMkNe2l5VXMBJ9wBKLbzqMWbkakAWOj7EC/qZ6dFWA075mniwAuWKY/Q8QYohAJbbeU4j0ObWrltd4ar2Ac9vsVyftYF5efg8PEqVdOxzrBn5taY1zCCRjee5ISeRDIovnBbq7x86jsx5VnXTjMN9FZCI2qmz992Sg/PPXpXat+O1YQlG0eBHEny2Ug9gaAYnGOVr6kZKE4lrjz47nrXVXO6lJsNXmuzTVnEgo30DAA3dV4fws/M5ptM5Pgg2qe94HyHWhhmtXOekWmGtP3YxpVe3M/SPl31UL570ZDuuCcpJTsbe90ZyXC3CiSJkLKbmFkfOgZ6DI2LT8KSp09/2NCtZYriLN/nXObn6gQzByGMxVyKNx2hh8ENt9hzTCAk5lYDK3g3wS8eLCY3EH/caEqT9mLZEZeRHtAhtfozo1VJL7sSZ0Zm7wiIxHylwOshh1sYI1gb1MgMqNnrr1t8+8UK+Q0NERQW3yiphG36HXWy/DdCG0EF+N850KbgH1FFur+m+3hZCZCFVp3tGCcOC+bxWMBT3+9yC6LARi5cFjLQaWLsNO5xEs4vqX3+s3QjJ0pAYDkgtoeY2Fbh+imN+JasWn/cSy5p3UdE4ZQ== andrei@kiss"
      ];
    };
    "${config.monorepo.vars.userName}" = {
      openssh.authorizedKeys.keys = [
        config.monorepo.vars.sshKey
      ];

      linger = true;
      initialPassword = "${config.monorepo.vars.userName}";
      isNormalUser = true;
      description = config.monorepo.vars.fullName;
      extraGroups = [ "networkmanager" "wheel" "video" "docker" "jackaudio" "tss" "dialout" "docker" "plugdev" ];
      shell = pkgs.zsh;
      packages = [];
    };
  };

  nix = {
    settings = {
      keep-outputs = true;
      keep-derivations = true;
      auto-optimise-store = true;
      max-jobs = 4; 
      cores = 0;
      substituters = [
        "https://cache.nixos-cuda.org"
      ];
      trusted-public-keys = [
        "cache.nixos-cuda.org:74DUi4Ye579gUqzH4ziL9IyiJBlDpMRn9MBN8oNan9M="
      ];
      experimental-features = "nix-command flakes ca-derivations";
      trusted-users = [ "@wheel" ];
    };
    gc.automatic = true;
  };
  time.timeZone = config.monorepo.vars.timeZone;
  i18n.defaultLocale = "en_CA.UTF-8";
  system.stateVersion = "24.11";
}

7.31. Disko

This is the disko configuration for my continuity system. It features a boot and ext4 partition, with configurable disk.

7.31.1. GPT Common

This is all configuration common to any GPT partitioned drive. I dynamically choose the partitioning scheme based on the options set.

{ config, ... }:
let
  matchSd = builtins.match "/dev/mmcblk[0-9]+" config.monorepo.vars.device != null;
  partitions = if ((builtins.match "/dev/vd[a-z]+" config.monorepo.vars.device) != null) then
              (import ./virtual-machine.nix)
                         else (if matchSd then
                           (import ./sd-card.nix)
                               else 
                                 (import (./. + "/${config.monorepo.vars.fileSystem}.nix")));
  spec = {
    disko.devices = {
      disk = {
        main = {
          type = "disk";
          device = config.monorepo.vars.device;
          content = {
            type = if matchSd then "mbr" else "gpt";
            inherit partitions;
          };
        };
      };
    };
  };
in
{
  monorepo.vars.diskoSpec = spec;
  disko.devices = spec.disko.devices;
}

7.31.2. ESP Boot Partition

{
  type = "EF00";
  content = {
    type = "filesystem";
    format = "vfat";
    mountpoint = "/boot";
    mountOptions = [ "umask=0077" ];
  };
}

7.31.3. Btrfs

This is a fully featured drive configuration and the recommended configuration to install if on a workstation or laptop. Btrfs enables you to enable impermanence and also encrypt the drive with /tmp/secret.key.

{
  ESP = (import ./esp-boot.nix) // {
    size = "512M";
  };
  luks = {
    size = "100%";
    content = {
      type = "luks";
      name = "crypted";
      passwordFile = "/tmp/secret.key";
      content = {
        type = "btrfs";
        extraArgs = [ "-f" ];
        subvolumes = {
          "/root" = {
            mountpoint = "/";
            mountOptions = [
              "compress=zstd"
              "noatime"
            ];
          };

          "/home" = {
            mountpoint = "/home";
            mountOptions = [
              "compress=zstd"
              "noatime"
            ];
          };

          "/nix" = {
            mountpoint = "/nix";
            mountOptions = [
              "compress=zstd"
              "noatime"
            ];
          };

          "/persistent" = {
            mountpoint = "/persistent";
            mountOptions = [
              "compress=zstd"
              "noatime"
            ];
          };
        };
      };
    };
  };
}

7.31.4. Ext4

This configuration is used for simple partitioning schemes with EFI. A simple ext4 disk with no encryption or any fancy features. You should be using EFI if you can.

{
  ESP = (import ./esp-boot.nix) // {
    size = "500M";
    priority = 1;
  };
  root = {
    size = "100%";
    priority = 2;
    content = {
      type = "filesystem";
      format = "ext4";
      mountpoint = "/";
    };
  };
}

7.31.5. Virtual Machine

This configuration is meant for virtual machines where BIOS is the only option.

{
  boot = {
    size = "1M";
    type = "EF02";
  };
  root = {
    label = "disk-main-root"; 
    size = "100%";
    content = {
      type = "filesystem";
      format = "ext4";
      mountpoint = "/";
    };
  };
}

7.31.6. TODO SD Card

{
  boot = {};
  root = {};
}

7.32. Home

7.32.1. Default Home Profile

As you can see, I have my installed home packages installed based on the profiles enabled. Also, I have many imports that we'll go through next.

{ lib, config, pkgs, sops-nix, super, ... }:
let
  dirContents = builtins.readDir ./.;
  files = lib.filterAttrs (name: type: type == "regular" && lib.hasSuffix ".nix" name && name != "default.nix" && name != "emacs-packages.nix") dirContents;
in
{
  imports = [
    sops-nix.homeManagerModules.sops
  ] ++ lib.mapAttrsToList (name: _: ./. + "/${name}") files;

  options = {
    monorepo.profiles = {
      enable = lib.mkEnableOption "Enables home manager desktop configuration";
      # Programs
      graphics.enable = lib.mkEnableOption "Enables graphical programs for user";
      lang-c.enable = lib.mkEnableOption "Enables C language support";
      lang-sh.enable = lib.mkEnableOption "Enables sh language support";
      lang-rust.enable = lib.mkEnableOption "Enables Rust language support";
      lang-python.enable = lib.mkEnableOption "Enables python language support";
      lang-sol.enable = lib.mkEnableOption "Enables solidity language support";
      lang-openscad.enable = lib.mkEnableOption "Enables openscad language support";
      lang-js.enable = lib.mkEnableOption "Enables javascript language support";
      lang-nix.enable = lib.mkEnableOption "Enables nix language support";
      lang-idris.enable = lib.mkEnableOption "Enables idris language support";
      lang-agda.enable = lib.mkEnableOption "Enables agda language support";
      lang-coq.enable = lib.mkEnableOption "Enables coq language support";
      lang-lean.enable = lib.mkEnableOption "Enables lean language support";
      lang-haskell.enable = lib.mkEnableOption "Enables haskell language support";
      crypto.enable = lib.mkEnableOption "Enables various cryptocurrency wallets";
      art.enable = lib.mkEnableOption "Enables various art programs";
      music.enable = lib.mkEnableOption "Enables mpd";
      workstation.enable = lib.mkEnableOption "Enables workstation packages (music production and others)";
      cuda.enable = lib.mkEnableOption "Enables CUDA user package builds";
      hyprland.enable = lib.mkEnableOption "Enables hyprland";
      email.enable = lib.mkEnableOption "Enables email";
    };
  };

  config = {
    home.packages = (if config.monorepo.profiles.email.enable then [ pkgs.mu ] else [])
                    ++
                    (if config.monorepo.profiles.lang-c.enable then (with pkgs; [
                      autobuild
                      clang
                      gdb
                      gnumake
                      bear
                      clang-tools
                      autotools-language-server
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.workstation.enable then (with pkgs; [
                      mumble
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-js.enable then (with pkgs; [
                      nodejs
                      bun
                      yarn
                      typescript
                      typescript-language-server
                      vscode-langservers-extracted
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-rust.enable then (with pkgs; [
                      cargo
                      rust-analyzer
                      rustfmt
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-python.enable then (with pkgs; [
                      poetry
                      python3
                      python314Packages.python-lsp-server
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-sol.enable then (with pkgs; [
                      solc
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-openscad.enable then (with pkgs; [
                      openscad
                      openscad-lsp
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-sh.enable then (with pkgs; [
                      bash-language-server
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-haskell.enable then (with pkgs; [
                      haskell-language-server
                      haskellPackages.hlint
                      ghc
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-coq.enable then (with pkgs; [
                      coq
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-lean.enable then (with pkgs; [
                      lean4
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-agda.enable then (with pkgs; [
                      agda
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-idris.enable then (with pkgs; [
                      idris
                      idris2Packages.idris2Lsp
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-nix.enable then (with pkgs; [
                      nil
                      nixd
                      nixfmt
                      nix-prefetch-scripts
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.crypto.enable then (with pkgs; [
                      bitcoin
                      monero-cli
                      monero-gui
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.art.enable then (with pkgs; [
                      inkscape
                      krita
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.music.enable then (with pkgs; [
                      mpc
                      sox
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.workstation.enable then (with pkgs; [
                      alsa-utils
                      alsa-scarlett-gui
                      ardour
                      audacity
                      blender
                      foxdot
                      fluidsynth
                      qjackctl
                      qsynth
                      qpwgraph
                      imagemagick
                      supercollider
                      inkscape
                      kdePackages.kdenlive
                      kicad
                    ]) else []);

    monorepo.profiles = {
      enable = lib.mkDefault super.monorepo.profiles.home.enable;
      music.enable = lib.mkDefault config.monorepo.profiles.enable;
      email.enable = lib.mkDefault config.monorepo.profiles.enable;
      cuda.enable = lib.mkDefault super.monorepo.profiles.cuda.enable;

      # Programming
      graphics.enable = lib.mkDefault (! super.monorepo.profiles.ttyonly.enable);
      hyprland.enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
      lang-c.enable = lib.mkDefault config.monorepo.profiles.enable;
      lang-rust.enable = lib.mkDefault config.monorepo.profiles.enable;
      lang-python.enable = lib.mkDefault config.monorepo.profiles.enable;
      lang-sol.enable = lib.mkDefault config.monorepo.profiles.enable;
      lang-sh.enable = lib.mkDefault config.monorepo.profiles.enable;
      lang-openscad.enable = lib.mkDefault config.monorepo.profiles.enable;
      lang-js.enable = lib.mkDefault config.monorepo.profiles.enable;
      lang-nix.enable = lib.mkDefault config.monorepo.profiles.enable;
      lang-coq.enable = lib.mkDefault config.monorepo.profiles.enable;
      lang-lean.enable = lib.mkDefault config.monorepo.profiles.enable;
      lang-haskell.enable = lib.mkDefault config.monorepo.profiles.enable;
      lang-idris.enable = lib.mkDefault config.monorepo.profiles.enable;
      lang-agda.enable = lib.mkDefault config.monorepo.profiles.enable;

      crypto.enable = lib.mkDefault config.monorepo.profiles.enable;
      art.enable = lib.mkDefault config.monorepo.profiles.enable;
      workstation.enable = lib.mkDefault super.monorepo.profiles.workstation.enable;
    };
  };
}

7.32.2. Secrets

These are some secrets that I use regularly for my programs in home.

{ config, super, ... }:
{
  sops = {
    defaultSopsFile = if config.monorepo.profiles.graphics.enable
                      then ../../secrets/secrets.yaml
                      else ../../secrets/vps_secrets.yaml;

    age = {
      keyFile = "/home/${super.monorepo.vars.userName}/.config/sops/age/keys.txt";
    };

    secrets = if super.monorepo.profiles.desktop.enable then {
      mail = {
        format = "yaml";
        path = "${config.sops.defaultSymlinkPath}/mail";
      };
      cloudflare-dns = {
        format = "yaml";
        path = "${config.sops.defaultSymlinkPath}/cloudflare-dns";
      };
      digikey = {
        format = "yaml";
        path = "${config.sops.defaultSymlinkPath}/digikey";
      };
      dn42 = {
        format = "yaml";
        path = "${config.sops.defaultSymlinkPath}/dn42";
      };

      ntfy = {
        format = "yaml";
        path = "${config.sops.defaultSymlinkPath}/${super.monorepo.vars.ntfySecret}";
        sopsFile = ../../secrets/common_secrets.yaml;
      };
    } else {
    };
    defaultSymlinkPath = "/run/user/1000/secrets";
    defaultSecretsMountPoint = "/run/user/1000/secrets.d";
  };
}

7.32.3. Firefox

I conditionally enable metamask based on the cryptocurrency option. Everything else here should be straightforward.

{ lib, config, pkgs, ... }:
{
  programs.librewolf = {
    enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
    package = pkgs.librewolf;
    profiles = {
      default = {
        id = 0;
        name = "default";
        isDefault = true;

        extensions.packages = with pkgs.nur.repos.rycee.firefox-addons; [
          ublock-origin
          tree-style-tab
          firefox-color
          vimium
          privacy-redirect
        ] ++ (lib.optional config.monorepo.profiles.crypto.enable pkgs.nur.repos.rycee.firefox-addons.metamask);
        settings = {
          "privacy.resistFingerprinting.letterboxing" = true;
        };
      };
    };
  };
}

7.32.4. Fcitx

This is a virtual keyboard program for writing in multiple languages. I use this sometimes.

{ config, pkgs, lib, ... }:
{
  i18n.inputMethod = {
    type = "fcitx5";
    enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
    fcitx5.addons = if config.monorepo.profiles.graphics.enable then (with pkgs; [
      fcitx5-gtk
      qt6Packages.fcitx5-chinese-addons
      qt6Packages.fcitx5-configtool
      fcitx5-mozc
      fcitx5-rime
    ]) else [];
  };
}

Note that I configure fcitx with chinese and some japanese input enabled.

7.32.5. Emacs

I install all my emacs packages within Nix so that they build deterministically with native compilation, and because I can fetch their exact versions. Note that I have a stub configuration here that tells emacs to load my real configuration at ~/monorepo/config/emacs.org as an org file which gets automatically tangled to an emacs-lisp file.

{ lib, config, pkgs, super, ... }:
{
  programs.emacs = 
    {
      enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
      package = pkgs.emacs-pgtk;
      extraConfig = ''
(setq debug-on-error t)
(setq system-email "${super.monorepo.vars.email}")
(setq system-username "${super.monorepo.vars.internetName}")
(setq system-fullname "${super.monorepo.vars.fullName}")
(setq system-gpgkey "${super.monorepo.vars.gpgKey}")
(load "${pkgs.writeText "init.el" (builtins.readFile ../../init.el)}")
'';

      extraPackages = import ./emacs-packages.nix;
    };
}
7.32.5.1. Emacs Packages

I want to separate out these packages so that my parent flake which builds my website has a list of my packages.

epkgs: [
  epkgs.agda2-mode
  epkgs.all-the-icons
  epkgs.auctex
  epkgs.catppuccin-theme
  epkgs.company
  epkgs.company-solidity
  epkgs.counsel
  epkgs.centaur-tabs
  epkgs.dashboard
  epkgs.doom-themes
  epkgs.doom-modeline
  epkgs.irony
  epkgs.elfeed
  epkgs.elfeed-org
  epkgs.elfeed-tube
  epkgs.elfeed-tube-mpv
  epkgs.elpher
  epkgs.ement
  epkgs.emmet-mode
  epkgs.emms
  epkgs.enwc
  epkgs.evil
  epkgs.evil-collection
  epkgs.evil-commentary
  epkgs.evil-org
  epkgs.f
  epkgs.flycheck
  epkgs.general
  epkgs.gptel
  epkgs.gruvbox-theme
  epkgs.haskell-mode
  epkgs.htmlize
  epkgs.idris-mode
  epkgs.irony-eldoc
  epkgs.ivy
  epkgs.ivy-pass
  epkgs.kiwix
  epkgs.latex-preview-pane
  epkgs.lsp-ivy
  epkgs.lsp-mode
  epkgs.lsp-haskell
  epkgs.lyrics-fetcher
  epkgs.mastodon
  epkgs.magit
  epkgs.magit-delta
  epkgs.mu4e
  epkgs.minuet
  epkgs.nix-mode
  epkgs.org-contrib
  epkgs.org-fragtog
  epkgs.org-journal
  epkgs.org-roam
  epkgs.org-roam-ui
  epkgs.org-superstar
  epkgs.page-break-lines
  epkgs.password-store
  epkgs.pdf-tools
  epkgs.pinentry
  epkgs.platformio-mode
  epkgs.projectile
  epkgs.rustic
  epkgs.scad-mode
  epkgs.simple-httpd
  epkgs.solidity-flycheck
  epkgs.solidity-mode
  epkgs.sudo-edit
  epkgs.telega
  epkgs.treemacs
  epkgs.treemacs-evil
  epkgs.treemacs-magit
  epkgs.treemacs-projectile
  epkgs.treesit-auto
  epkgs.typescript-mode
  epkgs.unicode-fonts
  epkgs.use-package
  epkgs.vterm
  epkgs.wgrep
  epkgs.web-mode
  epkgs.websocket
  epkgs.which-key
  epkgs.writegood-mode
  epkgs.writeroom-mode
  epkgs.yaml-mode
  epkgs.yasnippet
  epkgs.yasnippet-snippets
]

7.32.6. Gammastep

This is a program like redshift for making your screen emit more red and less blue light. Here I have the long and lat set for Vancouver, but you should replace it if you live outside the timezone.

{ lib, config, ... }:
{
  services.gammastep = {
    enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
    provider = "manual";
    latitude = 49.282730;
    longitude = -123.120735;

    temperature = {
      day = 5000;
      night = 3000;
    };

    settings = {
      general = {
        adjustment-method = "wayland";
      };
    };
  };
}

7.32.7. Git

My git configuration uses information set in the vars.nix in order to set configuration options. Make sure those are set correctly. I've set it to sign by default.

{ pkgs, lib, config, super, ... }:
{
  programs.git = {
    enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
    package = pkgs.gitFull;
    lfs.enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
    userName = super.monorepo.vars.fullName;
    userEmail = "${super.monorepo.vars.email}";
    signing = {
      key = super.monorepo.vars.gpgKey;
      signByDefault = true;
    };

    extraConfig = {
      init.defaultBranch = "main";
      credential."mail.${super.monorepo.vars.orgHost}" = {
        username = "${super.monorepo.vars.email}";
        helper = "!f() { test \"$1\" = get && echo \"password=$(cat /run/user/1000/secrets/mail)\"; }; f";
      };

      sendemail = {
        smtpserver = "mail.${super.monorepo.vars.orgHost}";
        smtpuser = "${super.monorepo.vars.email}";
        smtpserverport = 465;
        smtpencryption = "ssl";
      };
    };

    aliases = {
      pl = "pull";
      ps = "push";
      co = "checkout";
      c = "commit";
      a = "add";
      st = "status";
      sw = "switch";
      b = "branch";
    };
  };
}

7.32.8. Hyprland

My compositor/window manager. This automatically starts on startup. Instructions on how to use this component will come soon.

{ lib, config, wallpapers, pkgs, scripts, ... }:
{
  wayland.windowManager.hyprland = {
    enable = lib.mkDefault config.monorepo.profiles.hyprland.enable;
    package = pkgs.hyprland;
    xwayland.enable = true;
    systemd.enable = true;
    settings = {
      "$mod" = "SUPER";
      bezier = [
        "overshot, 0.05, 0.9, 0.1, 1.05"
      ];
      animation = [
        # "workspaces, 1, 10, overshot"
        "windows, 1, 2, default"
        "workspaces, 1, 2, default, slidefade 20%"
      ];
      exec-once = [
        "waybar"
        "swww-daemon --format xrgb"
        "sh -c 'swww img \"$(find ${wallpapers} -type f \\( -iname \"*.jpg\" -o -iname \"*.png\" \\) | shuf -n1)\"'"
        "fcitx5-remote -r"
        "fcitx5 -d --replace"
        "fcitx5-remote -r"
        "emacs"
        "librewolf"
      ];
      env = [
        "LIBVA_DRIVER_NAME,nvidia"
        "XDG_SESSION_TYPE,wayland"
        "GBM_BACKEND,nvidia-drm"
        "__GLX_VENDOR_LIBRARY_NAME,nvidia"
        "ELECTRON_OZONE_PLATFORM_HINT,auto"
      ];

      monitor = [
        "DP-4,2560x1440@165.000000,0x0,1"
        "Unknown-1,disable"
      ];

      layerrule = [
        {
          name = "waybar blur";
          "match:namespace" = "waybar";
          blur = "on";
        }
      ];

      windowrule = [ 
        {
          name = "emacs";
          "match:class" = "emacs";
          workspace = 1;
        }
        {
          name = "librewolf";
          "match:class" = "librewolf";
          workspace = 2;
        }
        {
          name = "chromium-browser";
          "match:class" = "chromium-browser";
          workspace = 2;
        }
        {
          name = "signal";
          "match:class" = "signal";
          workspace = 3;
        }
        {
          name = "Element";
          "match:class" = "Element";
          workspace = 3;
        }
        {
          name = "pavucontrol";
          "match:class" = "pavucontrol";
          workspace = 4;
        }
        {
          name = "qpwgraph";
          "match:class" = "qpwgraph";
          workspace = 4;
        }
        {
          name = "mpv";
          "match:class" = "mpv";
          workspace = 4;
        }
      ];

      bind = [
        "$mod, F, exec, librewolf"
        "$mod, Return, exec, kitty"
        "$mod, E, exec, emacs"
        "$mod, B, exec, bitcoin-qt"
        "$mod, S, exec, pavucontrol"
        "$mod, M, exec, monero-wallet-gui"
        "$mod, V, exec, element-desktop"
        "$mod, C, exec, signal-desktop"
        "$mod, D, exec, wofi --show run"
        "$mod, P, exec, bash ${scripts}/powermenu.sh"
        "$mod, Q, killactive"
        "$mod SHIFT, H, movewindow, l"
        "$mod SHIFT, L, movewindow, r"
        "$mod SHIFT, K, movewindow, u"
        "$mod SHIFT, J, movewindow, d"

        "$mod SHIFT, T, togglefloating"
        "$mod SHIFT, F, fullscreen"

        "$mod, H, movefocus, l"
        "$mod, L, movefocus, r"
        "$mod, K, movefocus, u"
        "$mod, J, movefocus, d"
        ", XF86AudioPlay, exec, mpc toggle"
        ", Print, exec, grim"

        "$mod, right, resizeactive, 30 0"
        "$mod, left, resizeactive, -30 0"
        "$mod, up, resizeactive, 0 -30"
        "$mod, down, resizeactive, 0 30"
      ]
      ++ (
        builtins.concatLists (builtins.genList
          (
            x:
            let
              ws =
                let
                  c = (x + 1) / 10;
                in
                  builtins.toString (x + 1 - (c * 10));
            in
              [
                "$mod, ${ws}, workspace, ${toString (x + 1)}"
                "$mod SHIFT, ${ws}, movetoworkspace, ${toString (x + 1)}"
              ]
          )
          10)
      );
      bindm = [
        "$mod, mouse:272, movewindow"
        "$mod, mouse:273, resizewindow"
        "$mod ALT, mouse:272, resizewindow"
      ];
      binde = [
        ", XF86AudioRaiseVolume, exec, wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%+"
        ", XF86AudioLowerVolume, exec, wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%-"
        ", XF86AudioNext, exec, mpc next"
        ", XF86AudioPrev, exec, mpc prev"
        ", XF86MonBrightnessUp , exec, xbacklight -inc 10"
        ", XF86MonBrightnessDown, exec, xbacklight -dec 10"
      ];
      decoration = {
        blur = {
          enabled = true;
          size = 9;
          passes = 4;
          contrast = 0.8;
          brightness = 1.1;
          noise = 0.02;
          new_optimizations = true;
          ignore_opacity = true;
          xray = false;
        };
        rounding = 5;
      };
      input = {
        scroll_method = "on_button_down";
        scroll_button = 276;
        sensitivity = -0.5;
        kb_options = "caps:swapescape";
        repeat_delay = 300;
        repeat_rate = 50;
        natural_scroll = false;
        touchpad = {
          natural_scroll = true;
          disable_while_typing = true;
          tap-to-click = true;
        };
      };
      cursor = {
        no_hardware_cursors = true;
      };
      misc = {
        force_default_wallpaper = 0;
        disable_hyprland_logo = true;
      };
    };
  };
}

7.32.9. Kitty

I've set my terminal, kitty, to use catppuccin colors.

{ lib, config, ... }:
{
  programs.kitty = {
    enable = lib.mkDefault (config.monorepo.profiles.hyprland.enable && config.monorepo.profiles.graphics.enable);
    settings = {
      enable_audio_bell = false;
      font_family = "Iosevka Nerd Font";
      font_size = 14;
      confirm_os_window_close = 0;
      background_opacity = "0.7";
      # Catppuccin theme
      foreground = "#cdd6f4";
      background = "#1e1e2e";
      selection_foreground = "#1e1e2e";
      selection_background = "#f5e0dc";
      cursor = "#f5e0dc";
      cursor_text_color = "#1e1e2e";
      url_color = "#f5e0dc";
      active_border_color = "#B4BEFE";
      inactive_border_color = "#6C7086";
      bell_border_color = "#F9E2AF";
      wayland_titlebar_color = "#1E1E2E";
      macos_titlebar_color = "#1E1E2E";
      active_tab_foreground = "#11111B";
      active_tab_background = "#CBA6F7";
      inactive_tab_foreground = "#CDD6F4";
      inactive_tab_background = "#181825";
      tab_bar_background = "#11111B";
      mark1_foreground = "#1E1E2E";
      mark1_background = "#B4BEFE";
      mark2_foreground = "#1E1E2E";
      mark2_background = "#CBA6F7";
      mark3_foreground = "#1E1E2E";
      mark3_background = "#74C7EC";
      color0 = "#45475A";
      color8 = "#585B70";
      color1 = "#F38BA8";
      color9 = "#F38BA8";
      color2 = "#A6E3A1";
      color10 = "#A6E3A1";
      color3 = "#F9E2AF";
      color11 = "#F9E2AF";
      color4 = "#89B4FA";
      color12 = "#89B4FA";
      color5 = "#F5C2E7";
      color13 = "#F5C2E7";
      color6 = "#94E2D5";
      color14 = "#94E2D5";
      color7 = "#BAC2DE";
      color15 = "#A6ADC8";
    };
  };
}

7.32.10. Mako

This is my notification system. My flake automatically fetches the notification sound, so you are all set from the get-go!

{ lib, config, sounds, ... }:
{
  services.mako = {
    enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
    settings = {
      on-notify = "exec mpv ${sounds}/polite.ogg --no-config --no-video";
      background-color = "#11111bf8";
      text-color = "#cdd6f4";
      border-color = "#89b4faff";
      border-radius = 1;
      font = "Fira Code 10";
      default-timeout = 3000;
    };
  };
}

7.32.11. Mbsync

Note that in order to use my email configuration, your imaps and smtps servers must be encrypted. This module uses the vars.nix as well as the home default.nix options.

{ lib, config, super, ... }:
{
  programs.mbsync = {
    enable = lib.mkDefault config.monorepo.profiles.email.enable;
    extraConfig = ''
      IMAPAccount ${super.monorepo.vars.internetName}
      Host mail.${super.monorepo.vars.orgHost}
      User ${super.monorepo.vars.email}
      PassCmd "cat ${config.sops.secrets.mail.path}"
      Port 993
      TLSType IMAPS
      AuthMechs *
      CertificateFile /etc/ssl/certs/ca-certificates.crt

      IMAPStore ${super.monorepo.vars.internetName}-remote
      Account ${super.monorepo.vars.internetName}

      MaildirStore ${super.monorepo.vars.internetName}-local
      Path ~/email/${super.monorepo.vars.internetName}/
      Inbox ~/email/${super.monorepo.vars.internetName}/INBOX
      SubFolders Verbatim

      Channel ${super.monorepo.vars.internetName} 
      Far :${super.monorepo.vars.internetName}-remote:
      Near :${super.monorepo.vars.internetName}-local:
      Patterns *
      Create Near
      Sync All
      Expunge None
      SyncState *
    '';
  };
}

7.32.12. MSMTP

This is the program I use to send email from emacs. It is really the same thing as above, just set the options to the ones you want in your system default.nix.

{ lib, config, super, ... }:
{
  programs.msmtp = {
    enable = lib.mkDefault config.monorepo.profiles.email.enable;
    extraConfig = ''
      # Set default values for all following accounts.
      defaults
      auth           on
      tls            on
      tls_trust_file /etc/ssl/certs/ca-certificates.crt
      tls_certcheck  off
      logfile        ~/.msmtp.log

      # Gmail
      account        ${super.monorepo.vars.internetName}
      host           mail.${super.monorepo.vars.orgHost}
      port           587
      from           ${super.monorepo.vars.email}
      user           ${super.monorepo.vars.email}
      passwordeval   "cat ${config.sops.secrets.mail.path}"


      # Set a default account
      account default : ${super.monorepo.vars.internetName}
    '';
  };
}

7.32.13. Mpd

This mpd configuration uses pipewire by default, and it should just work if you place music in the ~/music directory and then run mpc add / afterwards.

{ lib, config, super, ... }:
{
  services.mpd = {
  enable = lib.mkDefault config.monorepo.profiles.music.enable;
  dbFile = "/home/${super.monorepo.vars.userName}/.config/mpd/db";
  dataDir = "/home/${super.monorepo.vars.userName}/.config/mpd/";
  network.port = 6600;
  musicDirectory = "/home/${super.monorepo.vars.userName}/music";
  playlistDirectory = "/home/${super.monorepo.vars.userName}/.config/mpd/playlists";
  network.listenAddress = "0.0.0.0";
  extraConfig = ''
      audio_output {
        type            "pipewire"
        name            "pipewire output"
      }

      audio_output {
        type    "httpd"
        name    "Ret2pop's Music Stream"
        encoder   "opus"
        port    "8000"
        bitrate   "128000"
        format    "48000:16:1"
        always_on       "yes"
        tags            "yes"
      }

      audio_output {
        type            "shout"
        name            "My VPS Stream"
        host            "127.0.0.1"
        port            "8888"
        mount           "/stream"
        password        "SuperSecretSourcePass"
        bitrate         "128"
        format          "44100:16:2"
        protocol        "icecast2"
        user            "source"
        description     "My MPD Stream"
        genre           "Mixed"
    }
    '';
  };
}

7.32.14. MPV

I have some emacs + yt-dlp integrations with mpv with my rss feed, and therefore we need it here:

{ lib, config, ... }:
{
  programs.mpv = {
    enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
    config = {
      profile = "gpu-hq";
      force-window = true;
      ytdl-format = "bestvideo+bestaudio";
      cache-default = 4000000;
    };
  };
}

7.32.15. GTK

{ lib, config, pkgs, ... }:
{
  config = lib.mkIf config.monorepo.profiles.graphics.enable {
    gtk = {
      theme = {
        name = "catppuccin-mocha-pink-standard";
        package = pkgs.catppuccin-gtk.override {
          variant = "mocha";
          accents = [ "pink" ];
        };
      };
    };
    xdg.configFile = {
      "gtk-4.0/assets".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/assets";
      "gtk-4.0/gtk.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk.css";
      "gtk-4.0/gtk-dark.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk-dark.css";

      "gtk-3.0/gtk.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-3.0/gtk.css";
      "gtk-3.0/gtk-dark.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-3.0/gtk-dark.css";
      "gtk-3.0/settings.ini".text = ''
      [Settings]
      gtk-theme-name=${config.gtk.theme.name}
      gtk-application-prefer-dark-theme=1
    '';
    };
  };
}

7.32.16. Waybar

This is the bar I use for my hyprland configuration. You will need to adjust the monitors field in the default.nix for it to really appear.

{ lib, config, super, ... }:
{
  programs.waybar = {
    enable = lib.mkDefault config.monorepo.profiles.hyprland.enable;
    style = ''
      * {
          border: none;
          border-radius: 0px;
          font-family: Iosevka Nerd Font, FontAwesome, Noto Sans CJK;
          font-size: 14px;
          font-style: normal;
          min-height: 0;
      }

      window#waybar {
          background: rgba(30, 30, 46, 0.5);
          border-bottom: 1px solid #45475a;
          color: #cdd6f4;
      }

      #workspaces {
        background: #45475a;
        margin: 5px 5px 5px 5px;
        padding: 0px 5px 0px 5px;
        border-radius: 16px;
        border: solid 0px #f4d9e1;
        font-weight: normal;
        font-style: normal;
      }
      #workspaces button {
          padding: 0px 5px;
          border-radius: 16px;
          color: #a6adc8;
      }

      #workspaces button.active {
          color: #f4d9e1;
          background-color: transparent;
          border-radius: 16px;
      }

      #workspaces button:hover {
        background-color: #cdd6f4;
        color: black;
        border-radius: 16px;
      }

      #custom-date, #clock, #battery, #pulseaudio, #network, #custom-randwall, #custom-launcher {
        background: transparent;
        padding: 5px 5px 5px 5px;
        margin: 5px 5px 5px 5px;
        border-radius: 8px;
        border: solid 0px #f4d9e1;
      }

      #custom-date {
        color: #D3869B;
      }

      #custom-power {
        color: #24283b;
        background-color: #db4b4b;
        border-radius: 5px;
        margin-right: 10px;
        margin-top: 5px;
        margin-bottom: 5px;
        margin-left: 0px;
        padding: 5px 10px;
      }

      #tray {
          background: #45475a;
          margin: 5px 5px 5px 5px;
          border-radius: 16px;
          padding: 0px 5px;
          /*border-right: solid 1px #282738;*/
      }

      #clock {
          color: #cdd6f4;
          background-color: #45475a;
          border-radius: 0px 0px 0px 24px;
          padding-left: 13px;
          padding-right: 15px;
          margin-right: 0px;
          margin-left: 10px;
          margin-top: 0px;
          margin-bottom: 0px;
          font-weight: bold;
          /*border-left: solid 1px #282738;*/
      }

      #battery {
          color: #89b4fa;
      }

      #battery.charging {
          color: #a6e3a1;
      }

      #battery.warning:not(.charging) {
          background-color: #f7768e;
          color: #f38ba8;
          border-radius: 5px 5px 5px 5px;
      }

      #backlight {
          background-color: #24283b;
          color: #db4b4b;
          border-radius: 0px 0px 0px 0px;
          margin: 5px;
          margin-left: 0px;
          margin-right: 0px;
          padding: 0px 0px;
      }

      #network {
          color: #f4d9e1;
          border-radius: 8px;
          margin-right: 5px;
      }

      #pulseaudio {
          color: #f4d9e1;
          border-radius: 8px;
          margin-left: 0px;
      }

      #pulseaudio.muted {
          background: transparent;
          color: #928374;
          border-radius: 8px;
          margin-left: 0px;
      }

      #custom-randwall {
          color: #f4d9e1;
          border-radius: 8px;
          margin-right: 0px;
      }

      #custom-launcher {
          color: #e5809e;
          background-color: #45475a;
          border-radius: 0px 24px 0px 0px;
          margin: 0px 0px 0px 0px;
          padding: 0 20px 0 13px;
          /*border-right: solid 1px #282738;*/
          font-size: 20px;
      }

      #custom-launcher button:hover {
          background-color: #FB4934;
          color: transparent;
          border-radius: 8px;
          margin-right: -5px;
          margin-left: 10px;
      }

      #custom-playerctl {
        background: #45475a;
        padding-left: 15px;
        padding-right: 14px;
        border-radius: 16px;
        /*border-left: solid 1px #282738;*/
        /*border-right: solid 1px #282738;*/
        margin-top: 5px;
        margin-bottom: 5px;
        margin-left: 0px;
        font-weight: normal;
        font-style: normal;
        font-size: 16px;
      }

      #custom-playerlabel {
          background: transparent;
          padding-left: 10px;
          padding-right: 15px;
          border-radius: 16px;
          /*border-left: solid 1px #282738;*/
          /*border-right: solid 1px #282738;*/
          margin-top: 5px;
          margin-bottom: 5px;
          font-weight: normal;
          font-style: normal;
      }

      #window {
          background: #45475a;
          padding-left: 15px;
          padding-right: 15px;
          border-radius: 16px;
          /*border-left: solid 1px #282738;*/
          /*border-right: solid 1px #282738;*/
          margin-top: 5px;
          margin-bottom: 5px;
          font-weight: normal;
          font-style: normal;
      }

      #custom-wf-recorder {
          padding: 0 20px;
          color: #e5809e;
          background-color: #1E1E2E;
      }

      #cpu {
          background-color: #45475a;
          /*color: #FABD2D;*/
          border-radius: 16px;
          margin: 5px;
          margin-left: 5px;
          margin-right: 5px;
          padding: 0px 10px 0px 10px;
          font-weight: bold;
      }

      #memory {
          background-color: #45475a;
          /*color: #83A598;*/
          border-radius: 16px;
          margin: 5px;
          margin-left: 5px;
          margin-right: 5px;
          padding: 0px 10px 0px 10px;
          font-weight: bold;
      }

      #disk {
          background-color: #45475a;
          /*color: #8EC07C;*/
          border-radius: 16px;
          margin: 5px;
          margin-left: 5px;
          margin-right: 5px;
          padding: 0px 10px 0px 10px;
          font-weight: bold;
      }

      #custom-hyprpicker {
          background-color: #45475a;
          /*color: #8EC07C;*/
          border-radius: 16px;
          margin: 5px;
          margin-left: 5px;
          margin-right: 5px;
          padding: 0px 11px 0px 9px;
          font-weight: bold;
      }
    '';
    settings = {
      mainBar = {
        layer = "top";
        position = "top";
        height = 50;

        output = super.monorepo.vars.monitors;

        modules-left = [ "hyprland/workspaces" ];
        modules-center = [ "hyprland/window" ];
        modules-right = [ "battery" "clock" ];

        battery = {
          format = "{icon}  {capacity}%";
          format-icons = ["" "" "" "" "" ];
        };

        clock = {
          format = "⏰ {:%a %d, %b %H:%M}";
        };
      };
    };
  };
}

7.32.17. Wofi

This is a run launcher for wayland. I also use it for my powermenu.

{ lib, config, ... }:
{
  programs.wofi = {
    enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
    settings = {
      location = "bottom-right";
      allow_markup = true;
      show = "drun";
      width = 750;
      height = 400;
      always_parse_args = true;
      show_all = false;
      term = "kitty";
      hide_scroll = true;
      print_command = true;
      insensitive = true;
      prompt = "Run what, Commander?";
      columns = 2;
    };

    style = ''
      @define-color rosewater  #f5e0dc;
      @define-color rosewater-rgb  rgb(245, 224, 220);
      @define-color flamingo  #f2cdcd;
      @define-color flamingo-rgb  rgb(242, 205, 205);
      @define-color pink  #f5c2e7;
      @define-color pink-rgb  rgb(245, 194, 231);
      @define-color mauve  #cba6f7;
      @define-color mauve-rgb  rgb(203, 166, 247);
      @define-color red  #f38ba8;
      @define-color red-rgb  rgb(243, 139, 168);
      @define-color maroon  #eba0ac;
      @define-color maroon-rgb  rgb(235, 160, 172);
      @define-color peach  #fab387;
      @define-color peach-rgb  rgb(250, 179, 135);
      @define-color yellow  #f9e2af;
      @define-color yellow-rgb  rgb(249, 226, 175);
      @define-color green  #a6e3a1;
      @define-color green-rgb  rgb(166, 227, 161);
      @define-color teal  #94e2d5;
      @define-color teal-rgb  rgb(148, 226, 213);
      @define-color sky  #89dceb;
      @define-color sky-rgb  rgb(137, 220, 235);
      @define-color sapphire  #74c7ec;
      @define-color sapphire-rgb  rgb(116, 199, 236);
      @define-color blue  #89b4fa;
      @define-color blue-rgb  rgb(137, 180, 250);
      @define-color lavender  #b4befe;
      @define-color lavender-rgb  rgb(180, 190, 254);
      @define-color text  #cdd6f4;
      @define-color text-rgb  rgb(205, 214, 244);
      @define-color subtext1  #bac2de;
      @define-color subtext1-rgb  rgb(186, 194, 222);
      @define-color subtext0  #a6adc8;
      @define-color subtext0-rgb  rgb(166, 173, 200);
      @define-color overlay2  #9399b2;
      @define-color overlay2-rgb  rgb(147, 153, 178);
      @define-color overlay1  #7f849c;
      @define-color overlay1-rgb  rgb(127, 132, 156);
      @define-color overlay0  #6c7086;
      @define-color overlay0-rgb  rgb(108, 112, 134);
      @define-color surface2  #585b70;
      @define-color surface2-rgb  rgb(88, 91, 112);
      @define-color surface1  #45475a;
      @define-color surface1-rgb  rgb(69, 71, 90);
      @define-color surface0  #313244;
      @define-color surface0-rgb  rgb(49, 50, 68);
      @define-color base  #1e1e2e;
      @define-color base-rgb  rgb(30, 30, 46);
      @define-color mantle  #181825;
      @define-color mantle-rgb  rgb(24, 24, 37);
      @define-color crust  #11111b;
      @define-color crust-rgb  rgb(17, 17, 27);

      * {
        font-family: 'Iosevka Nerd Font', monospace;
        font-size: 14px;
      }

      /* Window */
      window {
        margin: 0px;
        padding: 10px;
        border: 0.16em solid @lavender;
        border-radius: 0.1em;
        background-color: @base;
        animation: slideIn 0.5s ease-in-out both;
      }

      /* Slide In */
      @keyframes slideIn {
        0% {
           opacity: 0;
        }

        100% {
           opacity: 1;
        }
      }

      /* Inner Box */
      #inner-box {
        margin: 5px;
        padding: 10px;
        border: none;
        background-color: @base;
        animation: fadeIn 0.5s ease-in-out both;
      }

      /* Fade In */
      @keyframes fadeIn {
        0% {
           opacity: 0;
        }

        100% {
           opacity: 1;
        }
      }

      /* Outer Box */
      #outer-box {
        margin: 5px;
        padding: 10px;
        border: none;
        background-color: @base;
      }

      /* Scroll */
      #scroll {
        margin: 0px;
        padding: 10px;
        border: none;
        background-color: @base;
      }

      /* Input */
      #input {
        margin: 5px 20px;
        padding: 10px;
        border: none;
        border-radius: 0.1em;
        color: @text;
        background-color: @base;
        animation: fadeIn 0.5s ease-in-out both;
      }

      #input image {
          border: none;
          color: @red;
      }

      #input * {
        outline: 4px solid @red!important;
      }

      /* Text */
      #text {
        margin: 5px;
        border: none;
        color: @text;
        animation: fadeIn 0.5s ease-in-out both;
      }

      #entry {
        background-color: @base;
      }

      #entry arrow {
        border: none;
        color: @lavender;
      }

      /* Selected Entry */
      #entry:selected {
        border: 0.11em solid @lavender;
      }

      #entry:selected #text {
        color: @mauve;
      }

      #entry:drop(active) {
        background-color: @lavender!important;
      }
    '';
  };
}

7.32.18. yt-dlp

A classic program that allows you to download from youtube. Also has integrations with mpv.

{ lib, config, ... }:
{
  programs.yt-dlp = {
    enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
    settings = {
      embed-thumbnail = true;
      embed-subs = true;
      sub-langs = "all";
      downloader = "aria2c";
      downloader-args = "aria2c:'-c -x8 -s8 -k1M'";
    };
  };
}

7.32.19. pantalaimon

{ lib, ... }:
{
  services.pantalaimon = {
    enable = lib.mkDefault false;
    settings = {
      Default = {
        LogLevel = "Debug";
        SSL = true;
      };

      local-matrix = {
        Homeserver = "https://matrix.nullring.xyz";
        ListenAddress = "127.0.0.1";
        ListenPort = 8008;
      };
    };

  };
}

7.32.20. Zsh

My zsh config has some useful aliases that one should read through. Otherwise it is pretty standard.

{ pkgs, systemHostName, super, ... }:
{
  programs.zsh = {
    enable = true;
    initContent = ''
    umask 0022
    export EXTRA_CCFLAGS="-I/usr/include"
    source ${pkgs.zsh-vi-mode}/share/zsh-vi-mode/zsh-vi-mode.plugin.zsh
    export QT_QPA_PLATFORM="wayland"
    export OLLAMA_MODEL="qwen3:14b"
    '';

    localVariables = {
      EDITOR = "emacsclient --create-frame --alternate-editor=vim";
      INPUT_METHOD = "fcitx";
      QT_IM_MODULE = "fcitx";
      GTK_IM_MODULE = "fcitx";
      XMODIFIERS = "@im=fcitx";
      XIM_SERVERS = "fcitx";
      WXSUPPRESS_SIZER_FLAGS_CHECK = "1";
    };

    shellAliases = {
      clone-secrets = "git clone ssh://\"$1\"/home/preston/secrets \"$HOME/secrets\"";
      get-channel-id = "yt-dlp --print \"%(channel_id)s\" --playlist-end 1 \"$1\"";
      se = "sops edit";
      f = "vim $(fzf)";
      e = "cd $(find . -type d -print | fzf)";
      c = "clear";
      g = "git";
      v = "vim";
      py = "python3";
      build-installer = "nix build $HOME/monorepo/nix#nixosConfigurations.installer.config.system.build.isoImage";
      rb = "sudo nixos-rebuild switch --flake $HOME/monorepo/nix#${systemHostName}";
      nfu = "cd ~/monorepo/nix && git add . && git commit -m \"new flake lock\" &&  nix flake update";
      usync =  "rsync -azvP --chmod=\"Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r\" ~/monorepo/result/ root@${super.monorepo.vars.remoteHost}:/var/www/${super.monorepo.vars.internetName}-website/";
      usite
      = "cd ~/src/publish-org-roam-ui && bash local.sh && rm -rf ~/website_html/graph_view; cp -r ~/src/publish-org-roam-ui/out ~/website_html/graph_view && rsync -azvP --chmod=\"Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r\" ~/website_html/ root@${super.monorepo.vars.remoteHost}:/var/www/${super.monorepo.vars.internetName}-website/";
      sai = "eval \"$(ssh-agent -s)\" && ssh-add ~/.ssh/id_ed25519 && ssh-add -l";
    };
    loginExtra = ''
      if [[ "$(tty)" = "/dev/tty1" ]]; then
          exec Hyprland
      fi
    '';
  };
}

7.32.21. User

This configuration is the backbone configuration for the default user. It specifies some generally useful packages and something every home should have, as well as some dependencies for these configurations.

{ lib, config, pkgs, super, ... }:
{
  home = {
    activation.startup-files = lib.hm.dag.entryAfter [ "installPackages" ] ''
    if [ ! -d "/home/${super.monorepo.vars.userName}/email/${super.monorepo.vars.internetName}/" ]; then
      mkdir -p /home/${super.monorepo.vars.userName}/email/${super.monorepo.vars.internetName}/
    fi

    if [ ! -d "/home/${super.monorepo.vars.userName}/music" ]; then
      mkdir -p /home/${super.monorepo.vars.userName}/music
    fi

    if [ ! -d /home/${super.monorepo.vars.userName}/org ]; then
      mkdir -p /home/${super.monorepo.vars.userName}/org
    fi

    if [ ! -d /home/${super.monorepo.vars.userName}/src ]; then
      mkdir -p /home/${super.monorepo.vars.userName}/src
    fi

    touch /home/${super.monorepo.vars.userName}/org/agenda.org
    touch /home/${super.monorepo.vars.userName}/org/notes.org
    '';

    enableNixpkgsReleaseCheck = false;
    username = super.monorepo.vars.userName;
    homeDirectory = "/home/${super.monorepo.vars.userName}";
    stateVersion = "24.11";

    packages = with pkgs; (if config.monorepo.profiles.graphics.enable then [
      # wikipedia
      # kiwix kiwix-tools
      gnupg
      unzip
      mupdf
      zathura

      fzf
      # passwords
      age sops

      # formatting
      ghostscript texliveFull pandoc

      # Emacs Deps
      graphviz jq

      # Apps
      octaveFull
      grim swww vim kotatogram-desktop tg qwen-code element-desktop signal-desktop signal-cli thunderbird jami

      # Sound/media
      pavucontrol alsa-utils imagemagick ffmpeg helvum

      # Net
      curl rsync gitFull iamb ungoogled-chromium

      # Tor
      torsocks tor-browser

      # For transfering secrets onto new system
      stow

      # fonts
      nerd-fonts.iosevka noto-fonts noto-fonts-cjk-sans noto-fonts-color-emoji fira-code font-awesome_6 victor-mono
      (aspellWithDicts
        (dicts: with dicts; [ en en-computers en-science ]))

      # Misc.
      pinentry-gnome3
      x11_ssh_askpass
      xdg-utils
      acpilight
      pfetch
      libnotify
      htop

      (pkgs.writeShellScriptBin "help"
        ''
#!/usr/bin/env sh
# Portable, colored, nicely aligned alias list

# Generate uncolored alias pairs
aliases=$(cat <<'EOF'
${let aliases = config.programs.zsh.shellAliases;
  in lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value:
    "${name} -> ${value}"
  ) aliases)}
EOF
                               )

# Align and color using awk
echo "$aliases" | awk '
BEGIN {
    GREEN="\033[0;32m";
    YELLOW="\033[0;33m";
    RESET="\033[0m";
    maxlen=0;
               }
{
    # Split line on " -> "
    split($0, parts, / -> /);
    name[NR]=parts[1];
    cmd[NR]=parts[2];
    if(length(parts[1])>maxlen) maxlen=length(parts[1]);
}
END {
    for(i=1;i<=NR;i++) {
        # printf with fixed width for alias name
        printf "%s%-*s%s -> %s%s%s\n", GREEN, maxlen, name[i], RESET, YELLOW, cmd[i], RESET;
        }
}'
'')

      (writeShellScriptBin "remote-build"
        ''
#!/bin/bash
nixos-rebuild --sudo --ask-sudo-password --target-host "$1" switch --flake $HOME/monorepo#spontaneity
''
      )
      (writeShellScriptBin "install-vps"
        ''
#!/bin/bash
nix run github:nix-community/nixos-anywhere -- --generate-hardware-config nixos-generate-config $HOME/monorepo/nix/systems/spontaneity/hardware-configuration.nix --flake $HOME/monorepo/nix#spontaneity --target-host "$1"
        '')
      (writeShellScriptBin "secrets"
        ''
#!/bin/bash
cd "$HOME/secrets"
git pull # repo is over LAN
stow */ # manage secrets with gnu stow
cd "$HOME"
        '')
      (writeShellScriptBin "spontaneity-ci"
        ''
#!/bin/bash
nixos-rebuild build-vm --flake $HOME/monorepo/nix#spontaneity && QEMU_OPTS="-serial stdio" ./result/bin/run-spontaneity-vm 2>&1 | tee vm-boot.log'')
    ] else [
      pfetch
      # net
      curl
      torsocks
      rsync
    ]);
  };

  services = {
    gpg-agent = {
      pinentry.package = pkgs.pinentry-emacs;
      enable = true;
      extraConfig = ''
      allow-emacs-pinentry
      allow-loopback-pinentry
    '';
    };
  };
  xdg.mimeApps = {
    enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
    defaultApplications = {
      "x-scheme-handler/mailto" = "emacsclient-mail.desktop";
        "text/html" = "librewolf.desktop";
        "text/xml" = "librewolf.desktop";
        "application/xhtml+xml" = "librewolf.desktop";
        "x-scheme-handler/http" = "librewolf.desktop";
        "x-scheme-handler/https" = "librewolf.desktop";
        "x-scheme-handler/about" = "librewolf.desktop";
        "x-scheme-handler/unknown" = "librewolf.desktop";
    };
  };

  programs.bash.enable = true;
  fonts.fontconfig.enable = true;
}

8. Systems

8.1. Home

This module dynamically imports the correct corresponding home.nix at the path.

{ config, sops-nix, ... }:
{
  home-manager = {
    backupFileExtension = "backup";
    sharedModules = [
      sops-nix.homeManagerModules.sops
    ];
    extraSpecialArgs = {
      super = config;
    };
    useGlobalPkgs = true;
    useUserPackages = true;
    users."${config.monorepo.vars.userName}" = (import (./. + "/${config.networking.hostName}/home.nix"));
  };
}

8.2. Common

These are the common includes for each of my systems. This ensures that we don't have to duplicate includes every time we want to add a new system. Also more common configuration can go here.

{ ... }:
{
  imports = [
    ./home.nix
    ../modules/default.nix
    ../disko/gpt-common.nix
  ];
  # Put configuration (e.g. monorepo variable configuration) common to all configs here
}

8.2.1. Home Manager Common

Also I want to have the same kind of file for the home namespace.

{ ... }:
{
  imports = [
    ../modules/home/default.nix
  ];
  # Put configuration (e.g. monorepo variable configuration) common to all configs here
}

8.3. Continuity

This is pretty understandable, if you understand all the above.

{ ... }:
{
  imports = [
    ../common.nix
  ];
  config = {
    monorepo = {
      profiles = {
        impermanence.enable = true;
        desktop.enable = true;
      };
      vars = {
        device = "/dev/sda";
        fileSystem = "btrfs";
      };
    };
  };
}

8.3.1. Home

Each system has a corresponding home configuration in order to set monorepo home options.

{ ... }:
{
  imports = [
    ../home-common.nix
  ];
}

8.4. Affinity

This is my configuration for my workstation. It runs ollama, as well as several other useful services.

{ ... }:
{
  imports = [
    ../common.nix
  ];
  config = {
    monorepo = {
      vars.device = "/dev/nvme0n1";
      vars.fileSystem = "ext4";
      profiles = {
        cuda.enable = true;
        workstation.enable = true;
      };
    };
  };
}

8.4.1. Home

I want cuda in home manager too.

{ ... }:
{
  imports = [
    ../home-common.nix
  ];
}

8.5. rpi-zero

{ ... }:
{
  imports = [
    ../common.nix
  ];
  config = {
    zramSwap = {
      enable = true;
      algorithm = "zstd";
      memoryPercent = 100;
    };
    boot.loader.grub.enable = false;
    boot.loader.generic-extlinux-compatible.enable = true;
    monorepo = {
      vars.device = "/dev/mmcblk0";
      profiles = {
        ttyonly.enable = true;
      };
    };
  };
}

8.5.1. Home

{ ... }:
{
  imports = [
    ../home-common.nix
  ];
  config.monorepo.profiles.enable = false;
}

8.6. Spontaneity

Spontaneity is my VPS instance. Note that much of this is not fully reproducible; you must change the IPs yourself and you must change some DNS records to match what you have on your system after deployment.

{ ... }:
{
  imports = [
    ../common.nix
    # nixos-anywhere generates this file
    ./hardware-configuration.nix
  ];
  config = {
    monorepo = {
      vars.device = "/dev/vda";
      profiles = {
        server = {
          enable = true;
          ipv4 = "66.42.84.130";
          gateway = "66.42.84.1";
          ipv6 = "2001:19f0:5401:10d0:5400:5ff:fe4a:7794";
          interface = "ens3";
        };
        grub.enable = true;
        pipewire.enable = false;
        tor.enable = false;
      };
    };
    boot.loader.grub.device = "nodev";
  };
}

8.7. Home

{ ... }:
{
  imports = [
    ../home-common.nix
  ];
}

8.8. Installer

My installer installs my systems almost completely without interaction. You can also make them install the exact version of the system that you want it to by pinning the commits to make it always work in the exact same deterministic way.

8.8.1. ISO Default Profile

This contains the installation script I use to install my systems.

{ pkgs, lib, modulesPath, disko, monorepoSelf ? null, self, ... }:
let
  commits = {
    diskoCommitHash = disko.rev or "dirty";
    monorepoCommitHash = if monorepoSelf != null then (monorepoSelf.rev or "dirty") else (self.rev or "dirty");
    monorepoUrl = "https://github.com/ret2pop/monorepo";
  };
in
{
  imports = [
    (modulesPath + "/installer/cd-dvd/installation-cd-minimal.nix")
  ];

  networking = {
    networkmanager = {
      enable = true;
    };
    firewall = {
      allowedTCPPorts = [ 22 ];
      allowedUDPPorts = [ ];
    };
    wireless.enable = lib.mkForce false;
  };
  services.openssh = {
    enable = true;
    ports = [ 22 ];
    settings = {
      PasswordAuthentication = false;
      AllowUsers = null;
      UseDns = true;
      PermitRootLogin = lib.mkForce "prohibit-password";
    };
  };

  users.users = {
    root.openssh.authorizedKeys.keys = [
      "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICts6+MQiMwpA+DfFQxjIN214Jn0pCw/2BDvOzPhR/H2 preston@continuity-dell"
    ];
    nixos = {
      packages = with pkgs; [
        gitFull
        curl
        gum
        (writeShellScriptBin "nix_installer"
          ''
#!/usr/bin/env bash

set -euo pipefail

if [ "$(id -u)" -eq 0 ]; then
  echo "ERROR! $(basename "$0") should be run as a regular user"
  exit 1
fi

cd "$HOME"

ping -q -c1 google.com &>/dev/null && echo "online! Proceeding with the installation..." || nmtui

if [ ! -d "$HOME/monorepo/" ]; then
  git clone ${commits.monorepoUrl} --recurse-submodules
  cd "$HOME/monorepo"
  git checkout "${commits.monorepoCommitHash}"
  cd "$HOME"
fi

gum style --border normal --margin "1" --padding "1 2" "Enter a password for the encrypted disk. If you're not installing a profile with an encrypted disk, you can leave this blank."
echo "$(gum input --password)" > /tmp/secret.key

gum style --border normal --margin "1" --padding "1 2" "Choose a system to install or select \`new\` in order to create a new system."

SYSTEM="$(gum choose $(find "$HOME/monorepo/nix/systems" -mindepth 1 -maxdepth 1 -type d -printf "%f\n" | grep -v -E 'installer'; printf "New"))"

if [[ "$SYSTEM" == "New" ]]; then
  gum style --border normal --margin "1" --padding "1 2" "Choose a system name"
  SYSTEM="$(gum input --placeholder "system name")"

  gum style --border normal --margin "1" --padding "1 2" "Select a drive file or create a new drive file."
  DRIVE="$(gum choose $(find "$HOME/monorepo/nix/disko" -mindepth 1 -maxdepth 1 -type f -printf "%f\n"; printf "New"))"

  if [[ "$DRIVE" == "New" ]]; then
    gum style --border normal --margin "1" --padding "1 2" "Choose a name to call your drive file."
    DRIVE="$(gum input --placeholder "drive file name (ex: partition_scheme.nix)")"
  fi
fi


if [ ! -d "$HOME/monorepo/nix/systems/$SYSTEM" ]; then
  mkdir -p "$HOME/monorepo/nix/systems/$SYSTEM"
  cp "$HOME/monorepo/nix/systems/continuity/home.nix" "$HOME/monorepo/nix/systems/$SYSTEM/home.nix"
  cat > "$HOME/monorepo/nix/systems/$SYSTEM/default.nix" <<EOF
{ ... }:
{
  imports = [
    ../includes.nix
    ../../disko/$DRIVE
  ];
  # CHANGEME
  config.monorepo.vars.drive = "/dev/sda";
}
EOF

  gum style --border normal --margin "1" --padding "1 2" "Edit the system default.nix with options."
  gum input --placeholder "Press Enter to continue" >/dev/null
  vim "$HOME/monorepo/nix/systems/$SYSTEM/default.nix"

  gum style --border normal --margin "1" --padding "1 2" "Edit the home default.nix with options."
  gum input --placeholder "Press Enter to continue" >/dev/null
  vim "$HOME/monorepo/nix/systems/$SYSTEM/home.nix"

  sed -i "/hostnames = \[/,/];/ s/];/  \"$1\"\n    ];/" "$HOME/monorepo/nix/flake.nix"

  if [ ! -f "$HOME/monorepo/nix/disko/$DRIVE" ]; then
    cp "$HOME/monorepo/nix/disko/drive-simple.nix" "$HOME/monorepo/nix/disko/$DRIVE"
    gum style --border normal --margin "1" --padding "1 2" "Edit the drive file with your preferred partitioning scheme."
    gum input --placeholder "Press Enter to continue" >/dev/null
    vim "$HOME/monorepo/nix/disko/$DRIVE"
  fi
  cd "$HOME/monorepo" && git add . && cd "$HOME"
fi

nix --extra-experimental-features 'nix-command flakes' eval "$HOME/monorepo/nix#evalDisko.$SYSTEM" > "$HOME/drive.nix"

gum style --border normal --margin "1" --padding "1 2" "Formatting the drive is destructive!"
if gum confirm "Are you sure you want to continue?"; then
    echo "Proceeding..."
else
    echo "Aborting."
    exit 1
fi

sudo nix --experimental-features "nix-command flakes" run "github:nix-community/disko/${commits.diskoCommitHash}" -- --mode destroy,format,mount "$HOME/drive.nix"

cd /mnt
sudo nixos-install --flake "$HOME/monorepo/nix#$SYSTEM"

target_user="$(ls /mnt/home | head -n1)"
if [ -z "$target_user" ]; then
    echo "No user directories found in /mnt/home"
    exit 1
fi
sudo cp -r "$HOME/monorepo" "/mnt/home/$target_user/"

echo "rebooting..."; sleep 3; reboot
'')
      ];
    };
  };

  systemd = {
    services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ];
    targets = {
      sleep.enable = false;
      suspend.enable = false;
      hibernate.enable = false;
      hybrid-sleep.enable = false;
    };
  };
}