Flake-based NixOS configurations for a fleet of servers, LXC containers, and workstations, with CI-gated, signature-verified GitOps deployment. Servers track the stable channel (26.05); workstations track unstable. All hosts build as .#hostname.
The primary host is srv-n1. Its configuration and the security layers behind it are documented at https://codeberg.org/sensei/nixos/wiki/srv-n1
This configuration is specific to one environment. Hostnames, usernames, disk layouts, mounts, and secrets will not transfer directly. Review every file before reusing any part of it.
- Repo structure
- Hosts
- Modules
- Deployment pipeline
- Build commands
- Showcase
- Installation
- Sponsor NixOS
- GitHub mirror
/.forgejo: CI workflows. Host builds, deploy gating, Renovate, and a daily Cloudflare IP range refresh./config: application configuration files (ghostty, niri, waybar, etc.), deployed to~/.configthrough Home Manager./home: Home Manager configurations.common.nixis the workstation baseline,server.nixthe server baseline, plus per-environment and per-shell files./machines: per-host configuration, grouped intodesktop,laptop,lxc, andserver. Each host directory holds itsdefault.nix,hardware-configuration.nix, disko layout, and any host-specific services. Server hosts define their OCI containers undercontainers/. Retired hosts are preserved on thelegacybranch./modules: shared NixOS modules, exposed as options under theworkstation.*andserver.*namespaces./pkgs: package derivations not available in nixpkgs./secrets: sops-encrypted secrets./.sops.yamlat the repo root defines which host keys can decrypt each secret./terra: Terraform + nixos-anywhere provisioning, one file per machine./workers: Cloudflare Workers.srv-n2-monitorpolls srv-n2 on a five-minute cron.
flake.nix defines two host builders. mkWorkstation builds against nixpkgs-unstable with the latest kernel; mkServer builds against nixpkgs-stable with an LTS kernel and imports the server baseline (SSH, service defaults, continuous deployment, binary cache, DNS, scheduled reboots). Both wire in Home Manager, disko, and sops-nix.
Current outputs:
| Host | Type | Role |
|---|---|---|
console |
workstation | living-room KDE build with controller support |
srv-n1 |
server | primary server; runs most services as rootless Quadlets |
srv-n2 |
server | public-facing edge; Caddy, CrowdSec, Cloudflare-restricted ingress |
git |
server | Forgejo host |
mongoose |
server | qBittorrent host |
pangolin |
server | Pangolin tunnel/ingress node |
jellyfin |
LXC | media server |
runner |
LXC | Forgejo Actions runner and Harmonia binary cache |
second-brain |
LXC | second-brain service, consumed as a flake input |
erebos (desktop) and prometheus (laptop) are defined but currently commented out, as is a five-node k3s cluster. Anything commented out is not being actively developed or maintained.
Modules are enable-gated options rather than unconditional imports. Workstation functionality lives under workstation.* (baseline, packages, desktop environments, virtualization, etc.); server functionality lives under server.* (baseline, cd, cache, dns, kernelReboot). A host enables what it needs:
workstation.baseline.enable = true;
workstation.niri.enable = true;Notes:
- Garbage collection removes generations older than 7 days on workstations and 5 days on servers. Store optimization runs weekly on both.
- The user is created with an
initialPassword, and SSH is key-only. Set a real password on first boot. - All builds default to zsh. A bash Home Manager file exists; swap the shell import in
flake.nix. - Desktop environments use their stock display managers (GDM, SDDM, LightDM). Window managers use
tuigreetwith autologin. Niri (with Noctalia Shell) is the most actively maintained environment; GNOME, KDE, and XFCE are stable; Hyprland lags upstream.
Servers are usually not rebuilt by hand.
- Forgejo Actions builds every flake output on push and pull request (
nix-build.yaml). - Renovate opens PRs for container image and flake input updates. Non-major container updates and lock file maintenance automerge once CI passes. New containers are pinned as
tag@digest. - A daily gate job (
deploy-gate.yaml) rebuilds all comin-enabled hosts frommainand force-pushes the result todeploy-candidate. - A follow-up job (
deploy-release.yaml) promotesdeploy-candidatetodeploy. - comin on each server polls the
deploybranch, verifies the tip commit is signed by a trusted key (hardware security key or the Forgejo instance signing key, which signs all PR merges), and applies it. Unsigned tips are refused, anddeployonly ever moves fast-forward.
A scheduled workflow also refreshes the Cloudflare IP allowlist consumed by srv-n2.
From the repo root:
sudo nixos-rebuild boot --flake .#console
The same form applies to any other entry in the flake. Server hosts can be built this way for testing, but routine changes reach them through the deployment pipeline above.
For installation instructions, see https://codeberg.org/sensei/nixos/wiki/Installation-instructions
Consider sponsoring NixOS to support the people who make this possible: https://github.com/sponsors/NixOS