archipelago 3e9c192b48 feat(container): bitcoin-ui pre-start hook renders nginx.conf from embedded template
Replaces the first-boot-containers.sh sed/envsubst approach with a
Rust-native render step bound into the ContainerOrchestrator lifecycle.

- New container::bitcoin_ui module: embeds the nginx.conf template via
  include_str!, reads the plaintext RPC password from
  /var/lib/archipelago/secrets/bitcoin-rpc-password, substitutes
  {{BITCOIN_RPC_AUTH}} with base64(archipelago:<password>), and atomic-
  writes (tmp + rename) to /var/lib/archipelago/bitcoin-ui/nginx.conf.
  Idempotent: byte-compares before writing so unchanged input is a
  no-op (no inode churn, no restart cascade).
- ProdContainerOrchestrator gains run_pre_start_hooks(app_id) returning
  HookOutcome::{Rewritten, Unchanged}. Fires in install_fresh before
  create_container, and in ensure_running: on Running + Rewritten
  triggers a restart; on Stopped re-renders then starts.
- bitcoin-ui Dockerfile no longer COPYs a default.conf; the file now
  arrives via runtime bind-mount of the rendered config. If the bind-
  mount is ever missing, nginx starts with no site configured and
  returns 404 everywhere — safe failure vs. serving upstream RPC with
  a stale Authorization header.
- apps/{bitcoin,electrs,lnd}-ui/manifest.yml land as first-class
  manifests. bitcoin-ui declares the bind-mount target and a dependency
  on bitcoin-core; electrs-ui and lnd-ui declare their own deps and
  health checks.
- 8 new unit tests on the render fn (idempotency, rotation, trimming,
  missing/empty secret, template invariants) plus an integration test
  asserting install(bitcoin-ui) actually lands a substituted nginx.conf
  on disk via the hook. 39/39 container:: tests pass
  (test_parse_image_versions pre-existing failure unchanged, out of
  scope).
2026-04-23 02:19:52 -04:00
..
2026-01-24 23:18:24 +00:00
2026-01-24 23:20:54 +00:00
2026-01-24 23:18:24 +00:00

Archipelago App Manifests

Containerized applications for the Archipelago Bitcoin Node OS. All apps run in rootless Podman with security hardening (cap-drop ALL, readonly root, non-root user, memory limits).

App Categories

Bitcoin & Lightning

  • bitcoin-knots — Full Bitcoin node (v28.1)
  • lnd — Lightning Network Daemon (v0.17.4-beta)
  • btcpay-server — Payment processor (v1.13.5)
  • thunderhub — Lightning management UI (v0.13.31)
  • mempool — Block explorer and fee estimator (v2.5.0)
  • electrumx — Electrum server
  • fedimint — Federated Bitcoin minting (v0.10.0)

Nostr

  • nostr-rs-relay — High-performance Rust relay (v0.9.0)
  • nostrudel — Nostr web client (v0.40.0)

Web5 & Identity

  • web5-dwn — Decentralized Web Node (v0.4.0)
  • did-wallet — Web5 DID Wallet

Self-Hosted Services

  • nextcloud (v28), jellyfin (v10.8.13), immich (release), photoprism (v240915)
  • vaultwarden (v1.30.0-alpine), onlyoffice (v7.5.1), penpot (v2.4)
  • homeassistant (v2024.1), filebrowser (v2.27.0), searxng (2024.11.17)
  • ollama (v0.5.4), grafana (v10.2.0), portainer (v2.19.4)

Networking

  • tailscale (stable), nginx-proxy-manager (v2.12.1)

Custom & External

  • indeedhub — Bitcoin documentary streaming (custom build)
  • router — Mesh routing and network management
  • botfights, nwnn, 484-kitchen, call-the-operator, arch-presentation, syntropy-institute, t-zero — External web apps

Manifest Format

Each app has a manifest.yml defining container image, resources, dependencies, security policies, health checks, and network config. See docs/app-manifest-spec.md for the spec.

Quick Reference