home | section main page


NixOS Configuration

Table of Contents

1. Introduction

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

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

2. Configurables

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

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

  # Your internet name
  internetName = internetName;

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

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

3. Flake.nix

The flake is the entry point of the NixOS configuration. Here, I have a list of all the systems that I use with all the modules that they use. My NixOS configuration is heavily modularized, so that adding new configurations that add modifications is made simple.

and now for the main flake:

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

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

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

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

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

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

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

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

    nixpak = {
      url = "github:nixpak/nixpak";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = {
    self,
      nixpkgs,
      home-manager,
      nur,
      disko,
      lanzaboote,
      sops-nix,
      nix-topology,
      nixos-dns,
      deep-research,
      impermanence,
      nixpak,
      ...
  }
    @attrs:
    let
      vars = import ./flakevars.nix;
      system = "x86_64-linux";
      pkgs = import nixpkgs { inherit system; };
      generate = nixos-dns.utils.generate nixpkgs.legacyPackages."${system}";

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

      # function that generates all systems from hostnames
      mkConfigs = map (hostname: {name = "${hostname}";
                                value = nixpkgs.lib.nixosSystem {
                                  inherit system;
                                  specialArgs = attrs;
                                  modules = if (hostname == "installer") then [
                                    (./. + "/systems/${hostname}/default.nix")
                                    { networking.hostName = "${hostname}"; }
                                    nix-topology.nixosModules.default
                                  ] else [
                                    {
                                      environment.systemPackages = with nixpkgs.lib; [
                                        deep-research.packages."${system}".deep-research
                                      ];
                                    }
                                    impermanence.nixosModules.impermanence
                                    nix-topology.nixosModules.default
                                    lanzaboote.nixosModules.lanzaboote
                                    disko.nixosModules.disko
                                    home-manager.nixosModules.home-manager
                                    sops-nix.nixosModules.sops
                                    nixos-dns.nixosModules.dns
                                    {
                                      nixpkgs.overlays = [ nur.overlays.default ];
                                      home-manager.extraSpecialArgs = attrs // { systemHostName = "${hostname}"; };
                                      networking.hostName = "${hostname}";
                                    }
                                    (./. + "/systems/${hostname}/default.nix")
                                  ];
                                };
                               });

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

        evalDisko = builtins.listToAttrs (mkDiskoFiles (builtins.filter (x: x != "installer") 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
            python3
            poetry
            statix
            deadnix
          ];
        };

        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

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.

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

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

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

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

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

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

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

    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, ... }:
{
  imports = [
    ./configuration.nix
    ./vars.nix
  ];

  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";
        home.enable = lib.mkEnableOption "Enables home user";
        server.enable = lib.mkEnableOption "Enables server services";
        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";
        impermanence.enable = lib.mkEnableOption "Enables imperamanence";
      };
    };
  };

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

    monorepo = {
      profiles = {
        documentation.enable = lib.mkDefault true;
        pipewire.enable = lib.mkDefault true;
        tor.enable = lib.mkDefault true;
        home.enable = lib.mkDefault true;
        impermanence.enable = lib.mkDefault false;
      };
    };
  };
}

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.

{ 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 {
      "public-inbox-netrc" = {
        owner = "public-inbox";
        group = "public-inbox";
        mode = "0400";
        content = ''
machine mail.${config.monorepo.vars.orgHost} login monorepo@${config.monorepo.vars.orgHost} password ${config.sops.placeholder."mail_monorepo_password_pi"}
machine mail.${config.monorepo.vars.orgHost} login discussion@${config.monorepo.vars.orgHost} password ${config.sops.placeholder."mail_monorepo_password_pi"}
    '';
      };
      "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.server.enable then {
      mail = {
        format = "yaml";
      };
      cloudflare-dns = {
        format = "yaml";
      };
      digikey = {
        format = "yaml";
      };
      dn42 = {
        format = "yaml";
      };
    } else {
      znc = {
        format = "yaml";
      };
      znc_password_salt = {
        format = "yaml";
      };
      znc_password_hash = {
        format = "yaml";
      };
      matrix_bridge = {
        format = "yaml";
      };
      livekit_secret = {
        format = "yaml";
        mode = "0444";
      };
      livekit = {
        format = "yaml";
      };
      mail_password = {
        format = "yaml";
        owner = "maddy";
      };

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

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

      conduit_secrets = {
        format = "yaml";
      };
      mautrix_env = {
        format = "yaml";
      };
      telegram_token = {
        format = "yaml";
      };
      discord_token = {
        format = "yaml";
      };
      mpd_password = {
        format = "yaml";
        owner = "nginx";
      };
      ntfy = {
        format = "yaml";
        owner = "ntfy-sh";
      };
    };
  };
}

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.

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

    windowManager = {
      i3 = {
        enable = (! config.monorepo.profiles.ttyonly.enable);
      };
    };

    desktopManager = {
      runXdgAutostartIfNone = true;
    };

    xkb = {
      layout = "us";
      variant = "";
      options = "caps:escape";
    };

    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, config, vars, ... }:
{
  # virtualisation = {
  #   oci-containers = {
  #     backend = "podman";
  #     containers = {};
  #   };
  #   containers.enable = true;
  #   podman = {
  #     enable = true;
  #     dockerCompat = true;
  #     defaultNetwork.settings.dns_enabled = true;
  #   };
  # };
}

7.6. Pipewire

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

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

7.7. SSH

