home | section main page | rss feed


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"
    # "rpi-zero"
  ];
}

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";
    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";
    };
    catppuccin-qutebrowser = {
      url = "github:catppuccin/qutebrowser";
      flake = false;
    };
  };

  outputs = {
    self,
      nixpkgs,
      home-manager,
      nur,
      disko,
      lanzaboote,
      sops-nix,
      nix-topology,
      nixos-dns,
      impermanence,
      git-hooks,
      ...
  }
    @attrs:
      let
        vars = import ./flakevars.nix;
        generate = nixos-dns.utils.generate nixpkgs.legacyPackages."${system}";
       
        rpiCheck = hostname: (builtins.match "rpi-.*" hostname) != null;
        noRpi = builtins.filter (hostname: (! rpiCheck hostname));
        noInstaller = builtins.filter (hostname: (hostname != "installer"));
        filterHosts = noInstaller (noRpi vars.hostnames);
        system = "x86_64-linux";
        getSystem = hostname: if rpiCheck hostname
                              then "aarch64-linux"
                              else "x86_64-linux";
                             
        pkgs = import nixpkgs { inherit system; };
       
        dnsConfig = {
          inherit (self) nixosConfigurations;
          extraConfig = import ./dns/default.nix;
        };
       
        commonModules = hostname: [
          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")
        ];
       
        mkHostModules = hostname:
          if (hostname == "installer") then [
            (./. + "/systems/${hostname}/default.nix")
            { networking.hostName = "${hostname}"; }
            nix-topology.nixosModules.default
          ] else (if (rpiCheck hostname)
                  then (commonModules hostname) ++ [
                    "${nixpkgs}/nixos/modules/installer/sd-card/sd-image-aarch64.nix"
                  ]
                  else (commonModules hostname));
                 
        # function that generates all systems from hostnames
        mkConfigs = map (hostname: {
          name = "${hostname}";
          value = nixpkgs.lib.nixosSystem {
            system = getSystem hostname;
            specialArgs = attrs // {
              system = (getSystem hostname);
              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;
                      system = getSystem hostname;
                      monorepoSelf = null;
                    };
                    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 (noInstaller vars.hostnames));
        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 (if config.monorepo.profiles.server.enable then {
      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";
      };
    } else {});
  };
}

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-clock" = {
        "context.properties" = {
          "default.clock.rate" = 48000;
          "default.clock.allowed-rates" = [ 48000 ];
         
          "default.clock.quantum" = 2048;
          "default.clock.min-quantum" = 1024;
          "default.clock.max-quantum" = 4096;
         
          "default.clock.quantum-limit" = 8192;
        };
      };
     
      pipewire-pulse."92-obs-very-stable" = {
        "pulse.properties" = {
          "pulse.min.req" = "1024/48000";
          "pulse.default.req" = "2048/48000";
          "pulse.max.req" = "4096/48000";
         
          "pulse.min.quantum" = "512/48000";
          "pulse.max.quantum" = "4096/48000";
        };
       
        "stream.properties" = {
          "node.latency" = "2048/48000";
          "node.max-latency" = "4096/48000";
          "resample.quality" = 10;
        };
      };
    };
  };
}

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.services.ollama.enable;
    port = 11111;
    host = "127.0.0.1";
    environment = {
      OLLAMA_API_BASE_URL = "http://127.0.0.1:11434";
      # Disable authentication
      WEBUI_AUTH = "False";
    };
  };

  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 [
    ] else [
    ];
    host = "0.0.0.0";
    openFirewall = true;
  };
}

7.19. Bitcoind

