- Nix 83.7%
- HTML 11.7%
- Shell 4.6%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| docs | ||
| hosts | ||
| images | ||
| keys | ||
| lib | ||
| modules | ||
| pkgs | ||
| resources | ||
| .gitignore | ||
| build.sh | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
| update-prod.sh | ||
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 onelbforge.org. Network addressing comes from OpenStack (modules/elbforge-prod/ipam.json).local: a throwaway QEMU VM onelbforge.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.