My SSH daemon configuration.

{ config, lib, ... }:
{
  services.openssh = {
    enable = true;
    settings = {
      PasswordAuthentication = lib.mkDefault (! config.monorepo.profiles.server.enable);
      AllowUsers = [ config.monorepo.vars.userName "root" "git" ];
      PermitRootLogin = "prohibit-password";
      KbdInteractiveAuthentication = false;
    };
  };
}

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, pkgs, 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:

{ config, lib, ... }:
{
  services.i2pd = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    address = "0.0.0.0";
    inTunnels = {
    };
    outTunnels = {
    };
  };
}

7.11. TODO Icecast

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

{ lib, config, ... }:
{
  services.icecast = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    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>
'';
  };
  admin.password = "changeme";
}

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

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 = "nullring.xyz";
          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, ... }:
{
  services.matrix-conduit = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    secretFile = "/run/secrets/conduit_secrets";
    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.lk-jwt-service = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    port = 6495;
    livekitUrl = "wss://livekit.${config.monorepo.vars.orgHost}";
    keyFile = "/run/secrets/livekit_secret";
  };
  services.livekit = {
    enable = lib.mkDefault config.monorepo.profiles.server.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;
      };
    };
  };
}

7.14. GoToSocial

This is a basic ActivityPub server.

{ lib, config, ... }:
{
  services.gotosocial = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    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. 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.16. TODO matrix-appservice-irc

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

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

7.16.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.17. Ollama

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

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

7.18. Bitcoind

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

7.19. 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 = "/srv/git";
  };
}

7.20. Ntfy

{ pkgs, lib, config, ... }:
{
  services.ntfy-sh = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    settings = {
      base-url = "https://ntfy.${config.monorepo.vars.remoteHost}";
      listen-http = "127.0.0.1:2586";
      envrionmentFile = "/run/secrets/ntfy";
      auth-file = "/var/lib/ntfy-sh/user.db";
      auth-default-access = "deny-all";
      enable-login = true;
    };
  };
  systemd.services.ntfy-sh = {
    serviceConfig = {
      EnvironmentFile = "/run/secrets/ntfy";
    };
    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
    '';
  };
}

7.21. 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.

{ config, lib, ... }:
{
  services.nginx = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    user = "nginx";
    recommendedGzipSettings = true;
    recommendedOptimisation = true;
    recommendedTlsSettings = true;
    recommendedProxySettings = false;

    gitweb = {
      enable = true;
      virtualHost = "${config.monorepo.vars.orgHost}";
    };

    virtualHosts = {
      "matrix.${config.monorepo.vars.orgHost}" = {
        enableACME = true;
        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:6167";
          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}:8443\"}]}'";
        };

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

      "matrix.${config.monorepo.vars.orgHost}-livekit" = {
        serverName = "matrix.${config.monorepo.vars.orgHost}";
        listen = [
          { 
            addr = "0.0.0.0"; 
            port = 8443; 
            ssl = true; 
          }
          {
            addr = "[::]";
            port = 8443;
            ssl = true;
          }
        ];
        addSSL = true;
        enableACME = false;
        forceSSL = false;
        useACMEHost = "matrix.${config.monorepo.vars.orgHost}";

        locations."/" = {
          proxyPass = "http://127.0.0.1:6495"; 
          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;
    '';
        };
      };

      "livekit.${config.monorepo.vars.orgHost}" = {
        enableACME = true;
        forceSSL = true;
        locations."/" = {
          proxyPass = "http://127.0.0.1:7880";
          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 ---
          '';
        };
      };

      "ntfy.${config.monorepo.vars.remoteHost}" = {
        serverName = "ntfy.${config.monorepo.vars.remoteHost}";
        enableACME = true;
        forceSSL = true;
        locations."/" = {
          proxyPass = "http://localhost:2586";
          proxyWebsockets = true;
        };
      };

      "${config.monorepo.vars.remoteHost}" = {
        serverName = "${config.monorepo.vars.remoteHost}";
        serverAliases = [ "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" ];
        root = "/var/www/${config.monorepo.vars.internetName}-website/";
        addSSL = true;
        enableACME = true;
      };

      "list.${config.monorepo.vars.orgHost}" = {
        forceSSL = true;
        enableACME = true;
        locations."/" = {
          proxyPass = "http://localhost:9090";
          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;
        '';
        };
      };

      # the port comes from ssh tunnelling
      "music.${config.monorepo.vars.remoteHost}" = {
        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;
      };

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

7.22. Git Web Interface

I enable the git web interface to show off my git repos to the world. This was the easiest frontend to set up on NixOS.

{ lib, config, ... }:
{
  services.gitweb = {
    gitwebTheme = lib.mkDefault config.monorepo.profiles.server.enable;
    projectroot = "/srv/git/";
    extraConfig = ''
our $export_ok = "git-daemon-export-ok";
our $site_name = "NullRing Git Server";
our $site_header = "NullRing Projects";
'';
  };
}

7.23. 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.24. CUDA

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

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

7.25. Maddy

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

{ lib, config, options, ... }:
{
  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;
    ensureCredentials = {
      "${config.monorepo.vars.internetName}@${config.monorepo.vars.orgHost}" = {
        passwordFile = "/run/secrets/mail_password";
      };
      "monorepo@${config.monorepo.vars.orgHost}" = {
        passwordFile = "/run/secrets/mail_monorepo_password";
      };
      "discussion@${config.monorepo.vars.orgHost}" = {
        passwordFile = "/run/secrets/mail_monorepo_password";
      };
    };
  };
}

