OPERATOR GUIDE
Install one trusted Midnight host.
The supported alpha topology puts the control plane, workers, runtime agent, build system, local registry, Postgres connection, and Traefik integration on one operator-controlled Linux VM.
On this page
BEFORE INSTALLATION
Prepare the host and its dependencies.
- Operating system
- A clean Ubuntu 24.04 or Debian 12 VM with systemd, journalctl, root or sudo access, and synchronized time.
- Containers
- Upstream Docker Engine with API 1.43 or newer and the unified cgroup v2 hierarchy. The distro docker.io package is not supported.
- State
- A reachable Postgres database and role dedicated to Midnight.
- Build path
- Pinned buildkitd and buildctl binaries plus a local OCI registry binary.
- Ingress
- Operator-installed Traefik with ports 80 and 443 available and its file provider pointed at Midnight's dynamic configuration directory.
- Host policy
- A reviewed firewall, AppArmor or SELinux posture, resolvable FQDN, and enough disk for images, builds, logs, and volumes.
- Build host
- Debhelper 13, Go 1.25, Node.js 20 or newer, npm 10 or newer, make, git, curl, jq, and the Debian packaging toolchain.
docker version --format '{{.Server.APIVersion}}'
stat -fc %T /sys/fs/cgroup
ss -ltn
timedatectl statusDocker must report API 1.43 or newer, cgroups must report cgroup2fs, and ports 80/443 must not have an unexpected owner.
CONTROLLED BUILD
Build and install the Debian package.
- 1
Clone the reviewed source
Check out the exact commit you intend to operate. Record its commit SHA with your change record.
- 2
Run the release checks
Build and test the server, CLI, API contract, and dashboard before packaging.
- 3
Build on Debian or Ubuntu
The package target requires the Debian packaging toolchain and writes the artifact beneath
build/deb/. - 4
Transfer and install
Copy only the verified package to the target host, then install it with apt.
MIDNIGHT_COMMIT=replace-with-reviewed-commit-sha
git clone https://github.com/packetloss404/midnight.git
cd midnight
git checkout --detach "$MIDNIGHT_COMMIT"
go version
node --version
npm --version
dpkg-checkbuilddeps deploy/debian/control
make bootstrap
make release-check
make package-debMIDNIGHT_PACKAGE='./midnight_0.1.0~alpha-1_amd64.deb'
test -f "$MIDNIGHT_PACKAGE"
sha256sum "$MIDNIGHT_PACKAGE"
sudo apt-get update
sudo apt-get install "$MIDNIGHT_PACKAGE"PACKAGE CONTRACT
Provide secrets and runtime integration.
The package creates the midnight system user, directories, key material, configuration defaults, and six systemd units. It does not enable them automatically.
- /etc/midnight/midnight.env
- Shared environment file for the server, workers, agent, BuildKit wrapper, and registry wrapper.
- /etc/midnight/db.dsn
- Owner-restricted Postgres DSN. Do not paste it into logs or evidence bundles.
- /etc/midnight/traefik/dynamic
- Absolute, midnight-writable publication root consumed by Traefik's file provider.
- /var/lib/midnight/doctor-postinst.json
- The package-observed preflight report. Review it before starting services.
sudo test -e /etc/midnight/db.dsn || sudo install -o midnight -g midnight -m 0600 /dev/null /etc/midnight/db.dsn
sudoedit /etc/midnight/db.dsn
sudoedit /etc/midnight/midnight.env
sudo install -d -o midnight -g midnight -m 0750 /etc/midnight/traefik/dynamic
sudo systemctl daemon-reloadPROOF OF BOOT
Start only after doctor passes.
sudo midnight-doctor --json --live
sudo systemctl enable --now midnight-server midnight-worker midnight-agent midnight-buildkit midnight-buildkit-worker midnight-registry
sudo systemctl --no-pager --full status midnight-server midnight-worker midnight-agent midnight-buildkit midnight-buildkit-worker midnight-registry
curl -fsS http://127.0.0.1:8080/api/v1alpha/compatFor every host-evidence flag and the complete handoff checklist, follow the repository's canonical operator install runbook ↗.
ONE-TIME CLAIM
Create the first human administrator.
The installation claim uses the package-created recovery bearer exactly for this bootstrap boundary. Prepare an owner-only JSON file containing a 16-character-or-longer password, a Base32 TOTP enrollment secret, and the current six-digit code from the authenticator you enrolled with that secret.
sudo test -e /root/midnight-claim.json || sudo install -o root -g root -m 0600 /dev/null /root/midnight-claim.json
sudoedit /root/midnight-claim.json{
"email": "operator@example.com",
"display_name": "Midnight Operator",
"password": "replace-with-a-unique-long-password",
"totp_secret": "REPLACEWITHBASE32SECRET",
"totp_code": "123456",
"workspace_slug": "midnight",
"workspace_display_name": "Midnight"
}sudo sh -eu <<'SH'
. /etc/midnight/midnight.env
printf 'header = "Authorization: Bearer %s"
' "$MIDNIGHT_API_BEARER_TOKEN" |
curl --config - --fail-with-body -X POST http://127.0.0.1:8080/api/v1alpha/auth/claim -H 'Content-Type: application/json' -H 'Idempotency-Key: initial-workspace-claim-v1' --data-binary @/root/midnight-claim.json
SH
sudo rm -f /root/midnight-claim.json