Companion UI containers (archy-bitcoin-ui, archy-lnd-ui, archy-electrs-ui) used to be launched as fire-and-forget tokio::spawn blocks from install.rs. If archipelago crashed mid-spawn or the container's cgroup was reaped, companions vanished from podman ps -a and only a manual rm/run could bring them back (the .228 incident). Now each companion is rendered as a Quadlet .container unit under ~/.config/containers/systemd/, daemon-reloaded, and started via systemctl --user. systemd owns supervision from that point on: - archipelago can crash, restart, or be uninstalled without touching any companion. - Quadlet's Restart=always + RestartSec=10 handles container exits. - A 30s reconcile tick in boot_reconciler enumerates expected companion units and re-installs any whose unit file or service vanished — defense-in-depth against external tampering. New module layout: - container/quadlet.rs: pure unit renderer + atomic write_if_changed + systemctl helpers (daemon_reload_user / enable_now / disable_remove / is_active). 6 unit tests, no I/O in the renderer. - container/companion.rs: per-app companion specs, install/remove/ reconcile, image presence (build local first, fall back to insecure registry only via image_uses_insecure_registry whitelist). 2 tests. install.rs handle_package_install now ends with a single call to companion::install_for(package_id), replacing 287 lines of spawn-and- hope shellouts plus a ~120-line nginx auth-injector helper that worked around per-node RPC password baking. The helper is gone too — the pre-start hook renders the per-node nginx.conf to /var/lib/archipelago/ bitcoin-ui/nginx.conf and the Quadlet unit bind-mounts it read-only. runtime.rs handle_package_uninstall now disables companions before the container rm loop. Otherwise systemd's Restart=always would respawn each companion within ~10s of removal. Tests: 53 container tests pass, including 6 quadlet renderer tests (host network, bridge network, capability set, atomic write idempotence) and 2 companion specs (per-app companion lookup, build_unit shape). boot_reconciler tests gain a #[cfg(test)] without_companion_stage() flag so the paused-clock fixtures don't race the real systemctl I/O. A bats regression test (companion-survives-archipelago-restart.bats, gated on ARCHY_ALLOW_DESTRUCTIVE=1) asserts the .228 failure mode cannot recur: every installed companion has a unit file, services stay active across systemctl --user restart archipelago, and a deleted unit file is recreated within one reconcile tick. Net delta: +941 / -363, but the +941 is mostly tests (~440 lines) and the new declarative layer; the imperative tokio::spawn block and its nginx-auth helper are gone, removing two failure classes (orphan companions on archipelago crash, and post-start exec races under tightly-confined cgroups) that previously needed manual SSH recovery. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
87 lines
1.0 KiB
Plaintext
87 lines
1.0 KiB
Plaintext
# SSH keys (sandbox copies)
|
|
.ssh/
|
|
|
|
# Rust build output
|
|
target/
|
|
**/target/
|
|
Cargo.lock
|
|
|
|
# Node.js
|
|
node_modules/
|
|
**/node_modules/
|
|
npm-debug.log*
|
|
yarn-debug.log*
|
|
yarn-error.log*
|
|
package-lock.json
|
|
pnpm-debug.log*
|
|
|
|
# Build outputs
|
|
dist/
|
|
dist-ssr/
|
|
build/
|
|
*.local
|
|
|
|
# IDE / editor
|
|
.idea/
|
|
.vscode/
|
|
*.swp
|
|
*.swo
|
|
*~
|
|
.DS_Store
|
|
|
|
# Environment and local overrides
|
|
.env
|
|
.env.local
|
|
.env.*.local
|
|
scripts/deploy-config.sh
|
|
|
|
# Logs
|
|
logs/
|
|
*.log
|
|
|
|
# OS
|
|
.DS_Store
|
|
Thumbs.db
|
|
|
|
# Testing
|
|
coverage/
|
|
.nyc_output/
|
|
|
|
# Temporary files
|
|
*.tmp
|
|
*.temp
|
|
|
|
# Build artifacts
|
|
*.iso
|
|
*.img
|
|
*.dmg
|
|
*.app
|
|
|
|
# macOS build output
|
|
build/macos/
|
|
|
|
# Image recipe output
|
|
image-recipe/output/
|
|
image-recipe/*.iso
|
|
image-recipe/*.img
|
|
|
|
# Loop tool artifacts (created in every subdirectory)
|
|
*/loop/
|
|
loop/loop/
|
|
loop/loop.log.bak
|
|
|
|
# Separate repos nested in tree
|
|
web/
|
|
|
|
._*
|
|
|
|
# Resilience harness reports (generated, contains session cookies)
|
|
scripts/resilience/reports/
|
|
|
|
# Codex / pnpm / python caches / editor backups
|
|
.codex
|
|
.pnpm-store/
|
|
**/__pycache__/
|
|
*.bak
|
|
.claude/scheduled_tasks.lock
|