7.25.1. Public Inbox

This is my mailing list software that I will use to develop software.

{ lib, config, ... }:
{
  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 = {
      # Allow the service to see the file it just created
      BindPaths = [ 
        "/var/lib/public-inbox" 
      ];
      ReadOnlyPaths = [ "/var/lib/public-inbox/style.css" ];
      # Ensure it can actually write to the directory during preStart
      ReadWritePaths = [ "/var/lib/public-inbox" ];
    };
  } else {};

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

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

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

  services.public-inbox = {
    enable = lib.mkDefault config.monorepo.profiles.server.enable;
    settings = {
      publicinbox.css = ["/var/lib/public-inbox/style.css"];
      publicinbox.wwwlisting = "all";
    };
    http = {
      enable = true;
      port = 9090;
    };
    inboxes = {
      "monorepo" = {
        description = "discussion of ret2pop's monorepo project and related work.";
        address = [ "monorepo@${config.monorepo.vars.orgHost}" ];
        inboxdir = "/var/lib/public-inbox/monorepo";
        url = "https://list.${config.monorepo.vars.orgHost}/monorepo";
        watch = [ "imaps://monorepo%40${config.monorepo.vars.orgHost}@mail.${config.monorepo.vars.orgHost}/INBOX" ];
      };

      "discussion" = {
        description = "Main Nullring Discussion Mailing List";
        address = [ "discussion@${config.monorepo.vars.orgHost}" ];
        inboxdir = "/var/lib/public-inbox/discuss";
        url = "https://list.${config.monorepo.vars.orgHost}/discussion";
        watch = [ "imaps://discussion%40${config.monorepo.vars.orgHost}@mail.${config.monorepo.vars.orgHost}/INBOX" ];
      };
    };
  };
}

7.25.2. 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.26. 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.27. 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.28. 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, ... }:
{
  imports = [
    ./public_inbox.nix
    ./matterbridge.nix
    ./mautrix.nix
    ./xserver.nix
    ./ssh.nix
    ./pipewire.nix
    ./tor.nix
    ./kubo.nix
    ./nvidia.nix
    ./cuda.nix
    ./nginx.nix
    ./secrets.nix
    ./git-daemon.nix
    ./ollama.nix
    ./i2pd.nix
    ./gitweb.nix
    ./conduit.nix
    ./bitcoin.nix
    ./murmur.nix
    ./ngircd.nix
    ./znc.nix
    ./docker.nix
    ./impermanence.nix
    ./coturn.nix
    ./maddy.nix
    ./ntfy-sh.nix
    ./fail2ban.nix
  ];

  environment.etc."wpa_supplicant.conf".text = ''
country=CA
'';

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


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

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

      kernelModules = [ ];
    };

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

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

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

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

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

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

      # hardened
      "extra_latent_entropy"

      # mineral
      # "init_on_alloc=1"
      # "random.trust_bootloader=off"
      # "init_on_free=1"
      "quiet"
      # "loglevel=0"
    ];

    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 = {
      "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;

      # "net.ipv4.conf.all.accept_redirects" = false;
      # "net.ipv4.conf.all.secure_redirects" = false;
      # "net.ipv4.conf.default.accept_redirects" = false;
      # "net.ipv4.conf.default.secure_redirects" = false;
      # "net.ipv6.conf.all.accept_redirects" = false;
      # "net.ipv6.conf.default.accept_redirects" = false;
    };
  };

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

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

    bluetooth = {
      enable = lib.mkDefault (! config.monorepo.profiles.ttyonly.enable);
      powerOnBoot = lib.mkDefault (! config.monorepo.profiles.ttyonly.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 = true;
    usbguard.enable = false;
    dbus.apparmor = "enabled";

    kanata.enable = true;

    # 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;
    light.enable = true;
    ssh.enableAskPassword = false;
  };

  nixpkgs = {
    hostPlatform = lib.mkDefault "x86_64-linux";
    config = {
      allowUnfree = true;
      cudaSupport = lib.mkDefault config.monorepo.profiles.cuda.enable;
    };
  };

  security = {
    acme = {
      acceptTerms = true;
      defaults.email = "ret2pop@gmail.com";
    };
    apparmor = {
      enable = true;
      killUnconfinedConfinables = true;
      packages = with pkgs; [
        apparmor-profiles
      ];
      policies = {
        firefox.path = "${pkgs.apparmor-profiles}/share/apparmor/extra-profiles/firefox";
      };
    };

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

    lockKernelModules = true;
    protectKernelImage = true;

    allowSimultaneousMultithreading = true;
    forcePageTableIsolation = true;

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

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

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

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

  users.groups.nginx = lib.mkDefault {};
  users.groups.git = lib.mkDefault {};
  users.groups.ircd = lib.mkDefault {};
  users.groups.ngircd = lib.mkDefault {};
  users.groups.conduit = lib.mkDefault {};
  users.groups.livekit = lib.mkDefault {};
  users.groups.matterbridge = lib.mkDefault {};
  users.groups.maddy = lib.mkDefault {};
  users.groups.ntfy-sh = lib.mkDefault {};
  users.groups.public-inbox = lib.mkDefault {};

  users.users = {
    conduit = {
      isSystemUser = lib.mkDefault true;
      group = "conduit";
    };
    matterbridge = {
      isSystemUser = lib.mkDefault true;
      group = "matterbridge";
    };

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

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

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

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

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

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

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

    root.openssh.authorizedKeys.keys = [
      "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICts6+MQiMwpA+DfFQxjIN214Jn0pCw/2BDvOzPhR/H2 preston@continuity-dell"
    ];

    git = {
      isSystemUser = true;
      home = "/srv/git";
      shell = "/bin/sh";
      group = "git";
      openssh.authorizedKeys.keys = [
        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICts6+MQiMwpA+DfFQxjIN214Jn0pCw/2BDvOzPhR/H2 preston@continuity-dell"
      ];
    };
    "${config.monorepo.vars.userName}" = {
      openssh.authorizedKeys.keys = [
        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICts6+MQiMwpA+DfFQxjIN214Jn0pCw/2BDvOzPhR/H2 preston@continuity-dell"
      ];

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

  nixpkgs.config.permittedInsecurePackages = [
    "python3.13-ecdsa-0.19.1"
    "olm-3.2.16"
  ];

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

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

7.29.1. Btrfs

{ lib, config, ... }:
let
  spec = {
    disko.devices = {
      disk = {
        main = {
          type = "disk";
          device = config.monorepo.vars.device;
          content = {
            type = "gpt";
            partitions = {
              ESP = {
                size = "512M";
                type = "EF00";
                content = {
                  type = "filesystem";
                  format = "vfat";
                  mountpoint = "/boot";
                  mountOptions = [ "umask=0077" ];
                };
              };
              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"
                        ];
                      };
                    };
                  };
                };
              };
            };
          };
        };
      };
    };
  };
