LND crashes with "netlinkrib: address family not supported by protocol"
in rootless podman because it needs NET_RAW to enumerate network
interfaces during TLS certificate generation. Added to capabilities
in config.rs, first-boot-containers.sh, and container-specs.sh.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
LND v0.18+ crashes with "netlinkrib: address family not supported"
because rootless podman blocks netlink access for TLS cert SAN
enumeration. Fix: add tlsextraip=0.0.0.0 and tlsextradomain=lnd
to lnd.conf so LND skips interface enumeration.
Also: fix status label to show "crashed" for both exited and
stopped containers with non-zero exit codes (previously only
caught "exited" state, but podman reports "stopped" for
restart-looping containers).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add install-tui.sh library with boot scan, logo decrypt reveal,
bouncing Bitcoin symbol progress bar, and celebration strobe.
The installer sources it if available, falls back to plain text
if missing (easy revert: just remove the source line).
Animations: CRT power-on scan, BIOS memory check simulation,
3D ASCII logo with character-by-character decrypt reveal,
progress bar with ₿ bouncing DVD-screensaver style during
long operations, logo color party on completion, flashing
"REMOVE THE USB DRIVE NOW" warning.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical flow fixes:
- Disable boot reconciliation that auto-created ALL containers on
unbundled installs (only FileBrowser should exist on first boot)
- Fix onboarding loop: RootRedirect no longer clears the
neode_onboarding_complete flag on boot screen completion
- Seed phrase persists when navigating back (no regeneration)
UI fixes:
- Boot screen: removed github and save icons from animation loop
- Seed screens: viewport height scaling with 100dvh
- Seed restore: removed outer card container from word input grid
- Seed screens use distinct background (bg-intro-1.jpg)
- Install progress simplified to "Installing" button style
- Uninstall state moved to global store (persists across navigation)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the Bitcoin RPC 60-second gate that blocked 13+ dependent containers
(mempool, electrumx, btcpay, lnd, fedimint) from being created on first boot.
Containers now always get created and auto-restart via health monitor once
Bitcoin becomes responsive — the designed recovery path.
Additional hardening:
- Validate archy-net creation with retry (silent failure broke DNS)
- Verify critical images are loaded, re-load from tarballs if missing
- Create SearXNG settings.yml before container start (was missing)
- Run reconciler automatically after first-boot failures
- Add load-images as explicit systemd dependency with 900s timeout
- Propagate config write errors in install.rs (bitcoin.conf, lnd.conf)
- FileBrowser password change: retry loop (6 attempts) + 0o600 perms
- Post-start verification: detect containers that exit immediately
- Add 2s dependency waits between container starts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Install, start, and failure events logged to
/var/log/archipelago-container-installs.log with timestamps
- Enables post-mortem debugging of container lifecycle issues
- UI container hooks: try registry pull before local build fallback
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- session.rs: use OnceCell for remember_secret to prevent concurrent
requests on first boot from generating different HMAC secrets, which
caused CSRF token mismatch on every state-changing RPC call (app
install, start, stop all failed with "CSRF token missing or invalid")
- install.rs: write lnd.conf with Bitcoin RPC credentials before LND
container starts (prevents "bitcoin.mainnet must be specified" crash);
inject Bitcoin RPC auth into bitcoin-ui nginx.conf; add proper error
logging to UI container build/run steps; fix UI containers to use
--network=host (they proxy to localhost backend/bitcoin RPC)
- Tor: remove After=tor.service from archipelago-tor-helper.path to
break systemd ordering cycle that prevented Tor from starting on boot
- Seed screen: compact grid layout (2 cols mobile, 4 cols sm+) with
tighter padding to fit kiosk displays without scrolling
- Dockerfiles: remove nonexistent assets/ COPY from bitcoin-ui, fix
electrs-ui to COPY qrcode.js and EXPOSE 50002 (matches nginx.conf)
- image-versions.sh: add UI container image variables for registry
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend reads Tor address once at startup. If Tor hasn't started yet,
the address is null forever until restart. Now retries at 5, 10, 20,
30, 60 seconds in a background task until Tor is available.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AIUI proxy requires python3 which was missing from rootfs packages.
Also sets the beta API key in the claude-api-proxy systemd service
so AIUI works out of the box on fresh installs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The claude-api-proxy.py requires python3 which was missing from the
rootfs package list, breaking AIUI on fresh installs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend reads onion addresses from /var/lib/archipelago/tor-hostnames/.
This dir was never created on fresh installs, breaking connect wallet
and tor address display. Now copies from system Tor hidden service dirs.
Also fixed log() function ordering.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The bitcoin-ui nginx proxy needs Basic Auth to talk to Bitcoin Core RPC.
The __BITCOIN_RPC_AUTH__ placeholder was not being replaced, causing a
browser login prompt. Now injects creds from secrets dir before build.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tor was configured in torrc but never started by first-boot-containers.sh.
Connect wallet and .onion services were broken on fresh installs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Uninstall was timing out at 15s default while podman stop takes 30-600s.
Now: uninstall 120s, stop 120s, restart 120s, start 60s.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Chromium kiosk: add --disable-gpu-compositing, --disable-gpu-rasterization,
--disable-software-rasterizer, --renderer-process-limit=1
drops GPU process from 64% to 12% CPU
- Container healthchecks: 30s to 120s interval in first-boot and reconcile
- AppCard: min-height on description so cards dont shift
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace fragmented random key generation with a single 24-word BIP-39
mnemonic that deterministically derives all node keys: Ed25519 (DID),
secp256k1 (Nostr/Bitcoin), BIP-84 xprv (Bitcoin Core), and LND aezeed
entropy. New onboarding flow: seed generate → word verification → identity
naming. Restore path enabled via 24-word entry. Includes seed RPC handlers,
mock backend support, LND/Bitcoin Core wallet-from-seed integration, and
UI polish across settings and discover views.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When no mesh config exists (fresh install), scan for serial devices
at /dev/ttyUSB* and /dev/ttyACM*. If a radio is found, auto-enable
mesh and save the config so subsequent boots connect immediately.
Previously, mesh defaulted to disabled and the radio was never probed
unless the user manually created a mesh-config.json file.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
system.stats (Home page) and monitoring collector both used df /
which shows the small 29GB root partition. Now prefers
/var/lib/archipelago (the LUKS encrypted data partition) when it
exists — showing the actual 1.8TB storage users care about.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Archipelago ASCII logo uses Unicode block characters (▄▀█) which
render as garbled symbols when the console font doesn't support them.
Force Uni2 codeset + Terminus font in both the live ISO and installed
system's console-setup config.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All 6 cycles completed successfully:
- C1: Full baseline diagnosis of all Bitcoin stack containers
- C2: Fixed DAC_OVERRIDE caps, health checks, container specs
- C3: Resilience testing — kill/recover for all containers + cascade
- C4: Complete test suite pass — all health checks green
- C5: 5-minute soak test passes with zero state changes
- C6: Code quality gate — all checks pass
Critical bugs found and fixed:
- Rootless volume permission denied (missing DAC_OVERRIDE capability)
- LND health check requiring macaroon auth
- Electrumx health check using missing curl binary
- Container-doctor killing active conmon processes (root/rootless mismatch)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical bug: the doctor runs as root but containers are rootless
under the archipelago user. When checking if a conmon process has an
associated container, the root podman database was queried (empty),
causing ALL conmon processes to be identified as orphaned and killed.
This terminated running containers every 30 minutes.
Fix: use sudo -u archipelago to query the rootless podman database.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Nginx needs CHOWN, SETUID, SETGID to chown cache directories and drop
privileges on startup. LND UI additionally needs NET_BIND_SERVICE to
bind port 80 inside the container. Without these, cap-drop ALL causes
nginx to crash with "Operation not permitted" on chown or bind.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The doctor runs as root (for tor permissions, process cleanup) but
containers are rootless under the archipelago user. Use sudo -u to
switch user context for podman commands.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rootless Podman 4.x restart policies don't auto-restart containers
after crashes. The doctor (which runs on a timer) now checks for
exited core containers (tiers 0-2) and restarts them.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The health check command goes through multiple shell layers
(assignment → variable expansion → eval → podman → sh -c). Inner
double quotes need \\\" escaping to survive as literal " in Python.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The electrumx container image doesn't include curl. Replace the HTTP
health check with a Python socket connection test to the RPC port.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- electrumx: add DAC_OVERRIDE to SPEC_CAPS — rootless podman maps container
UID 0 to host UID 1000, but volumes are owned by host UID 100000; without
DAC_OVERRIDE the container can't write to its own data directory
- lnd: replace curl-based health check with lncli using readonly macaroon —
the REST API requires macaroon auth, so unauthenticated curl always fails
- grafana: add DAC_OVERRIDE to SPEC_CAPS for the same rootless volume issue
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add AppIconGrid: 4-column swipeable icon grid with page dots for My Apps on mobile
- Tab bar: remove text labels, square icon-only buttons (w-14 h-14), doubled padding
- Hide tab bar and top context tabs when app session is open
- App session header hidden on mobile, replaced with floating glass close button
- App sessions now render fullscreen on mobile without nav chrome
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previous fix tried to copy from the live system at install time, but
the live ISO doesn't have netavark. Now: binaries are embedded in the
ISO during build (from the build host's /usr/lib/podman/), then copied
to the target at install time from the ISO filesystem.
This fixes container DNS on fresh installs — LND can now resolve
bitcoin-knots, mempool-api can resolve electrumx, etc.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The backend couldn't read Tor hidden service hostnames because the
systemd service only had SupplementaryGroups=dialout. Adding debian-tor
allows the backend to read /var/lib/tor/hidden_service_*/hostname
without needing sudo (which is blocked by NoNewPrivileges=yes).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fresh ISO installs use podman with CNI backend which lacks DNS.
Containers on archy-net can't resolve each other by name, causing:
- LND: "lookup bitcoin-knots: no such host"
- Any inter-container communication to fail
Fix: copy netavark + aardvark-dns from build host into ISO rootfs
and configure podman to use netavark backend. This enables automatic
DNS resolution on custom bridge networks (archy-net).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Every app in curatedApps.ts was hardcoded to docker.io/* instead of
our registry (80.71.235.15:3000/archipelago/*). This caused Bitcoin
Knots and all Discover tab installs to fail with pull errors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical:
- fix: container installs fail with "statfs: no such file or directory"
Root cause: NoNewPrivileges=yes in systemd blocks sudo inside backend.
Fix: use std::fs::create_dir_all + podman unshare chown (no sudo needed)
- fix: Tor services.json never written — \$ARCHY_TOR_DIR escaping bug
- fix: kiosk white screen — increase health wait to 60s, add --disable-gpu
Improvements:
- feat: LUKS encryption badge in Server disk stats (backend detects dm-crypt)
- fix: GRUB theme text scaling on 4:3 monitors — explicit fonts, wider menu
- fix: suppress default Debian MOTD (custom profile.d welcome is enough)
- fix: install error messages now show "Failed to pull/start" instead of
generic "Operation failed" (middleware.rs allowlist expanded)
- fix: container-tests CI — source cargo env before running tests
- docs: interactive container architecture diagram (HTML)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- build-iso-dev.yml now triggers on both main and dev-iso
- build-iso.yml (full Debian) is workflow_dispatch only
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- fix: login disconnect — verify session before WebSocket connect
- fix: 403 on app install — distinguish CSRF vs RBAC errors, only retry CSRF
- fix: health monitor now watches ALL containers (removed skip list for
backend services like nbxplorer, databases, UI containers)
- fix: server.get-state added to CSRF-exempt list (read-only)
- fix: ISO build includes container-specs.sh and lib/common.sh in rootfs
so reconcile actually works on fresh installs
- fix: gamepad nav — improved Server tab zone nav, focus styles, autofocus
- chore: move L484 web-only apps to Services tab
- chore: install store for cross-view install tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Peer rows: tabindex + role=button + Enter handler for D-pad selection
- Zone attributes: mesh-left, mesh-chat, mesh-tools for cross-panel nav
- Actions row: data-controller-container for Up from peers
- Right from peers → chat input, Right from chat → tools tabs (wide)
- Down from tabs → panel fields/buttons in grid fashion
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Down from Identity name input now lands on Personal button (closest)
instead of Continue (wider overlap but further away).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Passphrase input autofocused on mount
- "Download Backup" renamed to "Backup to Continue"
- Continue button autofocused after successful backup download
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Path screen: Continue autofocused after 500ms (was 400ms, missed transition)
- Identity screen: name input autofocused on mount
- path-action-button now shows orange focus glow (removed from suppression list)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove path-action-button from focus-visible suppression list
- Orange glow now shows on Continue when autofocused
- Bump autofocus delay to 500ms to clear slide transition
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>