Infrastructure as Code for Elbforge
  • Nix 83.7%
  • HTML 11.7%
  • Shell 4.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-19 01:01:51 +02:00
docs docs: add forgejo update docs 2026-09-11 09:00:20 +02:00
hosts forgejo: fix mount deps 2026-10-17 19:09:50 +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 tmp: add large file for debugging 2026-10-11 14:48:16 +02:00
pkgs ifstate: fix patch 2026-10-19 00:08:16 +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-10-16 18:35:56 +02:00
flake.nix cache: gradient -> hydra; sync common 2026-10-02 01:09:39 +02:00
README.md misc: fix readme ssh config 2026-10-19 01:01:51 +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 !elf-adm01.prod.elbforge.org
      ProxyJump root@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 Hydra cache (hosted by c3d2.de) at hydra.hq.c3d2.de, configured in flake.nix. The hydraJobs output is what gets built and pushed there.

Documentation