Projects cashmere nix Files
.onedev Loading last commit info...
docs
hosts
lib
modules
.dir-locals.el
.gitignore
.onedev-buildspec.yml.bak
.sops.yaml
README.org
flake.lock
flake.nix
homeModules.nix
outputs.nix
README.org

Architecture

Everything runs through flake-parts with easy-hosts for host management and import-tree for automatic module discovery.

Modules under ./modules/ are imported automatically. No manual registration needed. Drop a .nix file in the right directory and it gets picked up.

Shared configuration values (SSH keys, IPs, domains) live in lib/default.nix as sportLib and are injected into all NixOS modules via specialArgs and into home-manager modules via extraSpecialArgs. No relative imports needed.

sport.*

All configuration is unified under the sport namespace. Hosts declare what they are and what they need. Modules react to those declarations.

sport = {
  profiles.graphical.enable = true;
  profiles.workstation.enable = true;

  device = {
    cpu = "intel";
    gpu = "intel";
    hasBluetooth = true;
  };

  system.boot.loader = "grub";

  programs.wm = "mango";

  services = {
    navidrome.enable = true;
    rkvm.enable = true;
  };
};

Profiles

Role flags that modules gate their configuration on.

Profile Purpose
graphical Has a display. Enables fonts, PipeWire, portals.
headless No display. Server hardening.
server Runs services.
laptop Portable. Power management.
workstation Heavy desktop. Audiophile PipeWire, JACK.

Device

Hardware declarations. Modules activate based on these values.

Option Values Effect
cpu "intel", "amd", null Microcode, kernel params
gpu "nvidia", "amd", "intel", null GPU drivers, VAAPI
keyboard "us", "de", "piccolo" Keymap, keyd for piccolo
hasTouch bool Touchscreen support
hasBluetooth bool Bluetooth + blueman
hasPrinter bool CUPS printing
hasNitrokey bool Nitrokey U2F, smartcards
hasLogitech bool Logitech wireless

Services

Every service has a standardized interface: enable, host, port, domain.

Enable a service and it configures itself, including the Caddy reverse proxy where applicable. Override port or domain if the defaults don't work for your setup.

Programs

Desktop environment and program selection.

sport.programs = {
  wm = "mango";       # sway | mango | xfce | exwm
  greeter = "tuigreet"; # tuigreet | sddm
  terminal = "foot";   # foot | kitty
  shell = "fish";      # fish | bash
  browser = "brave";   # brave | qutebrowser | firefox
};

Hosts

Host Arch Role Location
md x8664 Primary desktop workstation Local
sportmacher x8664 Piccolo Series 71 tablet Local
chiefsosa aarch64 Production server Hetzner VPS
moneyspread x8664 Secondary server Hetzner VPS

md

Primary workstation. Intel CPU + Intel GPU, Mango window manager, ZFS on LUKS with encrypted disk, QMK keyboard support (Keychron), audiophile PipeWire. Runs Navidrome, OBS Studio, rkvm (server), VMs locally. ZFS snapshots via sanoid/syncoid to a secondary encrypted drive.

sportmacher

X-Plus Piccolo Series 71 tablet. 7-inch with Intel N-series, DSI panel needing rotation, touchscreen, trackpoint. Mango window manager, tuigreet as greeter, keyd for keyboard remapping. Connected to md via rkvm (client) over Tinc mesh VPN.

chiefsosa

Hetzner aarch64 VPS running the full service stack. See the services inventory below. All services toggled via sport.services.<name>.enable = true. SSH access via sshpiper on port 22 (routes to git, pb, or the main SSH on 23230). Box86/Box64 for running TeamSpeak3 on ARM.

moneyspread

Hetzner x8664 VPS at moneyspread.st. Runs the "wired" IRC network via Sable, plus Photoflow photo gallery, Soft Serve git hosting, snips pastebin, senpai IRC client, TeamSpeak6 server, step-ca SSH certificate authority, Coder remote dev environments, and a wishlist SSH directory. Uses server-base with disko ZFS, HPN SSH on port 23230, sshpiper on port 22 routing to git/pb/senpai/shell. Nginx handles TLS for all moneyspread.st subdomains.