{ config, lib, ... }:
{
  services.bitcoind."${config.monorepo.vars.userName}" = {
    enable = lib.mkDefault false;
    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;
        quic = true;
       
        locations."/" = {
          extraConfig = ''
  add_header Cache-Control "no-cache, must-revalidate";
  add_header Alt-Svc 'h3=":443"; ma=86400';
  include ${monorepoSelf.packages.${pkgs.system}.website}/csp_header.conf;
  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";
  add_header Alt-Svc 'h3=":443"; ma=86400';
  include ${monorepoSelf.packages.${pkgs.system}.website}/csp_header.conf;
  access_log off;
      '';
        };
        extraConfig = ''
  rewrite ^/graph_view/?(.*)$ https://graph.${config.monorepo.vars.remoteHost}/$1 permanent;
  error_page 404 /404.html;
  '';
      };
     
      # 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;
        quic = true;
        locations."/" = {
          extraConfig = ''
  add_header Alt-Svc 'h3=":443"; ma=86400';
  rewrite ^/$ /graph_view/index.html break;
  '';
        };
      };
    };
  };

  networking.firewall.allowedTCPPorts = lib.mkIf config.services.nginx.enable [ 80 443 ];
  networking.firewall.allowedUDPPorts = lib.mkIf config.services.nginx.enable [ 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.monorepo.profiles.server.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, pkgs, ... }:
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-git-credentials" = {
        owner = "public-inbox";
        group = "public-inbox";
        mode = "0400";
        content = (builtins.concatStringsSep "\n" (builtins.map (x: 
          "imaps://${x}%40${config.monorepo.vars.orgHost}:${config.sops.placeholder."mail_monorepo_password_pi"}@${emailServerName}"
        ) config.monorepo.vars.projects)) + "\nimaps://discussion%40${config.monorepo.vars.orgHost}:${config.sops.placeholder."mail_monorepo_password_pi"}@${emailServerName}";
      };
     
      "public-inbox-netrc" = {
        owner = "public-inbox";
        group = "public-inbox";
        mode = "0400";
        content = (builtins.concatStringsSep "\n" (builtins.map (x: "machine ${emailServerName} login ${x}%40${config.monorepo.vars.orgHost} password ${config.sops.placeholder."mail_monorepo_password_pi"}") config.monorepo.vars.projects)) + ''
  machine ${emailServerName} login discussion%40${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;
    path = [ pkgs.git ];
    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
export HOME=/var/lib/public-inbox
git config --global credential.helper "store --file /run/secrets/rendered/public-inbox-git-credentials"
'';
    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";
      GIT_TERMINAL_PROMPT = "0";
      GIT_CONFIG_COUNT = "1";
      GIT_CONFIG_KEY_0 = "credential.helper";
      GIT_CONFIG_VALUE_0 = "store --file /run/secrets/rendered/public-inbox-git-credentials";
    };
   
    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}%40${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;
  };

}
<LAMBDA>

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

We must put Nixpkgs in another configuration because we don't want to include it if isIntegrationTest is set.

{ lib, config, isIntegrationTest, system, ... }:
{
  nixpkgs = lib.mkIf (! isIntegrationTest) {
    hostPlatform = lib.mkDefault system;
    buildPlatform = lib.mkIf (system == "aarch64-linux") (lib.mkDefault "x86_64-linux");
    overlays = [
    ];
    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. QTile

{ lib, config, ... }:
{
    services.xserver.windowManager.qtile = {
    enable = lib.mkDefault config.monorepo.profiles.desktop.enable;
   
    extraPackages = python3Packages: with python3Packages; [
      qtile-extras
    ];
  };
}

7.31. Libinput

{ lib, config, ... }:
{
  services.libinput = {
    enable = lib.mkDefault config.monorepo.profiles.desktop.enable;
    mouse = {
      dev = "/dev/input/by-id/usb-047d_80fd-event-mouse";
      scrollMethod = "button";
      scrollButton = 276;
    };
  };
}

7.32. 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, system, ... }:
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);
   
  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 = {
    enable = true;
    algorithm = "zstd";
    memoryPercent = lib.mkDefault 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
    options brcmfmac roamoff=1 feature_disable=0x82000
  '';
    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)) && (system != "aarch64-linux"));
      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"
      "uvcvideo"
    ];
   
    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 = lib.mkDefault (system == "x86_64-linux");
    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 = system != "aarch64-linux";
      pkcs11.enable = true;
      tctiEnvironment.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);
      settings = {
        screencast = {
          chooser_type = "none";
          output_name = "DP-1";
        };
      };
    };
    extraPortals = with pkgs; if (! config.monorepo.profiles.ttyonly.enable) then [
      xdg-desktop-portal-gtk
      xdg-desktop-portal
      xdg-desktop-portal-wlr
    ] else [];
    config.common.default = "*";
  };

  systemd.user.services.xdg-desktop-portal-wlr = {
    serviceConfig = {
      Restart = lib.mkForce "on-failure";
    };
    environment = {
      XDG_CURRENT_DESKTOP = "qtile";
      XDG_SESSION_TYPE = "wayland";
    };
  };

  environment.etc."gitconfig".text = ''
    [init]
    defaultBranch = main
    '';
  environment.extraInit = ''
    umask 0022
    '';
  environment.systemPackages = with pkgs;  [
    restic
    sbctl
    gitFull
    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"
    ''
    )
  ] ++ (if system != "aarch64-linux" then [ git-lfs ] else []);

  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.33. Disko

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

