Infrastructure as Code for Elbforge
  • Nix 83.6%
  • HTML 10.7%
  • Shell 5.7%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Marcel 1223ff43db
flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'git+https://elbforge.org/NuschtOS/nuschtpkgs/?ref=backports-26.05&rev=24df2647a97f8369d2ac49b16e5c4ab72f7439fe&shallow=1' (2026-08-30)
  → 'git+https://elbforge.org/NuschtOS/nuschtpkgs/?ref=backports-26.05&rev=054114434b4fd533db021b24682339f494f03f28&shallow=1' (2026-09-06)
• Updated input 'sops-nix':
    'github:mic92/sops-nix/a8627b21b9107c5711c96b84f32a9a4b3d45295f?narHash=sha256-gkig4nPi1CWc4Z50GBsjE4ygSE7hMpl/TwID2an2Cck%3D' (2026-08-13)
  → 'github:mic92/sops-nix/fbf759290e0cb0a98dfc813a4eb7d53ad1dacb57?narHash=sha256-gkSH8VUtCo6hnysNmb9DbTuDepH2t5pv%2BQWjP75xKAk%3D' (2026-09-02)
2026-09-06 03:15:52 +02:00
docs misc: update readme 2026-07-22 18:24:43 +02:00
hosts redis-forgejo: move to zfs dataset 2026-09-01 00:19:03 +02:00
images local-vm: init 2026-04-29 02:01:06 +02:00
keys misc: update readme 2026-07-22 18:24:43 +02:00
lib elf-adm01: add postfix, integration into authentik and forgejo 2026-07-20 20:55:09 +02:00
modules better authentik theming 2026-08-29 04:36:48 +02:00
pkgs forgejo: 16.0.2 -> 16.0.3 2026-08-24 12:22:11 +02:00
resources networking: switch bach to udhcpc which correctly specifies ipv6 addrs as dynamic 2026-07-07 14:46:35 +02:00
.gitignore misc: fix gitignore 2026-05-21 01:20:34 +02:00
build.sh misc: fix scripts 2026-07-24 15:10:16 +02:00
flake.lock flake.lock: Update 2026-09-06 03:15:52 +02:00
flake.nix authentik: 2026.5.6 -> 2026.8.0 2026-08-24 18:42:01 +02:00
README.md misc: fix scripts 2026-07-24 15:10:16 +02:00
update-prod.sh misc: fix scripts 2026-07-24 15:10:16 +02:00

Elbforge Infra

NixOS configuration for Elbforge, a hosted developer platform built around Forgejo (git forge) with Authentik for single sign-on. Everything is defined as a Nix flake and deployed to OpenStack VMs hosted at the dd8a ALASCA deployment maintained by Cloud&Heat.

Hosts

Host Role What it runs
elf-rpx01 Reverse proxy HAProxy, ACME/TLS termination, HTTP + TCP (git-over-SSH) ingress
elf-forge01 Git forge Forgejo, with its data on a ZFS pool.
elf-idp01 Identity provider Authentik (SSO), configured declaratively through blueprints
elf-adm01 Admin services Authoritative DNS (Knot), mail (nixos-mailserver)
elf-db01 Database PostgreSQL for Authentik and Forgejo, with its data on a ZFS pool

Stages

Every host is built in two variants:

  • prod: the real deployment on elbforge.org. Network addressing comes from OpenStack (modules/elbforge-prod/ipam.json).
  • local: a throwaway QEMU VM on elbforge.test, for testing changes without touching production.

Repository layout

.
├── flake.nix              # entrypoint: inputs, packages, nixosConfigurations
├── flake.lock             # locked dependencies
├── hosts/
│   └── <name>/            # per-host config: default.nix + prod.nix + local.nix
├── modules/
│   ├── common/            # generic NixOS tuning (ssh, nix, kernel, tools, ...)
│   ├── elbforge/          # base config applied to every Elbforge host
│   ├── elbforge-prod/     # prod-stage overlay (domain, ipam from OpenStack)
│   ├── elbforge-local/    # local-stage overlay (domain, derived addressing)
│   └── elbforge-<role>/   # opt-in service roles (rpx, forge, auth, db, ns, mta, ...)
├── pkgs/                  # custom packages (authentik, forgejo, VM/image builders)
├── lib/                   # Nix helpers (nixosSystem, mkIp, mkMac, mkHash)
├── keys/                  # SSH public keys
├── resources/             # step-ca certs, dhcp scripts
├── images/                # local VM disk images
└── docs/                  # in-depth docs

How a host is assembled

hosts/<name>/default.nix sets the hostname and enables the roles it needs via elbforge.<role>.enable = true. The role modules under modules/elbforge-* implement each role and are gated behind those flags, so a host only pulls in what it turns on. Stage-specific bits live in hosts/<name>/prod.nix / local.nix and the matching modules/elbforge-{prod,local} overlay.

Common tasks

Build

# build all prod hosts
./build.sh

# build a single prod host (forge01 | idp01 | adm01 | rpx01)
./build.sh forge01

Deploy to production

Before you can deploy to production hosts, you should configure adm01 as your SSH jump host for elf-*.prod.elbforge.org. Otherwise, you won't be able to access them via SSH or deploy to them using update-prod.sh:

Host elf-*.prod.elbforge.org
    ProxyJump elf-adm01.prod.elbforge.org

Builds locally and switches the remote host over SSH:

./update-prod.sh forge01

Run a host locally as a VM

nix run .#elf-idp01-local

The VM sets up a br-elbforge bridge and boots with a decrypted host key. Disk images live in ./images/<name>.qcow2. Shut it down with shutdown from inside. See docs/local-vm.md.

You can also use the vm-helper to run multiple VMs at once:

nix run .#vm-helper

Build an OpenStack image

nix build .#openstack-image-x86_64

See docs/openstack/image.md for the openstack image create invocation used to upload it.

Secrets

Secrets are managed with sops-nix and pulled from the private elf-secrets flake input. Each host+stage has its own encrypted file, <host>.<stage>.yaml (e.g. elf-forge01.prod.yaml).

Binary cache

Prebuilt artifacts (notably Authentik and Forgejo) come from the Gradient cache at gradient.c3d2.de, configured in flake.nix. The hydraJobs output is what gets built and pushed there.

Documentation