in
{
  monorepo.vars.diskoSpec = spec;
  disko.devices = spec.disko.devices;
}

7.29.2. Simple

This configuration is used for simple partitioning schemes with EFI.

{ lib, config, ... }:
let
  spec = {
    disko.devices = {
      disk = {
        my-disk = {
          device = config.monorepo.vars.device;
          type = "disk";
          content = {
            type = "gpt";
            partitions = {
              ESP = {
                type = "EF00";
                size = "500M";
                priority = 1;
                content = {
                  type = "filesystem";
                  format = "vfat";
                  mountpoint = "/boot";
                  mountOptions = [ "umask=0077" ];
                };
              };
              root = {
                size = "100%";
                priority = 2;
                content = {
                  type = "filesystem";
                  format = "ext4";
                  mountpoint = "/";
                };
              };
            };
          };
        };
      };
    };
  };
in
{
  monorepo.vars.diskoSpec = spec;
  disko.devices = spec.disko.devices;
}

7.29.3. BIOS

For machines that use BIOS instead of EFI.

{ config, lib, ... }:
let
  spec = {
    disko.devices = {
      disk = {
        main = {
          device = config.monorepo.vars.device;
          type = "disk";
          content = {
            type = "gpt";
            partitions = {
              boot = {
                size = "1M";
                type = "EF02";
              };
              root = {
                label = "disk-main-root"; 
                size = "100%";
                content = {
                  type = "filesystem";
                  format = "ext4";
                  mountpoint = "/";
                };
              };
            };
          };
        };
      };
    };
  };
in
{
  monorepo.vars.diskoSpec = spec;
  disko.devices = spec.disko.devices;
}

7.30. Home