Home-manager is configured for the cashmere user via cashmere-moneyspread.nix, providing fish shell, starship prompt, atuin history sync, tmux (with noctalia theming), pueue background task manager, and standard CLI tools (eza, bat, btop, zoxide, yazi).

Remote Operations Workflow

Kitty's SSH kitten (kitten ssh) replaces plain ssh for all interactive sessions. It automatically copies shell integration, terminfo, fish config, starship prompt, and bat config to the remote host. Connections are shared within a kitty instance for instant subsequent logins.

Per-host visual identity

Each host gets a distinct terminal color shift via ~/.config/kitty/ssh.conf:

  • moneyspread — cold blue tint (you're on the secondary server)
  • chiefsosa — warm amber (primary server)

The KITTY_SSH_HOST and KITTY_HOST_ICON environment variables are set on the remote, available to prompts and scripts.

Commands

Command Effect
kssh moneyspread SSH via kitten (stays in current terminal)
kssh moneyspread --dash 3-pane kitty dashboard: shell + htop + journalctl -f
kssh --pick Interactive host picker via gum
beam moneyspread:~/logs/app.log ./ Download file from remote (kitten transfer)
beam ./config.nix chiefsosa:~/nix/ Upload file to remote
beam -d moneyspread:~/big.db ./ Transfer with rsync delta mode (large files)
rrun moneyspread nix-collect-garbage Queue remote command in pueue (desktop notification on done)
ops Interactive server operations menu (gum-powered)

ops menu

The ops command opens an interactive gum-powered menu for server management:

  • dashboard — spawns a new kitty window with 3-pane SSH layout
  • shell — plain SSH session
  • servicessystemctl list-units overview
  • logs — pick a service unit, follow its journal
  • deploy — triggers deploy-rs for the selected host
  • gc — queues nix-collect-garbage -d via pueue
  • beam — interactive file upload/download
  • disk — remote ncdu session
  • irc — opens senpai IRC client on the remote

Accessible from mango via Alt+Super → l → m.

Kitty keybindings

Keybind Action
Ctrl+Space → s SSH to moneyspread (new kitty tab)
Ctrl+Space → Shift+S SSH to chiefsosa (new kitty tab)
Ctrl+Space → Shift+V SSH to moneyspread in vertical split
Ctrl+Space → Shift+X Close all shared SSH connections

Background tasks (pueue)

The pueued daemon runs as a systemd user service. Completed tasks trigger desktop notifications via notify-send.

Abbreviation Expands to
pq pueue add --
pqs pueue status
pql pueue log
pqf pueue follow
pqk pueue kill
pqc pueue clean

The pueue status scratchpad is available in mango via Alt+Super → l → q.

Services Inventory

All services run on chiefsosa unless noted. Domain defaults use cashmere.rs.

Service Port Domain Description
caddy 443 (all) Reverse proxy + TLS via ACME
sshpiper 22 (direct) SSH multiplexer (git, pb, shell)
ergochat 6697 irc.cashmere.rs IRCv3 server (TLS)
soju 6699 bouncer.cashmere.rs IRC bouncer
catchmeonirc 8787 (internal) IRC bot (sysinfo, webhooks, RSS, mesh)
kiwiirc 8669 chat.cashmere.rs Web IRC client
convos 8668 irc.chat.cashmere.rs Web IRC client (alt)
sharkey 8487 social.cashmere.rs Fediverse (Misskey fork)
matrix 6167 matrix.cashmere.rs Matrix homeserver
mautrix 29318 (internal) Matrix bridge
bitlbee 6667 bridge.cashmere.rs IM-to-IRC gateway
git (Soft Serve) 23232 git.cashmere.rs Git hosting (SSH on 6611 via sshpiper)
onedev 6610 dev.cashmere.rs CI/CD + Git forge
snips 8580 pb.cashmere.rs Pastebin (SSH paste via sshpiper)
grafana 3000 grafana.cashmere.rs Monitoring dashboards
umami 5932 umami.cashmere.rs Web analytics
screego 5050 screen.cashmere.rs Screen sharing
send 4594 send.cashmere.rs Encrypted file sharing
atuin 8887 atuin.cashmere.rs Shell history sync
tt-rss rss.cashmere.rs RSS reader
qbittorrent 8938 qb.cashmere.rs Torrent client
wishlist 2200 (SSH) SSH directory / menu
pgs 2281 pgs.cashmere.rs Static site hosting via SSH
nix-cache 5000 cache.cashmere.rs Binary cache
stayem 8080 (internal) Custom application
strapi 1338 dashboard.atelier-mai.art CMS backend
atelier-frontend 19997 atelier-mai.art Portfolio frontend
catchmyorg 8930 cashmere.rs Org-mode site generator
teamspeak3-arm 9987 ts.cashmere.rs TeamSpeak3 (ARM via Box86/Box64)
storagebox (mount) Hetzner Storage Box CIFS mount
borgbackup (scheduled) Borg backups to storagebox
navidrome 4533 (local) Music server (runs on md)
rkvm 5258 (mesh) KVM switch (server on md)
teamspeak3 9987 (local) TeamSpeak3 (runs on md)
lastfm-playlist (local) Last.fm playlist creator (runs on md)
moneyspread
sable 6697 irc.moneyspread.st Sable IRC server ("wired" network)
nginx 443 (all moneyspread.st) Reverse proxy + TLS via ACME
photoflow moneyspread.st Photo gallery
sshpiper 22 (direct) SSH multiplexer (git, pb, senpai, shell)
git (Soft Serve) 23232 git.moneyspread.st Git hosting (SSH on 6622 via sshpiper)
snips 8580 pb.moneyspread.st SSH pastebin
senpai 2266 (SSH via wishlist) TUI IRC client on wired
wishlist 2200 (SSH) SSH directory / menu

Caddy

Central reverse proxy and TLS terminator for the entire infrastructure. Nearly every service registers a virtual host with Caddy. ACME certificates are provisioned automatically via Let's Encrypt.

Services that need direct TLS access (ergochat, soju) read Caddy's certificates from disk. sportLib.mkCaddyCertFixService creates a helper systemd unit that fixes file permissions so the service can read the cert, and a dummy Caddy vhost that triggers certificate provisioning for the domain.

The Caddy module also defines several "infrastructure" vhosts directly: Matrix .well-known delegation on the bare domain, Grafana, Screego, Atuin, and the musicbot web UI.

IRC Stack (ergochat + soju + catchmeonirc)

Three services form the IRC infrastructure. See IRC Infrastructure Reference for full details.

  • ergochat — IRCv3 server. Network name cashmerehq. Plaintext on :6668 (used internally by borgbackup notifications and deploy-notify), TLS on :6697. Shares Caddy's Let's Encrypt certs. Multiclient and history enabled.
  • soju — IRC bouncer. TLS-only on :6699, same cert-sharing pattern. Depends on ergochat.
  • catchmeonirc — Multi-purpose IRC bot. Connects to ergochat via SASL as catchmebot. Joins #dev, #rss, #sysinfo, #notify. Features: RSS feed aggregation (NixOS news, HM news, wiki changes), webhook receiver for CI notifications, URL tracking, system info monitoring across hosts via mesh VPN SSH. Has 4 SOPS secrets.

Other internal services also post to IRC: borgbackup sends backup reports to #sysinfo, and a deploy-notify service diffs NixOS profile changes on boot and posts to #sysinfo.

OneDev + CI

OneDev is a self-hosted DevOps platform (Git hosting + CI/CD) at dev.cashmere.rs. Uses an embedded HSQLDB database. The ExecStartPre script auto-backs up the database before version upgrades (keeping 3 snapshots). See OneDev Operations Reference for upgrade procedures.

The onedev-org companion module injects a custom plugin (from the onedev-org flake input) that adds Org-mode rendering via pandoc.

The ci module sets up the CI/CD pipeline:

  • Creates a ci user on chiefsosa with a SOPS-managed SSH key (also deployed to the onedev user)
  • Both ci and onedev are Nix trusted-users with doas rules for nix, nix-env, and switch-to-configuration
  • On all deploy targets (chiefsosa, md, sportmacher), the CI SSH pubkey is authorized for the cashmere user, enabling deploy-rs to SSH in

SSHPiper

SSH reverse proxy sitting on port 22 — the main entry point for all SSH traffic. Routes connections based on username:

  • git -> Soft Serve (127.0.0.1:6611)
  • pb -> snips pastebin (127.0.0.1:2223)
  • .* (everything else) -> system SSH (127.0.0.1:23230)

Auto-injects authorized keys and generates an upstream ed25519 key for transparent proxying.

Git (Soft Serve)

Git hosting via Soft Serve. SSH listener on port 22 (routed through sshpiper), HTTP reverse-proxied by Caddy at git.cashmere.rs. Initial admin key set from config.sport.system.sshKeys.

Nix Binary Cache

Harmonia-based binary cache at cache.cashmere.rs. The signing key (SOPS-managed) is shared with the onedev group so CI builds can sign store paths. A daily systemd timer runs nix store sign --recursive /run/current-system to ensure the current system closure is signed and cached.

Backups (borgbackup + storagebox)

Daily encrypted Borg backups to a Hetzner Storage Box. Backs up state directories for: soft-serve, matrix, stayem, sharkey, mautrix, caddy, ergochat, atuin, pgs, bitlbee, grafana, umami, onedev, and /srv/www. Encryption uses repokey-blake2 with a SOPS-managed passphrase. Retention: 7 daily, 4 weekly, 6 monthly.

Post-backup, an IRC notification script connects to ergochat's plaintext port and posts stats (duration, files changed, deduplicated size) to #sysinfo.

The storagebox module mounts the same Hetzner Storage Box via SSHFS at /mnt/storagebox using the same SSH key.

TeamSpeak3

Three modules handle TeamSpeak across hosts:

  • server-teamspeak3 — Native TS3 server + TS3AudioBot in Podman on md. Bot mounts /home/cashmere/Music read-only.
  • server-teamspeak3-arm — ARM64 variant on chiefsosa using Box86/Box64 emulation (ghcr.io/sobc/ts3server-for-arm). AudioBot streams music from Navidrome on md via Tinc mesh.
  • server-teamspeak3-proxy — Socat port forwarder on chiefsosa that proxies TS3 UDP voice (9987) and TCP file transfer (30033) to md over Tinc mesh.

catchMyorg

Org-mode notes publisher served at the bare domain cashmere.rs. Has a SOPS-managed SSH key for git operations. Manages a "notes" vault at /var/lib/catchmyorg/notes with git-backed auto-commit.

Networking

Tinc VPN

All hosts are connected via a Tinc mesh VPN overlay network. chiefsosa acts as the hub node.

Host Mesh IP Role
chiefsosa 10.13.37.1 Hub
md 10.13.37.2 Workstation
sportmacher 10.13.37.3 Workstation
moneyspread 10.13.37.4 Server

Tinc enables:

  • rkvm keyboard/mouse sharing between md and sportmacher
  • TeamSpeak3 proxy from chiefsosa to md (voice over UDP, file transfer over TCP)
  • catchmeonirc remote system monitoring over SSH
  • Direct inter-host access without exposing services to the internet

Per-host Ed25519 keys are managed via SOPS. The module is at modules/nixosModules/base/tinc.nix. See Tinc VPN Reference for full details.

Yggdrasil

All hosts also run Yggdrasil, an IPv6 mesh overlay network. Peers through German public nodes via TLS. Public-IP servers (chiefsosa, moneyspread) also peer directly with each other for resilience. The ygg0 interface is trusted. See Yggdrasil VPN Reference for details.

Host Yggdrasil IPv6
chiefsosa 201:6904:7fcb:6fa6:b869:48cc:a863:e9a6
md 202:5e97:a5ba:a207:ce38:ac4a:ca3:8f86
sportmacher 200:aa5e:2bcd:b7b3:7852:a02f:77bc:658a
moneyspread 200:1c8c:1f5:f25d:1a9f:c191:e656:9636

Hostnames resolve as <host>.ygg within the mesh (e.g., chiefsosa.ygg).

Firewall

NixOS firewall is enabled on all hosts. Tinc's tinc.cashmere and Yggdrasil's ygg0 interfaces are trusted (all mesh traffic bypasses firewall rules). Only explicitly listed TCP/UDP ports are opened on public interfaces.

Secrets Management

Secrets are managed with sops-nix using age encryption.

  • Each host has its own secrets/*.yaml files under hosts/<hostname>/secrets/
  • Age keys are stored at /keys.txt (md) or /var/lib/sops-nix/key.txt (servers)
  • Key recipients are defined in .sops.yaml at the repo root
  • Secrets are decrypted at activation time and placed under /run/secrets/
  • SOPS templates are used for env files that mix secrets and non-secrets (e.g., catchmeonirc)

To add a secret to a host:

  1. Add the secret to the host's YAML file: sops hosts/<hostname>/secrets/secrets.yaml
  2. Reference it in NixOS config: sops.secrets."my-secret" = { };
  3. Use the path: config.sops.secrets."my-secret".path

Nixpkgs Configuration

Nixpkgs is configured identically for both NixOS and home-manager via sportLib.sharedNixpkgsConfig. Both receive the same overlays:

Overlay Purpose
workarounds Temporary fixes for broken upstream packages
custom-packages Packages built from modules/packages/
NUR Nix User Repository
emacs-overlay Latest Emacs builds and MELPA packages

The workarounds overlay pins or patches packages with upstream issues. Each override has a comment explaining the issue and a link to the fix so it can be removed after a flake update.

Flake Inputs

Input Purpose
flake-parts Flake structure framework
import-tree Automatic module discovery
easy-hosts Host registry for NixOS configs
nixpkgs Main package set (unstable)
nixpkgs-stable Stable channel (25.11)
home-manager User environment management
sops-nix Secrets management with age encryption
deploy-rs Remote NixOS deployment
disko Declarative disk partitioning
nixos-facter-modules Hardware detection
stylix System-wide theming
catppuccin Catppuccin theme for home-manager
noctalia Noctalia shell
mango Mango window manager
ewm Emacs window manager
nixgl OpenGL wrapper for non-NixOS
nix-flatpak Declarative Flatpak management
emacs-overlay Latest Emacs + MELPA
nur Nix User Repository
nix-index-database Prebuilt nix-index database
stayem Custom application (private)
auralis Custom tool (private)
catchmeonirc IRC bot (private)
catchmyorg Org-mode site generator (private)
lastfm-playlist-creator Last.fm playlist creator (private)
onedev-org OneDev Org-mode plugin (private)
ncs Custom package repository (private)

Module Structure

modules/
  easy-hosts.nix                # Host registry + shared specialArgs
  deploy.nix                    # deploy-rs configuration
  hpi.nix                       # HPI (Human Programming Interface) packages
  homeModules.nix               # flake-parts option declarations for HM
  nixosModules/
    base.nix                    # Aggregator: all base modules
    base/                       # Core system (boot, users, locale, nix, ...)
      tinc.nix                  # Tinc VPN mesh (IPv4, 10.13.37.x)
      yggdrasil.nix             # Yggdrasil IPv6 mesh VPN
      nixpkgs-config.nix        # Shared nixpkgs overlays + config
      rkvm.nix                  # KVM switch (rkvm server/client)
    desktop.nix                 # Aggregator: all desktop modules
    desktop/                    # Desktop (GPU, steam, xfce, keyd, ...)
    options/                    # sport.* option declarations
      device.nix                # sport.device.* definitions
      profiles.nix              # sport.profiles.* definitions
      programs.nix              # sport.programs.* definitions
      services.nix              # sport.services.* definitions
      system.nix                # sport.system.* definitions
    server/
      base.nix                  # Server aggregator (disko, SSH, users)
      disk.nix                  # Configurable disko ZFS
      ssh.nix                   # Configurable SSH (HPN support)
      users.nix                 # Configurable server users
      services/                 # 40+ self-hosted service modules
  homeConfigurations/
    cashmere.nix                # Standalone + base home-manager config
    cashmere-md.nix             # md workstation HM overrides
    cashmere-moneyspread.nix    # moneyspread server HM config
    cashmere-x12.nix            # x12 tablet HM overrides
    wwp.nix                     # wwp HM config
  homeModules/
    packages.nix                # Package aggregator
    packages/                   # Categorized packages
      core.nix                  # Essential CLI tools
      dev.nix                   # Development tools
      gui.nix                   # GUI desktop apps
      media.nix                 # Media/audio/video
      wayland.nix               # Wayland-specific tools
      gaming.nix                # Gaming (wine, etc.)
    ssh.nix                     # SSH client config + step-ca cert management
    tmux.nix                    # tmux with vi mode, noctalia theming
    pueue.nix                   # Background task queue with notifications
    sops.nix                    # User-level secrets
    emacs.nix                   # Emacs config
    kitty/                      # kitty terminal + SSH kitten config
    mango/                      # Mango WM config (per-host)
    noctalia/                   # Runtime color scheme daemon
    ...                         # ~40 more program modules
  overlays/
    custom-packages.nix         # Packages from ncs flake input
    workarounds.nix             # Temporary upstream fixes
  packages/                     # Custom package definitions

Centralized Values (sportLib)

All shared values live in lib/default.nix and are available as sportLib in every NixOS module (via specialArgs) and every home-manager module (via extraSpecialArgs).

sportLib.defaultUser       # "cashmere"
sportLib.defaultDomain     # "cashmere.rs"
sportLib.defaultFlakePath  # "/home/cashmere/nix"
sportLib.defaultTimezone   # "Europe/Berlin"
sportLib.defaultLocale     # "en_US.UTF-8"

sportLib.sshKeys.nitrokey  # primary hardware key
sportLib.serverSSHKeys     # all keys authorized on servers
sportLib.allSSHKeys        # every known key

sportLib.hosts.chiefsosa.ipv4   # "157.180.75.233"
sportLib.hosts.chiefsosa.ipv6   # "2a01:4f9:c013:2fa::1"
sportLib.hosts.mesh.md          # "10.13.37.2"

sportLib.mkServiceOption   # creates standardized service options
sportLib.mkCaddyProxy      # creates Caddy reverse proxy config
sportLib.mkCaddyCertFixService  # fixes cert perms for non-Caddy services
sportLib.sharedNixpkgsConfig    # nixpkgs config shared across NixOS + HM

Adding a New Host

  1. Create hosts/<hostname>/default.nix
  2. Set sport.* options for profiles, device, services
  3. Add the host to modules/easy-hosts.nix
  4. Pick which module aggregators to include (base, desktop, server-base)
  5. Build: nix build .#nixosConfigurations.<hostname>.config.system.build.toplevel

Minimal example:

# hosts/newhost/default.nix
{ pkgs, sportLib, ... }:
{
  sport = {
    profiles.graphical.enable = true;
    device.cpu = "intel";
    device.gpu = "intel";
    programs.wm = "mango";
    programs.greeter = "tuigreet";
  };

  networking.hostName = "newhost";
  system.stateVersion = "25.05";
}
# in modules/easy-hosts.nix
hosts.newhost = {
  path = ../hosts/newhost;
  arch = "x86_64";
  class = "nixos";
  modules = [
    self.nixosModules.base
    self.nixosModules.desktop
  ];
};

Adding a New Service (NixOS)

  1. Create modules/nixosModules/server/services/<name>.nix
  2. Add sport.services.<name> option in modules/nixosModules/options/services.nix using sportLib.mkServiceOption
  3. Gate the module config on lib.mkIf config.sport.services.<name>.enable
  4. Enable it in any host: sport.services.<name>.enable = true
  5. Add the module to easy-hosts for the target host
# modules/nixosModules/options/services.nix (add to options.sport.services)
myapp = mkSvc "myapp" {
  port = 8888;
  domain = "myapp.${d}";
};
# modules/nixosModules/server/services/myapp.nix
{ ... }:
{
  flake.nixosModules.server-myapp =
    {
      pkgs,
      lib,
      config,
      sportLib,
      ...
    }:
    let
      cfg = config.sport.services.myapp;
    in
    {
      config = lib.mkIf cfg.enable {
        # Caddy reverse proxy (sportLib helper)
        services.caddy.virtualHosts.${cfg.domain}.extraConfig = ''
          reverse_proxy localhost:${toString cfg.port}
        '';

        # The actual service
        systemd.services.myapp = {
          after = [ "network-online.target" ];
          wants = [ "network-online.target" ];
          wantedBy = [ "multi-user.target" ];
          serviceConfig = {
            ExecStart = "${pkgs.myapp}/bin/myapp --port ${toString cfg.port}";
            DynamicUser = true;
            Restart = "always";
          };
        };
      };
    };
}
# in modules/easy-hosts.nix, add to the target host's modules list
self.nixosModules.server-myapp
# in hosts/chiefsosa/default.nix (or whichever host)
sport.services.myapp.enable = true;

Adding a New Module (home-manager)

Home-manager modules follow the flake-parts pattern. The outer function receives flake-parts args, the inner function receives home-manager args (including sportLib via extraSpecialArgs). import-tree picks up the file automatically — no manual registration.

  1. Create modules/homeModules/<name>.nix
  2. Import it in modules/homeConfigurations/cashmere.nix (add self.homeModules.<name>)
# modules/homeModules/myapp.nix
{ ... }:
{
  flake.homeModules.myapp =
    {
      pkgs,
      config,
      lib,
      sportLib,
      ...
    }:
    {
      home.packages = [ pkgs.myapp ];

      xdg.configFile."myapp/config.toml".text = ''
        user = "${sportLib.defaultUser}"
        server = "${sportLib.hosts.chiefsosa.ipv4}"
      '';
    };
}
# in modules/homeConfigurations/cashmere.nix, add to imports list
self.homeModules.myapp

Server Base

The server-base aggregator (modules/nixosModules/server/base.nix) includes:

  • disk.nix — Configurable disko ZFS partitioning
  • ssh.nix — OpenSSH with optional HPN (High Performance Networking) support
  • users.nix — Server user creation with SSH key authorization
modules.disk = {
  enable = true;
  device = "/dev/sda";
};

modules.users = {
  enable = true;
  sshKeys = [ sportLib.sshKeys.nitrokey ];
};

modules.ssh = {
  enable = true;
  useHpn = true;
};

Home Manager Packages

Packages are split into categories. The aggregator homeModules.packages imports all groups. To exclude a group, import individual categories instead of the aggregator.

Group What's in it
core CLI essentials, nix tools, file utils
dev Language servers, compilers, build tools
gui Desktop apps, browsers, chat clients
media Audio/video tools, media players
wayland Wayland compositing tools, clipboard, bars
gaming Wine, winetricks, game-related

Build Commands

# Evaluate all outputs (check for warnings/errors)
nix flake check --no-build

# Build a specific host
nix build .#nixosConfigurations.chiefsosa.config.system.build.toplevel
nix build .#nixosConfigurations.md.config.system.build.toplevel

# Build standalone home-manager config
nix build .#homeConfigurations.cashmere.activationPackage

Deploy

Remote deployments use deploy-rs. All deploy targets use remoteBuild = true and doas for privilege escalation.

Target Hostname SSH Port Notes
chiefsosa 157.180.75.233 23230 Production server
moneyspread 152.53.151.56 23230 Root access
sportmacher 10.13.37.3 (Tinc) 22 Via Tinc mesh
md 10.13.37.2 (Tinc) 22 Via Tinc mesh
deploy .#chiefsosa
deploy .#moneyspread
deploy .#sportmacher
deploy .#md

Documentation

Detailed documentation lives in docs/:

Please wait...
Connection lost or session expired, reload to recover
Page is in error, reload to recover