7.33.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, lib, ... }:
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 {}
                     else 
                       (import (./. + "/${config.monorepo.vars.fileSystem}.nix")));
  spec = {
    disko.devices = {
      disk = {
        main = {
          type = "disk";
          device = config.monorepo.vars.device;
          content = {
            type = "gpt";
            inherit partitions;
          };
        };
      };
    };
  };
in
{
  monorepo.vars.diskoSpec = spec;
  disko.devices = lib.mkIf (! matchSd) spec.disko.devices;
}

7.33.2. ESP Boot Partition

This is a small fragment that can be abstracted away from the EFI boot partition.

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

7.33.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.33.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.33.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.33.6. TODO SD Card

{
  boot = {
    name = "ESP";
    start = "16M";
    end = "516M";
    bootable = true;
    content = {
      type = "filesystem";
      format = "vfat";
      mountpoint = "/boot";
    };
  };

  root = {
    name = "root";
    start = "516M";
    end = "100%";
    content = {
      type = "filesystem";
      format = "btrfs";
      mountpoint = "/";
      mountOptions = [ "compress=zstd" ];
    };
  };
}

7.34. Home

7.34.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";
      lang-scheme.enable = lib.mkEnableOption "Enables scheme language support";
      lang-data.enable = lib.mkEnableOption "Enables markup languages 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.lang-scheme.enable then (with pkgs; [
                      chez
                    ]) 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
                      semgrep
                      ty
                      ruff
                      python314Packages.debugpy
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-sol.enable then (with pkgs; [
                      solc
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-data.enable then (with pkgs; [
                      yaml-language-server
                    ]) 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) && config.monorepo.profiles.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;
      lang-scheme.enable = lib.mkDefault config.monorepo.profiles.enable;
      lang-data.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.34.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.34.3. OBS

{ pkgs, config, ... }:
{
  programs.obs-studio = {
    enable = config.monorepo.profiles.workstation.enable;
    plugins = with pkgs.obs-studio-plugins; [
      wlrobs
    ];
  };
}

7.34.4. 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;
    enable = false;
    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;
        };
      };
    };
  };
}
<LAMBDA>

7.34.5. QuteBrowser

{ lib, config, catppuccin-qutebrowser, ... }:
{
  programs.qutebrowser = {
    enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
    enableDefaultBindings = true;
    searchEngines = {
      g = "https://www.google.com/search?hl=en&amp;q={}";
      w = "https://en.wikipedia.org/wiki/Special:Search?search={}&amp;go=Go&amp;ns0=1";
      aw = "https://wiki.archlinux.org/?search={}";
      nw = "https://wiki.nixos.org/index.php?search={}";
      npk = "https://search.nixos.org/packages?channel=unstable&query={}";
    };
    settings = {
      content.blocking.method = "both";
      fonts.default_family = "Lora";
      fonts.default_size = "12pt";
     
      # Command/completion UI
      fonts.statusbar = "12pt Lora";
      fonts.completion.entry = "12pt Lora";
      fonts.completion.category = "bold 12pt Lora";
      fonts.prompts = "12pt Lora";
     
      # Tabs
      fonts.tabs.selected = "12pt Lora";
      fonts.tabs.unselected = "12pt Lora";
     
      # Hints
      fonts.hints = "bold 12pt Lora";
     
      # Rendering
      qt.force_software_rendering = "chromium";
    };
    extraConfig = (builtins.readFile "${catppuccin-qutebrowser}/setup.py") +
                  ''
config.load_autoconfig()
setup(c, "mocha", True)
'';
  };
}

