Containers installed via marketplace need host.containers.internal
to resolve for Tor proxy (9050) and inter-service communication.
Was only in first-boot-containers.sh and podman_client.rs, not in
the direct podman run path used by package.install RPC.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
First release with working UI sidecar containers (--user 0:0, CHOWN caps)
and complete update pipeline (manifest publishing, archive extraction,
WebSocket notifications).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The backend's post-install hooks create archy-bitcoin-ui, archy-lnd-ui,
archy-electrs-ui containers but with only NET_BIND_SERVICE cap. Nginx
inside these containers crashes on chown in rootless podman.
Added --user=0:0, CHOWN, DAC_OVERRIDE, SETUID, SETGID caps to match
the first-boot-containers.sh pattern. Also fixed manifest publish
Python error (git log fails in rsync'd workspace with no .git).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These services had hidden services configured in torrc but their
app IDs weren't mapped in tor_service_name(), so read_tor_address()
returned None and the UI showed them as having no Tor service.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a node was already known (via link-node) but had an empty onion
address, the peer-joined handler returned early without updating the
onion. Now it patches missing onion/pubkey fields on existing nodes.
Also adds update_node() to federation storage and updates the
architecture comparison doc with system resources, StartOS/umbrelOS
tabs, Web5 section, and comparison view.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- update.rs: extract frontend .tar.gz archives during apply (was TODO/skip)
- update.rs: back up current frontend before extraction, set binary perms
- server.rs: periodic scan reads update_state.json, sets status_info.updated
flag and broadcasts via WebSocket so frontend gets notified automatically
- build-iso-dev.yml: publish binary + frontend archive + manifest.json with
SHA256 hashes to /Builds/releases/v{version}/ after each build
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend:
- Add --add-host host.containers.internal:host-gateway to LND and Bitcoin
Knots containers (fixes DNS resolution failure in rootless podman)
- Add --user 0:0 and DAC_OVERRIDE to nginx UI sidecar containers
(fixes chown crash in rootless podman for bitcoin-ui, electrs-ui, lnd-ui)
- Add hostadd to Rust Podman API client for web UI container installs
- Add Chromium privacy flags to kiosk launcher (disable telemetry)
Frontend:
- Fix onboarding reset on raw IP visits (trust localStorage as first-class
signal, skip boot screen when server is up but not onboarded)
- Fix seed regression: persist challenge indices in sessionStorage so going
back from Verify doesn't change which words are asked
- Remove glass container from seed Generate/Verify/Restore screens
- Add Back button to Restore from Seed screen
- Replace Network card: Tor (purple), VPN status (orange), Bitcoin sync (orange)
- Add ElectrumX to curated app list with correct .webp icon
- Install flow: navigate to My Apps immediately with toast, hide
installed/installing apps from marketplace and discover views
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Build versioning:
- Sequential build counter (/opt/archipelago/build-counter)
- Version format: 0.1.0-beta.N (written to build-info.txt)
- Backend reads version from build-info.txt at startup, falls
back to Cargo.toml version — no recompile needed
- UI sidebar + settings show the build version automatically
LND fix (belt + suspenders):
- Added NET_RAW capability (config.rs, first-boot, container-specs)
- Combined with tlsextraip=0.0.0.0 from previous commit
Status labels:
- Both "exited" AND "stopped" states with non-zero exit codes
now show "crashed" in the UI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
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>
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>
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>
- 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>
Critical fixes:
- Remove ensure_default_user() — no more auto-creating user with
password123. Login page now shows "Create Password" form on first
boot. User sets their own password during onboarding flow.
- CSRF 403: increased retry delay from 300ms to 500ms for stale
cookie recovery after remember-me session restore.
- Reboot: multiple fallback methods (/sbin/reboot, sysrq, kill init)
when USB is pulled and /usr/sbin isn't available.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CSRF fix (THE BLOCKER):
- After remember-me session restore, the browser has a stale CSRF
cookie but a new session token. ALL subsequent RPC calls return 403.
- Fix: exempt read-only polling methods (node-messages-received,
server.echo, system.stats, tor.status, etc.) from CSRF validation.
CSRF still protects state-changing operations (install, uninstall,
start, stop, restart, settings changes).
Reboot fix:
- The separate /tmp/archipelago-reboot.sh approach failed because
/bin/bash is on the squashfs which gets unmounted when USB is pulled.
- Fix: do everything inline in the installer script — show message,
unmount USB, wait for Enter, then reboot. Use sysrq-trigger first
(kernel-level, doesn't need userspace binaries).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Version per build:
- Health endpoint returns "1.2.0-alpha-{git_hash}" using GIT_HASH env
- CI passes git hash to cargo build
FileBrowser auto-login:
- filebrowser-client.ts: include CSRF token + credentials:include
- First-boot: generate random password, store at secrets/filebrowser/
- Set FileBrowser admin password to match after container creation
Nostr relay:
- Use docker.io/scsibug/nostr-rs-relay:0.9.0 (not in our registry)
UID mappings:
- Added electrumx (UID 1000), mysql-mempool, archy-btcpay-db, nextcloud-db
522 tests pass, Rust compiles clean.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Container name resolution:
- New all_container_names() — single source of truth for every app's
container name variants (bitcoin-knots/bitcoin/bitcoin-core, etc.)
- Covers all historical naming patterns and multi-container stacks
Start/Stop/Restart:
- No more silent failures (let _ = podman...). Every operation logs
the command, checks exit status, and returns real errors to the UI.
- Restart uses stop+start fallback when podman restart fails
(handles rootless podman loopback adapter errors)
- "No containers found" error when app doesn't exist
Tor helper:
- Install archipelago-tor-helper.path + .service in rootfs
- Enable the path unit so backend can manage Tor as non-root
- Copy tor-helper.sh to /opt/archipelago/scripts/
Verified: container with proper caps can stop/start/restart cleanly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical: headless services (Bitcoin, LND, Electrumx) need companion
UI containers that serve web dashboards. These were only built for
Bitcoin, and only on bundled ISO builds.
Changes:
- install.rs: auto-build UI containers for LND (port 8081) and
Electrumx (port 50002) in addition to Bitcoin (port 8334)
- build-auto-installer-iso.sh: always bundle docker UI source files
(was skipping for unbundled builds — they're tiny HTML, not images)
- Dockerfiles: fix nginx base image tag 1.29.6→1.27.4 (matches registry)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fedimintd v0.10.0 requires --data-dir and --bitcoind-url as CLI args,
not just env vars. Container was exiting with usage error.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add orchestration_tests.rs + mock_podman.rs (container unit tests)
- Add container-tests.yml CI workflow
- Add dev-container-test.sh for local testing
- MASTER_PLAN.md: add TASK-49 (P0) with 6-phase plan
- Login.vue: minor fixes from user testing
- AppCard.vue: enter key handler fix
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dashboard System card now reports disk usage for /var/lib/archipelago
(the LUKS encrypted partition) instead of / (small root partition).
This shows the actual usable storage (428GB) rather than the 29GB root.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- LND: add --bitcoin.active --bitcoin.mainnet and all bitcoind
connection args as container CMD args (was only env var before)
- SearXNG: add volume mount + auto-create settings.yml on install
(container exits immediately without it)
- Default caps: all containers get full rootless podman baseline
Tested on .198:
- Bitcoin Knots: running, syncing (942803 blocks)
- Grafana: running, migration complete
- Vaultwarden: running, keys created
- SearXNG: running, listening on 8080
- LND: needs bitcoin container named 'bitcoin-knots' on archy-net
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All containers now get CHOWN+FOWNER+SETUID+SETGID+DAC_OVERRIDE+NET_BIND_SERVICE
as the default cap set. Rootless podman needs these for:
- CHOWN/FOWNER/DAC_OVERRIDE: file ownership in mapped UID namespace
- SETUID/SETGID: internal user switching (entrypoint scripts)
- NET_BIND_SERVICE: port binding in network namespaces
Tested on .198: Grafana, Vaultwarden, Bitcoin Knots all start successfully.
Previously failed with "Permission denied" or "loopback adapter" errors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bitcoin Knots failed to start with "failed to set loopback adapter up"
because cap-drop=ALL removed NET_BIND_SERVICE, which rootless podman
needs for network namespace setup.
- Add NET_BIND_SERVICE to Bitcoin/LND/Fedimint capabilities
- Add NET_BIND_SERVICE as default for ALL apps (rootless podman needs it)
- UID mapping fix from previous commit also included
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
create_data_dirs now chowns data directories to the correct mapped
UID for rootless podman (host_uid = 100000 + container_uid).
Previously only Grafana (UID 472) was handled. Now all containers
get the correct ownership:
- Bitcoin Knots: 100101 (container UID 101)
- Grafana: 100472 (UID 472)
- LND: 101000 (UID 1000)
- MariaDB: 100999 (UID 999)
- Postgres: 100070 (UID 70)
- All others: 100000 (UID 0, root)
Without this, containers fail with "Operation not permitted" on
chown during startup because rootless podman restricts UID operations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical fixes from ISO testing on .198:
- Backend auto-creates default user (password123) on first start
so login works immediately after onboarding
- Force reboot (reboot -f) after install to avoid SquashFS errors
when live USB is removed
- Eject USB before prompting user, not after
- Add firmware-misc-nonfree for Intel i915 GPU (suppresses dozens
of "Possible missing firmware" warnings during initramfs update)
- First boot screen: wait up to 10s for DHCP before showing IP
- First boot screen: compact layout fits 80-col terminals
- ISOLINUX menu resolution dropped to 640x480 for universal
VESA compatibility (was 1024x768, caused scaling on some hardware)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Secure flag on session cookies broke HTTP LAN access — browsers refuse
to send Secure cookies over plain HTTP, causing 401 redirect loop.
Fix: check X-Forwarded-Proto header. Only set Secure when request came
over HTTPS. HTTP on LAN works, HTTPS still gets Secure cookies.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add identity.create + server.echo to UNAUTHENTICATED_METHODS
- Clear web/dist before frontend build to prevent stale artifacts
- Add autocomplete attrs to login inputs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FileBrowser crash fix:
- Add --cap-add=NET_BIND_SERVICE (port 80 needs it with --cap-drop=ALL)
- Add --cap-add=DAC_OVERRIDE for rootless volume access
- Both in first-boot script and backend config.rs
Test script fixes:
- Extract csrf_token cookie and send as X-CSRF-Token header on RPC calls
- Add --phase1-only flag for safe install-only checks (no side effects)
- Auto-test service uses --phase1-only so it doesn't steal onboarding
Install fixes:
- Pre-create ~/.local/share/containers (ReadWritePaths mount namespace error)
- Fix console-setup.service: add After=tmp.mount + ExecStartPre mkdir /tmp
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The parmanode compatibility layer was scaffolded but never wired up —
zero imports or calls from anywhere in the codebase. Closes gitea#1.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All container image references now pull from 80.71.235.15:3000/archipelago/
instead of Docker Hub and ghcr.io. image-versions.sh is the single source
of truth; all scripts use $*_IMAGE variables instead of hardcoded refs.
Files updated:
- scripts/image-versions.sh: central ARCHY_REGISTRY variable
- core/*/config.rs: registry whitelist includes app registry
- core/*/stacks.rs: Immich + Penpot stack images
- scripts/{first-boot,deploy-to-target,container-specs}.sh: use variables
- docker/*/Dockerfile: nginx base image from registry
- image-recipe/: ISO build, podman config, menu script
- scripts/{container-doctor,deploy-bitcoin-knots,fix-indeedhub,validate-app-manifest}.sh
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>