Docs: Pin the verified Panama bootstrap

This commit is contained in:
Gabriel Brown
2026-08-27 10:14:55 -04:00
parent 0d1841cf86
commit dce00e45d1
5 changed files with 156 additions and 16 deletions
+16
View File
@@ -94,6 +94,22 @@ it against the real system.
Never bare `sudo`. Load the `panama-sudo` skill first. Migrations already follow the rule.
## Initial bootstrap trust
Use the complete command in `README.md` for a new machine. It downloads `boot`
from the documented commit URL into a private temporary directory, enforces the
documented curl time and byte limits, verifies the committed blob with
`sha256sum -c`, and passes both pins to the verified script. Desktop and server
bootstrap use the same commit and digest. Never substitute a branch URL, pipe a
response into Bash, or invent a newer pin from an uncommitted file.
`boot` validates the full lowercase commit and SHA-256 before Git or install. A
fresh destination fetches only that revision and creates a tracked local `main`
after HEAD matches. An existing checkout must be clean and an ancestor of the
requested revision; it advances with fast-forward only. Dirty, divergent,
fetch-failed, or mismatched checkouts stop without reset or install. Once Panama
exists, use `panama update` for normal updates.
`boot --server` is the one exception where a new Fedora VPS may begin as root.
Before it offers SSH hardening, it copies a safe root key when possible or
verifies the target key. The target user's `.ssh` must be owned by that user at
+43 -16
View File
@@ -1,25 +1,37 @@
# Panama
Formerly Sunhat. A personal config for Fedora, with the intention of helping a
user set up their Fedora system with one command.
user set up their Fedora system with one checked command.
```sh
bash <(curl -fsSL https://git.gbrown.org/gib/Panama/raw/branch/main/boot)
(
set -euo pipefail
bootstrap_commit=0d1841cf86975d52485c94c0caa5d1b67e5c54a1
bootstrap_sha=fd8dcd70d1266da109972df346e3d85d1037f6f6e1942b0157064412ab892372
bootstrap_dir="$(umask 077; mktemp -d)"
trap 'rm -rf -- "$bootstrap_dir"' EXIT
bootstrap="$bootstrap_dir/boot"
curl --fail --location --connect-timeout 10 --max-time 30 --max-filesize 262144 \
--output "$bootstrap" \
"https://git.gbrown.org/gib/Panama/raw/commit/$bootstrap_commit/boot"
printf '%s %s\n' "$bootstrap_sha" "$bootstrap" >"$bootstrap_dir/boot.sha256"
sha256sum -c "$bootstrap_dir/boot.sha256"
PANAMA_BOOT_REVISION="$bootstrap_commit" PANAMA_BOOT_SHA256="$bootstrap_sha" \
bash "$bootstrap"
)
```
`boot` installs git if the machine lacks it, clones this repository to
`boot` installs git if the machine lacks it, creates a verified checkout at
`~/.local/share/Panama` (or `$PANAMA_PATH`), and hands off to `install`. It is
deliberately small enough to read first, and the same two steps by hand work
identically:
deliberately small enough to read first. The command downloads one immutable
`boot` blob into a private temporary directory, checks its SHA-256, then asks
that verified script to fetch the same commit. A clean existing checkout may
fast-forward to that exact revision. A dirty or divergent checkout, a failed
fetch, or a revision mismatch stops before `install`; Panama never resets local
work or falls back to whatever checkout happens to be present.
```sh
git clone https://git.gbrown.org/gib/Panama.git ~/.local/share/Panama
~/.local/share/Panama/install
```
Both are safe to run again: an existing clone is fast-forwarded rather than
replaced. Once a machine exists, though, the command that keeps it current is
`panama update` — one command, and it never asks you anything:
Once a machine exists, the command that keeps it current is `panama update`
one command, and it never asks you anything:
```sh
panama update
@@ -35,10 +47,25 @@ shell environment minus everything that needs a screen, plus rootless podman
and the compose services in [`server/`](server/README.md). The answer is the
one thing Panama records durably (`~/.local/state/panama/role`), because
`panama update` asks nothing and still has to know. A fresh server skips the
question entirely:
question entirely. It uses the same immutable boot blob and pins as the desktop
command; only the final `--server` argument differs:
```sh
bash <(curl -fsSL https://git.gbrown.org/gib/Panama/raw/branch/main/boot) --server
(
set -euo pipefail
bootstrap_commit=0d1841cf86975d52485c94c0caa5d1b67e5c54a1
bootstrap_sha=fd8dcd70d1266da109972df346e3d85d1037f6f6e1942b0157064412ab892372
bootstrap_dir="$(umask 077; mktemp -d)"
trap 'rm -rf -- "$bootstrap_dir"' EXIT
bootstrap="$bootstrap_dir/boot"
curl --fail --location --connect-timeout 10 --max-time 30 --max-filesize 262144 \
--output "$bootstrap" \
"https://git.gbrown.org/gib/Panama/raw/commit/$bootstrap_commit/boot"
printf '%s %s\n' "$bootstrap_sha" "$bootstrap" >"$bootstrap_dir/boot.sha256"
sha256sum -c "$bootstrap_dir/boot.sha256"
PANAMA_BOOT_REVISION="$bootstrap_commit" PANAMA_BOOT_SHA256="$bootstrap_sha" \
bash "$bootstrap" --server
)
```
That command also works from a brand-new VPS's **root** login. It creates or
@@ -220,7 +247,7 @@ docs/ Settings reference, and the design specs behind the work
## Tests
187 of them, under `tests/`. `tests/contracts.manifest` classifies every
188 of them, under `tests/`. `tests/contracts.manifest` classifies every
contract by the capabilities it needs. Run the hermetic set, or grant a
specific external capability when automation needs it:
+22
View File
@@ -72,6 +72,28 @@ record both the reviewed archive digest and this reviewed installed-byte digest
in `.panama-provenance`; later runs require the receipt and re-hash the installed
binary before treating an existing directory as trusted.
## Panama bootstrap
The public desktop and server commands use the same committed `boot` blob:
```text
commit 0d1841cf86975d52485c94c0caa5d1b67e5c54a1
SHA-256 fd8dcd70d1266da109972df346e3d85d1037f6f6e1942b0157064412ab892372
URL https://git.gbrown.org/gib/Panama/raw/commit/0d1841cf86975d52485c94c0caa5d1b67e5c54a1/boot
```
The digest was derived from the committed blob with:
```bash
git show 0d1841cf86975d52485c94c0caa5d1b67e5c54a1:boot | sha256sum
```
That implementation commit contains only `boot` and its boot/root-server
contracts. The following documentation commit records the pin and does not
contribute bytes to it. Rotate the bootstrap pin only through the same two-step
sequence: commit the boot implementation first, derive its committed blob
digest, then update the command and this ledger in a second commit.
## Rotation policy
Do not replace a key on an automated update. A key rotation is a reviewed
+7
View File
@@ -43,6 +43,13 @@ Other tools that beat raw commands:
- `panama test --safe` — run only contracts classified as hermetic in
`tests/contracts.manifest`
For a new machine, use the complete verified bootstrap command in `README.md`.
Desktop and server installs use the same commit-addressed `boot` file and
SHA-256; server adds only `--server`. Do not replace that URL with a branch or
pipe its response into Bash. `boot` refuses missing or malformed pins, a boot
digest mismatch, and any dirty, divergent, fetch-failed, or mismatched existing
checkout. Use `panama update` after installation.
A plain `panama test` prompts in a terminal before it starts non-hermetic contracts. Automation
must grant each required capability with a repeatable `--allow`, such as
`panama test --allow live-host updates`. Each contract has a 180-second outer timeout by default,
+68
View File
@@ -20,6 +20,74 @@ panama="$repo_dir/bin/panama"
findings=()
note() { findings+=("$1"); }
# ── Verified bootstrap command ───────────────────────────────────────────────
if grep -qE 'bash[[:space:]]+<\(curl[^)]*/raw/branch/main/boot' "$readme"; then
note 'the README still executes the mutable main-branch bootstrap'
fi
if grep -q '/raw/branch/main/boot' "$readme"; then
note 'the README still names the mutable main-branch boot URL'
fi
require_bootstrap_occurrences() {
local pattern="$1" expected="$2" explanation="$3" actual
actual="$(grep -cE -- "$pattern" "$readme")"
(( actual == expected )) || note "$explanation"
}
mapfile -t documented_commits < <(
sed -nE "s/^bootstrap_commit=['\"]?([0-9a-f]{40})['\"]?$/\1/p" "$readme" | sort -u
)
mapfile -t documented_shas < <(
sed -nE "s/^bootstrap_sha=['\"]?([0-9a-f]{64})['\"]?$/\1/p" "$readme" | sort -u
)
if (( ${#documented_commits[@]} != 1 )); then
note 'the README does not declare one full lowercase 40-hex bootstrap commit'
else
documented_commit="${documented_commits[0]}"
if ! git -C "$repo_dir" cat-file -e "$documented_commit^{commit}" 2>/dev/null; then
note 'the documented bootstrap commit does not resolve to a repository commit'
fi
fi
if (( ${#documented_shas[@]} != 1 )); then
note 'the README does not declare one lowercase 64-hex bootstrap SHA-256'
else
documented_sha="${documented_shas[0]}"
fi
if [[ -n "${documented_commit:-}" && -n "${documented_sha:-}" ]] \
&& [[ "$(git -C "$repo_dir" show "$documented_commit:boot" 2>/dev/null | sha256sum | cut -d' ' -f1)" != "$documented_sha" ]]; then
note 'the documented SHA-256 does not match boot in the documented commit'
fi
require_bootstrap_occurrences '^bootstrap_commit=[0-9a-f]{40}$' 2 \
'the desktop and server commands do not declare the same full bootstrap commit'
require_bootstrap_occurrences '^bootstrap_sha=[0-9a-f]{64}$' 2 \
'the desktop and server commands do not declare the same full bootstrap SHA-256'
require_bootstrap_occurrences 'https://git\.gbrown\.org/gib/Panama/raw/commit/\$bootstrap_commit/boot' 2 \
'the desktop and server commands do not both use the commit-addressed boot URL'
require_bootstrap_occurrences '--connect-timeout 10' 2 \
'the desktop and server commands do not both use the 10-second connect timeout'
require_bootstrap_occurrences '--max-time 30' 2 \
'the desktop and server commands do not both use the 30-second total timeout'
require_bootstrap_occurrences '--max-filesize 262144' 2 \
'the desktop and server commands do not both use the 256 KiB response limit'
require_bootstrap_occurrences 'mktemp[[:space:]]+-d' 2 \
'the desktop and server commands do not both use a private temporary directory'
require_bootstrap_occurrences 'sha256sum[[:space:]]+-c' 2 \
'the desktop and server commands do not both verify with sha256sum -c'
require_bootstrap_occurrences 'PANAMA_BOOT_REVISION="?\$bootstrap_commit"?[[:space:]]+PANAMA_BOOT_SHA256="?\$bootstrap_sha"?' 2 \
'the desktop and server commands do not both pass the verified pins to boot'
grep -qE 'bash[[:space:]]+"?\$bootstrap"?([[:space:]]|$)' "$readme" \
|| note 'the README bootstrap does not execute the verified temporary file'
grep -qE 'bash[[:space:]]+"?\$bootstrap"?[[:space:]]+--server' "$readme" \
|| note 'the server bootstrap does not reuse the verified temporary file'
if grep -qE 'curl[^|]*\|[[:space:]]*(bash|sh)|bash[[:space:]]+<\(curl' "$readme"; then
note 'the README pipes a network response into a shell'
fi
# ── The contract count ───────────────────────────────────────────────────────
#
# Counted the way `panama test` collects the suite, so the README agrees with