7.34.6. 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.34.7. 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, self, ... }:
{
  programs.emacs = 
    {
      enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
      package = pkgs.emacs-pgtk;
      extraConfig = ''
  (setq debug-on-error t)
  (setq logo-file "${self}/data/logo.png")
  (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}")
  (setq my-ispell-dictionary "${pkgs.scowl}/share/dict/words.txt")
  (setq my-ispell-args '(
                         "--encoding=iso-8859-1"
                         "--mode=url" 
                         "--data-dir=${pkgs.aspell}/lib/aspell"
                         "--dict-dir=${pkgs.aspellDicts.en}/lib/aspell"))
                         
  (load "${pkgs.writeText "init.el" (builtins.readFile ../../init.el)}")
  '';
     
      extraPackages = import ./emacs-packages.nix;
    };
}
7.34.7.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: with epkgs; [
  aggressive-indent
  all-the-icons
  agda2-mode
  auctex
  catppuccin-theme
  company
  company-box
  company-solidity
  counsel
  centaur-tabs
  dap-mode
  dash
  dashboard
  doom-themes
  doom-modeline
  indent-bars
  irony
  elfeed
  elfeed-org
  elfeed-tube
  elfeed-tube-mpv
  elpher
  ement
  emmet-mode
  emms
  engrave-faces
  enwc
  evil
  evil-collection
  evil-commentary
  evil-multiedit
  evil-mc
  evil-surround
  evil-org
  evil-lion
  evil-textobj-tree-sitter
  f
  flycheck
  geiser
  geiser-chez
  general
  git-gutter
  gptel
  gruvbox-theme
  haskell-mode
  htmlize
  idris-mode
  irony-eldoc
  ivy
  ivy-posframe
  latex-preview-pane
  lsp-ivy
  lsp-mode
  lsp-ui
  lsp-haskell
  lyrics-fetcher
  mastodon
  magit
  magit-delta
  mu4e
  mixed-pitch
  minuet
  nix-mode
  ox-rss
  ob-nix
  org-alert
  org-contrib
  org-ql
  org-super-agenda
  org-fragtog
  org-journal
  org-modern
  org-roam
  org-roam-ui
  pulseaudio-control
  pulsar
  page-break-lines
  password-store
  pdf-tools
  pinentry
  platformio-mode
  projectile
  polymode
  poetry
  rustic
  s
  sops
  solaire-mode
  scad-mode
  simple-httpd
  solidity-flycheck
  solidity-mode
  sudo-edit
  treemacs
  treemacs-evil
  treemacs-magit
  treemacs-projectile
  treemacs-all-the-icons
  all-the-icons-ivy-rich
  treesit-auto
  typescript-mode
  use-package
  vterm
  wgrep
  web-mode
  websocket
  which-key
  writegood-mode
  writeroom-mode
  yaml-mode
  yasnippet
  yasnippet-snippets
]

7.34.8. 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.34.9. iamb

My iamb profile. Note that iamb does not support calling (obviously, as it is a terminal app), but the nice thing about it is that I can set it up declaratively, so in case element-desktop stops working because of lack of declarative setup, I can still use this.

{ super, ... }:
{
  programs.iamb = {
    # enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
    enable = false;
    settings = {
      default_profile = "personal";
      profiles.personal = {
        user_id = "@${super.monorepo.vars.internetName}:matrix.${super.monorepo.vars.orgHost}";
      };
      image_preview.protocol = {
        type = "kitty";
        size = {
          height = 10;
          width = 66;
        };
      };
    };
  };
}

