MidnightDocumentation

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.

Ubuntu 24.04Debian 12systemdcgroup v2
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.
Preflight factsbash
docker version --format '{{.Server.APIVersion}}'
stat -fc %T /sys/fs/cgroup
ss -ltn
timedatectl status

Docker 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. 1

    Clone the reviewed source

    Check out the exact commit you intend to operate. Record its commit SHA with your change record.

  2. 2

    Run the release checks

    Build and test the server, CLI, API contract, and dashboard before packaging.

  3. 3

    Build on Debian or Ubuntu

    The package target requires the Debian packaging toolchain and writes the artifact beneath build/deb/.

  4. 4

    Transfer and install

    Copy only the verified package to the target host, then install it with apt.

Build hostbash
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-deb
Target hostbash
MIDNIGHT_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.
Configure protected filesbash
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-reload

PROOF OF BOOT

Start only after doctor passes.

Enable servicesbash
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/compat

For 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.

Prepare the claim bodybash
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
/root/midnight-claim.jsonjson
{
  "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"
}
Submit locally without placing the recovery bearer in shell historybash
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