7.30.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, ... }:
{
  imports = [
    sops-nix.homeManagerModules.sops
    ../vars.nix
    ./fcitx.nix
    ./emacs.nix
    ./firefox.nix
    ./git.nix
    ./hyprland.nix
    ./mpv.nix
    ./yt-dlp.nix
    ./wofi.nix
    ./kitty.nix
    ./waybar.nix
    ./zsh.nix
    ./mbsync.nix
    ./msmtp.nix
    ./gammastep.nix
    ./mpd.nix
    ./mako.nix
    ./user.nix
    ./gtk.nix
    ./secrets.nix
  ];

  options = {
    monorepo.profiles = {
      enable = lib.mkEnableOption "Enables home manager desktop configuration";
      # Programs
      graphics.enable = lib.mkEnableOption "Enables graphical programs for user";
      lang-c.enable = lib.mkEnableOption "Enables C language support";
      lang-sh.enable = lib.mkEnableOption "Enables sh language support";
      lang-rust.enable = lib.mkEnableOption "Enables Rust language support";
      lang-python.enable = lib.mkEnableOption "Enables python language support";
      lang-sol.enable = lib.mkEnableOption "Enables solidity language support";
      lang-openscad.enable = lib.mkEnableOption "Enables openscad language support";
      lang-js.enable = lib.mkEnableOption "Enables javascript language support";
      lang-nix.enable = lib.mkEnableOption "Enables nix language support";
      lang-idris.enable = lib.mkEnableOption "Enables idris language support";
      lang-agda.enable = lib.mkEnableOption "Enables agda language support";
      lang-coq.enable = lib.mkEnableOption "Enables coq language support";
      lang-lean.enable = lib.mkEnableOption "Enables lean language support";
      lang-haskell.enable = lib.mkEnableOption "Enables haskell language support";

      crypto.enable = lib.mkEnableOption "Enables various cryptocurrency wallets";
      art.enable = lib.mkEnableOption "Enables various art programs";
      music.enable = lib.mkEnableOption "Enables mpd";
      workstation.enable = lib.mkEnableOption "Enables workstation packages (music production and others)";
      cuda.enable = lib.mkEnableOption "Enables CUDA user package builds";
      hyprland.enable = lib.mkEnableOption "Enables hyprland";

      email = {
        email = lib.mkOption {
          type = lib.types.str;
          default = "ret2pop@nullring.xyz";
          example = "john@example.com";
          description = "Email address and imaps/smtps account";
        };
        imapsServer = lib.mkOption {
          type = lib.types.str;
          default = "mail.nullring.xyz";
          example = "imap.example.com";
          description = "imaps server address";
        };
        smtpsServer = lib.mkOption {
          type = lib.types.str;
          default = "mail.nullring.xyz";
          example = "smtp.example.com";
          description = "smtp server address";
        };
        enable = lib.mkEnableOption "Enables email";
      };
    };
  };

  config = {
    home.packages = (if config.monorepo.profiles.email.enable then [ pkgs.mu ] else [])
                    ++
                    (if config.monorepo.profiles.lang-c.enable then (with pkgs; [
                      autobuild
                      clang
                      gdb
                      gnumake
                      bear
                      clang-tools
                      autotools-language-server
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.workstation.enable then (with pkgs; [
                      mumble
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-js.enable then (with pkgs; [
                      nodejs
                      bun
                      yarn
                      typescript
                      typescript-language-server
                      vscode-langservers-extracted
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-rust.enable then (with pkgs; [
                      cargo
                      rust-analyzer
                      rustfmt
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-python.enable then (with pkgs; [
                      poetry
                      python3
                      python314Packages.python-lsp-server
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-sol.enable then (with pkgs; [
                      solc
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-openscad.enable then (with pkgs; [
                      openscad
                      openscad-lsp
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-sh.enable then (with pkgs; [
                      bash-language-server
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-haskell.enable then (with pkgs; [
                      haskell-language-server
                      haskellPackages.hlint
                      ghc
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-coq.enable then (with pkgs; [
                      coq
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-lean.enable then (with pkgs; [
                      lean4
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-agda.enable then (with pkgs; [
                      agda
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-idris.enable then (with pkgs; [
                      idris
                      idris2Packages.idris2Lsp
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.lang-nix.enable then (with pkgs; [
                      nil
                      nixd
                      nixfmt
                      nix-prefetch-scripts
                    ]) else [])
                    ++
                    (if config.monorepo.profiles.crypto.enable then (with pkgs; [
                      bitcoin
                      # electrum
                      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
                      murmur
                    ]) else []);

    monorepo.profiles = {
      enable = lib.mkDefault true;
      music.enable = lib.mkDefault config.monorepo.profiles.enable;
      hyprland.enable = lib.mkDefault config.monorepo.profiles.enable;
      email.enable = lib.mkDefault config.monorepo.profiles.enable;

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

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

7.30.2. Secrets

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

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

    secrets = if config.monorepo.profiles.graphics.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";
      };
    } else {
    };
    defaultSymlinkPath = "/run/user/1000/secrets";
    defaultSecretsMountPoint = "/run/user/1000/secrets.d";
  };
}

7.30.3. Firefox

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

{ lib, config, pkgs, ... }:
{
  programs.firefox = {
    enable = lib.mkDefault config.monorepo.profiles.graphics.enable;
    package = pkgs.firefox;
    policies = {
      EnableTrackingProtection = true;
      OfferToSaveLogins = false;
    };
    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
        ]
        ++ (lib.optional
          config.monorepo.profiles.crypto.enable pkgs.nur.repos.rycee.firefox-addons.metamask);

        settings = {
          media = {
            memory_cache_max_size = 65536;
            cache_readahead_limit = 7200;
            cache_resume_threshold = 3600;
            peerconnection.ice = {
              proxy_only_if_behind_proxy = true;
              default_address_only = true;
            };
          };

          gfx = {
            content.skia-font-cache-size = 20;
            canvas.accelerated = {
              cache-items = 4096;
              cache-size = 512;
            };
          };

          network = {
            http = {
              max-connections = 1800;
              max-persistent-connections-per-server = 10;
              max-urgent-start-excessive-connections-per-host = 5;
              referer.XOriginTrimmingPolicy = 2;
            };

            buffer.cache = {
              size = 262144;
              count = 128;
            };

            dns = {
              max_high_priority_threads = 8;
              disablePrefetch = true;
            };

            pacing.requests.enabled = false;
            dnsCacheExpiration = 3600;
            ssl_tokens_cache_capacity = 10240;
            prefetch-next = false;
            predictor.enabled = false;
            cookie.sameSite.noneRequiresSecure = true;
            IDN_show_punycode = true;
            auth.subresource-http-auth-allow = 1;
            captive-portal-service.enabled = false;
            connectivity-service.enabled = false;
          };

          browser = {
            download = {
              always_ask_before_handling_new_types = true;
              manager.addToRecentDocs = false;
              open_pdf_attachments_inline = true;
              start_downloads_in_tmp_dir = true;
            };

            urlbar = {
              suggest.quicksuggest.sponsored = false;
              suggest.quicksuggest.nonsponsored = false;
              suggest.calculator = true;
              update2.engineAliasRefresh = true;
              unitConversion.enabled = true;
              trending.featureGate = false;
            };

            search = {
              separatePrivateDefault.ui.enabled = true;
              suggest.enabled = false;
            };

            newtabpage.activity-stream = {
              feeds = {
                topsites = false;
                section.topstories = false;
                telemetry = false;
              };
              asrouter.userprefs.cfr = {
                addons = false;
                features = false;
              };
              telemetry = false;
            };

            privatebrowsing = {
              vpnpromourl = "";
              forceMediaMemoryCache = true;
            };

            display = {
              focus_ring_on_anything = true;
              focus_ring_style = 0;
              focus_ring_width = 0;
            };

            cache.jsbc_compression_level = 3;
            helperApps.deleteTempFileOnExit = true;
            uitour.enabled = false;
            sessionstore.interval = 60000;
            formfill.enable = false;
            xul.error_pages.expert_bad_cert = true;
            contentblocking.category = "strict";
            ping-centre.telemetry = false;
            discovery.enabled = false;
            shell.checkDefaultBrowser = false;
            preferences.moreFromMozilla = false;
            tabs.tabmanager.enabled = false;
            aboutConfig.showWarning = false;
            aboutwelcome.enabled = false;
            bookmarks.openInTabClosesMenu = false;
            menu.showViewImageInfo = true;
            compactmode.show = true;
            safebrowsing.downloads.remote.enabled = false;
            tabs.crashReporting.sendReport = false;
            crashReports.unsubmittedCheck.autoSubmit2 = false;
            privateWindowSeparation.enabled = false;
          };

          security = {
            mixed_content = {
              block_display_content = true;
              upgrade_display_content = true;
            };
            insecure_connection_text = {
              enabled = true;
              pbmode.enabled = true;
            };
            OCSP.enabled = 0;
            remote_settings.crlite_filters.enabled = true;
            pki.crlite_mode = 2;
            ssl.treat_unsafe_negotiation_as_broken = true;
            tls.enable_0rtt_data = false;
          };

          toolkit = {
            telemetry = {
              unified = false;
              enabled = false;
              server = "data:,";
              archive.enabled = false;
              newProfilePing.enabled = false;
              shutdownPingSender.enabled = false;
              updatePing.enabled = false;
              bhrPing.enabled = false;
              firstShutdownPing.enabled = false;
              coverage.opt-out = true;
            };
            coverage = {
              opt-out = true;
              endpoint.base = "";
            };
            legacyUserProfileCustomizations.stylesheets = true;
          };

          dom = {
            security = {
              https_first = true;
              https_first_schemeless = true;
              sanitizer.enabled = true;
            };
            enable_web_task_scheduling = true;
          };

          layout = {
            css = {
              grid-template-masonry-value.enabled = true;
              has-selector.enabled = true;
              prefers-color-scheme.content-override = 2;
            };
            word_select.eat_space_to_next_word = false;
          };

          urlclassifier = {
            trackingSkipURLs = "*.reddit.com, *.twitter.com, *.twimg.com, *.tiktok.com";
            features.socialtracking.skipURLs = "*.instagram.com, *.twitter.com, *.twimg.com";
          };

          privacy = {
            globalprivacycontrol.enabled = true;
            history.custom = true;
            userContext.ui.enabled = true;
            trackingprotection = {
              enabled = true;
              pbmode.enabled = true;
              socialtracking.enabled = true;
            };
          };

          full-screen-api = {
            transition-duration = {
              enter = "0 0";
              leave = "0 0";
            };
            warning = {
              delay = -1;
              timeout = 0;
            };
          };

          permissions.default = {
            desktop-notification = 2;
            geo = 2;
          };

          signon = {
            formlessCapture.enabled = false;
            privateBrowsingCapture.enabled = false;
          };

          datareporting = {
            policy.dataSubmissionEnabled = false;
            healthreport.uploadEnabled = false;
          };

          extensions = {
            pocket.enabled = false;
            getAddons.showPane = false;
            htmlaboutaddons.recommendations.enabled = false;
            postDownloadThirdPartyPrompt = false;
          };

          app = {
            shield.optoutstudies.enabled = false;
            normandy.enabled = false;
            normandy.api_url = "";
          };

          image.mem.decode_bytes_at_a_time = 32768;
          editor.truncate_user_pastes = false;
          pdfjs.enableScripting = false;
          geo.provider.network.url = "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%";
          permissions.manager.defaultsUrl = "";
          webchannel.allowObject.urlWhitelist = "";
          breakpad.reportURL = "";
          captivedetect.canonicalURL = "";
          cookiebanners.service.mode = 1;
          findbar.highlightAll = true;
          content.notify.interval = 100000;
        };
      };
    };
  };
}

7.30.4. Fcitx

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

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

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

7.30.5. Emacs

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

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

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

7.30.6. Gammastep

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

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

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

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

7.30.7. Git

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

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

    extraConfig = {
      init.defaultBranch = "main";
    };

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

7.30.8. Hyprland

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

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

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

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

      windowrule = [ 
        {
          name = "emacs";
          "match:class" = "emacs";
          workspace = 1;
        }
        {
          name = "firefox";
          "match:class" = "firefox";
          workspace = 2;
        }
        {
          name = "vesktop";
          "match:class" = "vesktop";
          workspace = 3;
        }
        {
          name = "pavucontrol";
          "match:class" = "pavucontrol";
          workspace = 4;
        }
        {
          name = "qpwgraph";
          "match:class" = "qpwgraph";
          workspace = 4;
        }
        {
          name = "mpv";
          "match:class" = "mpv";
          workspace = 4;
        }
      ];

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

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

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

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

7.30.9. Kitty

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

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

7.30.10. Mako

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

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

7.30.11. Mbsync

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

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

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

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

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

7.30.12. MSMTP

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

{ lib, config, ... }:
{
  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        ${config.monorepo.vars.userName}
      host           ${config.monorepo.profiles.email.smtpsServer}
      port           587
      from           ${config.monorepo.profiles.email.email}
      user           ${config.monorepo.profiles.email.email}
      passwordeval   "cat ${config.sops.secrets.mail.path}"


      # Set a default account
      account default : ${config.monorepo.vars.userName}
    '';
  };
}

7.30.13. Mpd

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

{ lib, config, ... }:
{
  services.mpd = {
  enable = lib.mkDefault config.monorepo.profiles.music.enable;
  dbFile = "/home/${config.monorepo.vars.userName}/.config/mpd/db";
  dataDir = "/home/${config.monorepo.vars.userName}/.config/mpd/";
  network.port = 6600;
  musicDirectory = "/home/${config.monorepo.vars.userName}/music";
  playlistDirectory = "/home/${config.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"    # optional
        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"             # This must match your SSH tunnel local port
    mount           "/stream"          # The URL path (e.g. http://vps:8000/stream)
    password        "SuperSecretSourcePass"
    bitrate         "128"
    format          "44100:16:2"
    protocol        "icecast2"         # Essential for modern Icecast
    user            "source"           # Default icecast source user
    description     "My MPD Stream"
    genre           "Mixed"
}
    '';
  };
}

7.30.14. MPV

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

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

7.30.15. GTK

{ lib, config, pkgs, ... }:
{
  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.30.16. Waybar

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

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

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

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

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

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

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

      #custom-date {
        color: #D3869B;
      }

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

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

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

      #battery {
          color: #89b4fa;
      }

      #battery.charging {
          color: #a6e3a1;
      }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        output = config.monorepo.vars.monitors;

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

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

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

7.30.17. Wofi

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

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

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

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

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

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

        100% {
           opacity: 1;
        }
      }

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

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

        100% {
           opacity: 1;
        }
      }

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

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

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

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

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

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

      #entry {
        background-color: @base;
      }

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

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

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

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

7.30.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.30.19. Zsh

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

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

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

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

7.30.20. 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, ... }:
{
  home = {
    activation.startup-files = lib.hm.dag.entryAfter [ "installPackages" ] ''
    if [ ! -d "/home/${config.monorepo.vars.userName}/email/${config.monorepo.vars.internetName}/" ]; then
      mkdir -p /home/${config.monorepo.vars.userName}/email/${config.monorepo.vars.internetName}/
    fi

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

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

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

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

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

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

      fzf
      # passwords
      age sops

      # formatting
      ghostscript texliveFull pandoc

      # Emacs Deps
      graphviz jq

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

      # Sound/media
      pavucontrol alsa-utils imagemagick ffmpeg helvum

      # Net
      curl rsync git iamb ungoogled-chromium

      # Tor
      torsocks tor-browser

      # For transfering secrets onto new system
      magic-wormhole stow

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

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

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

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

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

      (writeShellScriptBin "remote-build"
        ''
#!/bin/bash
nixos-rebuild --sudo --ask-sudo-password --target-host "$1" switch --flake $HOME/monorepo/nix#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"
        '')
    ] 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 = true;
    defaultApplications = {
      "x-scheme-handler/mailto" = "emacsclient-mail.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
    ];
    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.

{ config, lib, ... }:
{
  imports = [
    ./home.nix
    ../modules/default.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.

{ lib, config, ... }:
{
  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 = [
    ../../disko/btrfs-simple.nix
    ../common.nix
  ];
  config = {
    monorepo = {
      profiles = {
        impermanence.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.

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

8.4. Affinity

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

{ config, lib, home-manager, ... }:
{
  imports = [
    ../common.nix
    ../../disko/drive-simple.nix
  ];
  config = {
    zramSwap = {
      enable = true;
      algorithm = "zstd";
      memoryPercent = 50;
    };
    monorepo = {
      vars.device = "/dev/nvme0n1";
      profiles = {
        server.enable = false;
        cuda.enable = true;
        workstation.enable = true;
      };
    };
  };
}

8.4.1. Home

I want cuda in home manager too.

{ lib, config, pkgs, ... }:
{
  imports = [
    ../home-common.nix
  ];
  config.monorepo = {
    profiles.cuda.enable = true;
  };
}

8.5. 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.

{ config, lib, ... }:
  let
    ipv4addr = "66.42.84.130";
    ipv6addr = "2001:19f0:5401:10d0:5400:5ff:fe4a:7794";
  in
  {
    imports = [
      ../common.nix
      ../../disko/drive-bios.nix

      # nixos-anywhere generates this file
      ./hardware-configuration.nix
    ];
    config = {
      monorepo = {
        vars.device = "/dev/vda";
        profiles = {
          server.enable = true;
          ttyonly.enable = true;
          grub.enable = true;
          pipewire.enable = false;
          tor.enable = false;
          home.enable = false;
        };
      };

      boot.loader.grub.device = "nodev";
      boot.kernel.sysctl = {
        "net.ipv6.conf.ens3.autoconf" = 0;
        # Keep accept_ra = 1 so you still get the default gateway/route!
        "net.ipv6.conf.ens3.accept_ra" = 1; 
      };

      systemd.network.enable = true;
      systemd.network.networks."40-ens3" = {
        matchConfig.Name = "ens3";
        networkConfig = {
          # This is the magic combo for Vultr:
          IPv6AcceptRA = true;         # Accept routes (so we know where the internet is)
          IPv6PrivacyExtensions = false; # No random privacy IPs
        };
        ipv6AcceptRAConfig = {
          UseAutonomousPrefix = false; # Do NOT generate an IP address from the RA
        };
      };
      networking = {
        useDHCP = lib.mkForce false;
        networkmanager.enable = lib.mkForce false;
        tempAddresses = "disabled";
        extraHosts = ''
    127.0.0.1 livekit.${config.monorepo.vars.orgHost}
    127.0.0.1 matrix.${config.monorepo.vars.orgHost}
  '';
        interfaces.ens3.ipv4.addresses = [
          {
            address = ipv4addr;
            prefixLength = 24;
          }
        ];
        interfaces.ens3.useDHCP = lib.mkForce false;
        interfaces.ens3.ipv6.addresses = [
          {
            address = ipv6addr;
            prefixLength = 64;
          }
        ];
        defaultGateway = "66.42.84.1";
        firewall = {
          allowedTCPPorts = [
            80
            143
            443
            465
            587
            993
            3478
            5349
            6697
            6667
            7881
            8443
            8448
            9418
          ];
          allowedUDPPorts = [
            3478 5349 7882
          ];
          allowedUDPPortRanges = [
            { from = 49152; to = 65535; }
          ];
        };
        domains = {
          enable = true;
          baseDomains = {
            "${config.monorepo.vars.remoteHost}" = {
              a.data = ipv4addr;
              aaaa.data = ipv6addr;
            };
            "${config.monorepo.vars.orgHost}" = {
              a.data = ipv4addr;
              aaaa.data = ipv6addr;

              mx.data = [
                {
                  preference = 10;
                  exchange = "mail.${config.monorepo.vars.orgHost}";
                }
              ];
              txt = {
                data = "v=spf1 ip4:${ipv4addr} ip6:${ipv6addr} -all";
              };
            };
          };
          subDomains = {
            "${config.monorepo.vars.remoteHost}" = {};
            "notes.${config.monorepo.vars.remoteHost}" = {
              a.data = "45.76.87.125";
            };

            "_dmarc.${config.monorepo.vars.orgHost}" = {
              txt = {
                data = "v=DMARC1; p=none";
              };
            };

            "default._domainkey.${config.monorepo.vars.orgHost}" = {
              txt = {
                data = "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsC9GpfjvQlldPrHAC7Yt+ZF0aduUIVV4j2+KUkF0j6NsrpOgvU6COWKQSod/B/qyPBLWf+w5P5YiJ9XnOgw6Db/I9C67eusEHnV/cbvokXLQjSBvXee1OEdrT9i+6iUgDeGWP4CrD1DcwvXzAcCI9exy3yALHVlbkyYvi0KAYofs8dVQ3JCwSCMlol71lA6ULJ2zbCIWeSOv9/C6QZ5HOIeeoFLesX6O/YvF4FYxWbSHy244TXYuczQKuayjKgD6e8gIT5WJRQj8IAWOQ2podWw6hSuB3Ig+ekoOfnl5ivJGOMbAzFTj8FtbS4ncyidLU1kIOeuLfiILeDDLlIeYTwIDAQAB";
              };
            };

            "ntfy.${config.monorepo.vars.remoteHost}" = {};
            "matrix.${config.monorepo.vars.remoteHost}" = {};
            "www.${config.monorepo.vars.remoteHost}" = {};
            "music.${config.monorepo.vars.remoteHost}" = {};
            "mail.${config.monorepo.vars.remoteHost}" = {
            };

            "livekit.${config.monorepo.vars.orgHost}" = {};
            "${config.monorepo.vars.orgHost}" = {};
            "git.${config.monorepo.vars.orgHost}" = {};
            "matrix.${config.monorepo.vars.orgHost}" = {};
            "social.${config.monorepo.vars.orgHost}" = {};
            "list.${config.monorepo.vars.orgHost}" = {};
            "talk.${config.monorepo.vars.orgHost}" = {};
            "mail.${config.monorepo.vars.orgHost}" = {};
            "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" = {};
          };
        };
      };
    };
  }

8.6. Home

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

8.7. 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.7.1. Commit Hash Pinning

Modify this to pin the installer image hash to make the installer image always work deterministically.

{
  diskoCommitHash = "c8a0e78d86b12ea67be6ed0f7cae7f9bfabae75a";
  monorepoCommitHash = "7d8501ebc97fc238d73dee4638ab58eb32a11dc1";
  monorepoUrl = "https://github.com/ret2pop/monorepo";
}

8.7.2. ISO Default Profile

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

{ pkgs, config, lib, modulesPath, ... }:
let
  commits = import ./commits.nix;
in
{
  imports = [
    (modulesPath + "/installer/cd-dvd/installation-cd-minimal.nix")
  ];

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

  users.extraUsers.root.password = "nixos";
  users.extraUsers.nixos.password = "nixos";
  users.users = {
    root.openssh.authorizedKeys.keys = [
      "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICts6+MQiMwpA+DfFQxjIN214Jn0pCw/2BDvOzPhR/H2 preston@continuity-dell"
    ];
    nixos = {
      packages = with pkgs; [
        git
        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}
  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;
    };
  };
}
Copyright © 2024 Preston Pan