lanbat/nixconf

One file per service. The wiring writes itself.

lanbat/nixconf is a whole homelab as a single Nix flake: an x86_64 server, a Raspberry Pi 5 for encrypted storage and TV, one sign-on for everything, and no Kubernetes. It is published as a reference. Read it, fork it, or borrow the patterns that save you weeks.

Hosts
server, storage Pi 5, optional voice Pi 3
Services
20+, one file each
Sign-on
Authentik, wired per service
Disks
disko, LUKS2, XFS
Secrets
agenix
Deploys
deploy-rs
Orchestrator
systemd and Podman
License
MIT

Edit the service. See what gets generated.

A service in lanbat is a short description. Change the highlighted values in the block below. The Caddy vhost, systemd ordering, sign-on and dashboard tile follow from it, and evaluation rejects clashes before anything is deployed. This is a simplified preview of the wiring in modules/wiring/.

services/paperless.nixvalues are editable
lanbat.services. = {
  subdomain = "";
  port = ;
  auth = "";
  tier = "";
  state = [ "paperless" ];
  units = [ "paperless" ];
  nfs.drives = [  ];
  nfs.units = [ "paperless" ];
  dashboard = {
    group = "Documents";
    name = "Paperless";
    description = "Document archive";
  };
};
Break it:

Some things boot. Some things wait for you.

Always-on infrastructure starts without a key. Personal data (photos, passwords, cloud, media) sits on an encrypted LUKS layer that you unlock on demand. If the Pi's storage disappears, the services that depend on it stop cleanly and come back by themselves. Try it on the real service list.

Server
Pi storage

          
  • running
  • locked until unlock-workload
  • stopped, waiting for Pi storage
  • asleep until the first request

What the design bets on

  1. The server is the brain

    Compute, databases, SSO and the reverse proxy live on one machine. When something is wrong, you know where to look.

  2. The Pi is storage and TV

    Encrypted NVMe drives exported over NFS, plus Kodi and EmulationStation on the screen. A Pi 3 can be a speaker and voice satellite.

  3. Failure is a state, not an incident

    Services that need the Pi's storage stop when it drops and restart when it returns. Caddy shows a storage page instead of a stack trace.

  4. No Kubernetes

    systemd, Podman and NixOS modules are enough for two machines, and far easier to debug at midnight.

  5. Native first, containers when needed

    Nextcloud, Jellyfin, Home Assistant and Samba run as NixOS services. Authentik, Immich and Frigate use containers because packaging them natively isn't practical.

  6. One place per service

    Vhost, tier, storage, account and secrets are declared in the service's own file and checked at evaluation. Port, subdomain, secret and UID clashes fail the build.

Add a site or a service without rewriting config

Configuration has three layers. The flake builds one NixOS configuration per host in each active profile, and you can inspect any of them straight from the flake.

Profile

A whole site: its domain, its hosts, its plugins. Your real one stays out of git.

  • homelab
  • cabin
  • staging
deployments/<profile>/deploy.nix
Role

What a host is: the bundle of infrastructure it needs.

  • server
  • storage-pi
  • voice-pi
lib/roles/
Plugin

Optional features per host, built in or loaded from an external flake. The reference homelab adds Frigate-based parking enforcement this way.

  • services
  • tv
  • voice
  • android
  • your own flake
plugins/

Provisions its own Android TVs

Device-owner policy, CA trust and APKs are pushed over ADB by a package built in Nix.

Inspect before you deploy

nix run .#validate-deploy
nix run .#hosts
nix run .#deploy-query -- <host>

Checked on every pull request

The assertion suite and the VM tests run on each pull request, formatting included. A nightly job boots the full server in a VM and catches two changes that pass alone and break together.

CI status Nightly status

From a fresh clone to a running site

You need an x86_64 server, a Raspberry Pi 5 with NVMe storage and a microSD card, a domain with local DNS for <service>.<domain>, and a workstation with Nix and flakes enabled. Services stay on your LAN; Caddy uses an internal CA that each device trusts once.

  1. Enter the dev shell

    It provides deploy-rs, agenix and nixos-anywhere.

    git clone https://github.com/lanbat/nixconf
    cd nixconf
    nix develop
  2. Create your local deploy files

    The real files are gitignored, so your domain, IPs and plugins are never committed. Then set the domain, host IPs and plugins.

    cp deploy.nix.example deploy.nix
    cp deployments/homelab/deploy.nix.example \
       deployments/homelab/deploy.nix
  3. Encrypt your secrets

    Follow the secrets guide. They are agenix files that only the right hosts can decrypt.

  4. Deploy each host

    CI runs the Pi's aarch64 checks, so --skip-checks keeps your workstation from building them.

    deploy --skip-checks path:.#homelab-server
    deploy --skip-checks path:.#homelab-pi-storage

The full walk-through, covering disk layout, secrets and post-install, is the deployment checklist. After a reboot, the runbook shows how to unlock.

Run a homelab like this? Compare notes.

Pull requests are welcome. The contributor guide covers how to check a change locally and the conventions the repo follows, including the checklist for adding a new service.