7.34.10. 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;
    userName = super.monorepo.vars.fullName;
    userEmail = super.monorepo.vars.email;
    lfs.enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
   
    signing = {
      key = super.monorepo.vars.gpgKey;
      signByDefault = true;
    };
   
    # alias = {
    #   pl = "pull";
    #   ps = "push";
    #   co = "checkout";
    #   c = "commit";
    #   a = "add";
    #   st = "status";
    #   sw = "switch";
    #   b = "branch";
    # };
   
    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";
      };
     
    };
    # settings = {
    #   user = {
    #     name = super.monorepo.vars.fullName;
    #     email = super.monorepo.vars.email;
    #   };
   
      
    # };
   
    aliases = {
      pl = "pull";
      ps = "push";
      co = "checkout";
      c = "commit";
      a = "add";
      st = "status";
      sw = "switch";
      b = "branch";
    };
  };
}

7.34.11. 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 = "1";
      # 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.34.12. 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.34.13. 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.34.14. 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.34.15. 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";
    };
  };
}

7.34.16. 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.34.17. QTile

{ sounds, wallpapers, pkgs, ... }:
let
  qtilePaths = pkgs.writeText "qtile-paths.py" ''
WALLPAPER = "${wallpapers}/pastel-city.png"
SOUND = "${sounds}/nice.wav"
  '';
in
{
  xdg.configFile."qtile/config.py".source = ../../qtile/config.py;
  xdg.configFile."qtile/paths.py".source = qtilePaths;
}

7.34.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.34.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.34.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 = {
      ret2pop-serve = "devd -ol ~/website_html/";
      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 qtile start -b wayland
        fi
      '';
  };
}

7.34.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";
    sessionVariables = {
      QTWEBENGINE_FORCE_USE_GBM = 0;
      NIXOS_OZONE_WL = 1;
      XDG_SESSION_TYPE = "wayland";
      XDG_CURRENT_DESKTOP = "qtile";
    };
   
    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 element-desktop signal-desktop signal-cli thunderbird jami imv slurp wl-clipboard
     
      # Sound/media
      pavucontrol alsa-utils imagemagick ffmpeg pulseaudio
     
      # Net
      curl rsync gitFull ungoogled-chromium devd
     
      # 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
      nerd-fonts.symbols-only emacs-all-the-icons-fonts lora
     
      aspell
      aspellDicts.en-computers
      aspellDicts.en
      aspellDicts.en-science
     
      # Misc.
      pinentry-gnome3
      x11_ssh_askpass
      xdg-utils
      acpilight
      pfetch
      libnotify
      htop
      minify
      python3Packages.adblock
     
      (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" = "org.qutebrowser.qutebrowser.desktop";
      "text/xml" = "org.qutebrowser.qutebrowser.desktop";
      "application/xhtml+xml" = "org.qutebrowser.qutebrowser.desktop";
      "x-scheme-handler/http" = "org.qutebrowser.qutebrowser.desktop";
      "x-scheme-handler/https" = "org.qutebrowser.qutebrowser.desktop";
      "x-scheme-handler/about" = "org.qutebrowser.qutebrowser.desktop";
      "x-scheme-handler/unknown" = "org.qutebrowser.qutebrowser.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 = {
    boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
    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 = {
    boot = {
      loader = {
        grub.enable = false;
        generic-extlinux-compatible.enable = true;
      };
      initrd.kernelModules = [ "vc4" "bcm2835_dma" "i2c_bcm2835" ];
      kernelParams = [
        "console=ttyS1,115200n8"
      ];
    };
   
    zramSwap.memoryPercent = 100;
    services.gitDaemon.enable = true;
   
    monorepo = {
      vars.device = "/dev/mmcblk0";
      profiles = {
        ttyonly.enable = true;
      };
    };
  };
}

In order to separate the nixpkgs options for my integration tests to set their own, we need to include this in a separate file:

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;
    };
  };
}