Public: anyone can read this; the crew can change it.

A box of the forge's own runs a restored snapshot as a service, beside production, taking no traffic #9008

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/8945-a-box-of-the-forge-s-own-runs-a-restored → main 1 commit fork

  • Merged. scout/8945-a-box-of-the-forge-s-own-runs-a-restored was merged into main as 5fac391.

Review

Sign in to review this change.
5 files changed +129 −0
docs/EXTRACT.md +13
@@ -118,3 +118,16 @@ The edge sign-in becomes the forge's own sign-in and grants. Zero-downtime
118118 deploys become the forge's swap. Backups become the snapshot. TLS becomes
119119 the proxy's. The crew, the studio, the contracts, the audit, the following —
120120 all of it already lives in the forge and moves with the data.
121
122 ## The box beside production
123
124 Steps 1–3 as files: `scripts/box-install.sh` (user, `/var/lib/forge`,
125 `/etc/forge/forge.env`, checkout at `/opt/forge`, `bun install`, the unit) and
126 `infra/forge-box/forge.service` (`Restart=always`, enabled at boot, so a
127 killed process or a reboot brings it back). Then the lines of
128 [RESTORE.md](RESTORE.md) with `<data-dir>` = `/var/lib/forge` as the `forge`
129 user, and `systemctl enable --now forge`. Nothing points at the box; compare
130 repository and app counts with production, kill the process and reboot to see
131 it return. Restoring reads the bucket by the card's lines only — no platform
132 service is involved. `test/forge-box-unit.test.ts` parses the unit.
133 Done on a machine: the drill itself (restore, counts, reboot) is the owner's to run.
docs/RESTORE.md +4
@@ -33,3 +33,7 @@ writing anything; a missing one restores without the key and lists the
3333 sealed values to set again. To pick an older snapshot, put its name
3434 (`2026-09-22T08-00-00Z`) where line 5 says `latest`. Details:
3535 [SNAPSHOT.md](SNAPSHOT.md).
36
37 On a box that stays: `scripts/box-install.sh`, then lines 3–6 as the `forge`
38 user with `<data-dir>` `/var/lib/forge`, then `systemctl enable --now forge`
39 in place of line 7 ([EXTRACT.md](EXTRACT.md), _The box beside production_).
infra/forge-box/forge.service added +22
@@ -0,0 +1,22 @@
1 [Unit]
2 Description=The forge, restored from a snapshot, beside production
3 After=network-online.target
4 Wants=network-online.target
5 StartLimitIntervalSec=0
6
7 [Service]
8 Type=simple
9 User=forge
10 Group=forge
11 WorkingDirectory=/opt/forge
12 EnvironmentFile=/etc/forge/forge.env
13 Environment=FORGE_DATA=/var/lib/forge
14 ExecStart=/usr/local/bin/bun run src/main.ts
15 Restart=always
16 RestartSec=2
17 NoNewPrivileges=true
18 ProtectSystem=full
19 ReadWritePaths=/var/lib/forge
20
21 [Install]
22 WantedBy=multi-user.target
scripts/box-install.sh added +39
@@ -0,0 +1,39 @@
1 #!/usr/bin/env bash
2 # Install the forge on a box as a systemd service (docs/EXTRACT.md steps 1-3).
3 # Run as root from a checkout: scripts/box-install.sh [/opt/forge]
4 # It does not restore and does not start the forge; docs/RESTORE.md lines 3-6
5 # fill /var/lib/forge, then `systemctl enable --now forge`.
6 set -euo pipefail
7
8 src="$(cd "$(dirname "$0")/.." && pwd)"
9 dest="${1:-/opt/forge}"
10
11 [ "$(id -u)" = 0 ] || { echo "run as root" >&2; exit 1; }
12 for bin in bun git; do
13 command -v "$bin" >/dev/null || { echo "missing binary: $bin" >&2; exit 1; }
14 done
15 [ -x /usr/local/bin/bun ] || ln -s "$(command -v bun)" /usr/local/bin/bun
16
17 id forge >/dev/null 2>&1 || useradd --system --home /var/lib/forge --shell /usr/sbin/nologin forge
18 install -d -o forge -g forge -m 700 /var/lib/forge
19 install -d -m 755 /etc/forge
20 if [ ! -e /etc/forge/forge.env ]; then
21 umask 077
22 cat > /etc/forge/forge.env <<'ENV'
23 # FORGE_URL=https://forge.example
24 # FORGE_APP_DOMAIN=forge.example
25 # FORGE_SNAPSHOT_PASSPHRASE=
26 # S3_ENDPOINT= S3_BUCKET= S3_ACCESS_KEY= S3_SECRET_KEY= S3_REGION=
27 ENV
28 fi
29
30 if [ "$src" != "$dest" ]; then
31 mkdir -p "$dest"
32 cp -a "$src/." "$dest/"
33 fi
34 chown -R forge:forge "$dest"
35 (cd "$dest" && runuser -u forge -- bun install --frozen-lockfile)
36
37 install -m 644 "$dest/infra/forge-box/forge.service" /etc/systemd/system/forge.service
38 systemctl daemon-reload
39 echo "installed; restore into /var/lib/forge (docs/RESTORE.md), then: systemctl enable --now forge"
test/forge-box-unit.test.ts added +51
@@ -0,0 +1,51 @@
1 /** The box's systemd unit (`infra/forge-box/forge.service`) says what docs/EXTRACT.md step 3 says. */
2 import { expect, test } from "bun:test";
3 import { readFileSync } from "node:fs";
4 import { join } from "node:path";
5
6 const root = join(import.meta.dir, "..");
7
8 function parse(text: string): Map<string, Map<string, string[]>> {
9 const out = new Map<string, Map<string, string[]>>();
10 let sec: Map<string, string[]> | undefined;
11 for (const raw of text.split("\n")) {
12 const line = raw.trim();
13 if (!line || line.startsWith("#")) continue;
14 const h = line.match(/^\[(\w+)\]$/);
15 if (h) {
16 sec = new Map();
17 out.set(h[1]!, sec);
18 continue;
19 }
20 const kv = line.match(/^(\w+)=(.*)$/);
21 if (!kv || !sec) throw new Error(`unparsable unit line: ${line}`);
22 sec.set(kv[1]!, [...(sec.get(kv[1]!) ?? []), kv[2]!]);
23 }
24 return out;
25 }
26
27 const unit = parse(readFileSync(join(root, "infra/forge-box/forge.service"), "utf8"));
28 const svc = unit.get("Service")!;
29
30 test("the unit runs the forge from /opt/forge and always restarts", () => {
31 expect(svc.get("ExecStart")).toEqual(["/usr/local/bin/bun run src/main.ts"]);
32 expect(svc.get("WorkingDirectory")).toEqual(["/opt/forge"]);
33 expect(svc.get("Restart")).toEqual(["always"]);
34 expect(svc.get("Environment")).toContain("FORGE_DATA=/var/lib/forge");
35 expect(svc.get("User")).toEqual(["forge"]);
36 });
37
38 test("the unit starts at boot and never gives up restarting", () => {
39 expect(unit.get("Install")!.get("WantedBy")).toEqual(["multi-user.target"]);
40 expect(unit.get("Unit")!.get("StartLimitIntervalSec")).toEqual(["0"]);
41 });
42
43 test("the install script places the unit, keeps no secret, and is executable", () => {
44 const path = join(root, "scripts/box-install.sh");
45 const sh = readFileSync(path, "utf8");
46 expect(sh).toContain("/etc/systemd/system/forge.service");
47 expect(sh).toContain("infra/forge-box/forge.service");
48 expect(sh).toContain("set -euo pipefail");
49 expect(sh).not.toMatch(/PASSPHRASE=\S/);
50 expect(require("node:fs").statSync(path).mode & 0o111).toBeGreaterThan(0);
51 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs