159 Commits

Author SHA1 Message Date
Dorian
4295476291 feat: frontend remote relay, kiosk hardening, CSS compositor fix
Frontend:
- Add remote-relay.ts: receives companion input via /ws/remote-relay,
  dispatches keyboard/mouse/scroll events into browser DOM
- Add CompanionIndicator.vue: NES gamepad icon when companion connected
- Wire relay start/stop to auth state in App.vue

Kiosk:
- Move Chromium data dir to /var/lib/archipelago/chromium-kiosk (encrypted)
- Disable MetricsReporting, AutofillServerCommunication, PasswordManager
- Remove --metrics-recording-only (contradicts disable-metrics)

CSS:
- Fix Chromium ghost rectangles: only apply preserve-3d + backface-visibility
  during transitions, not always-on (causes Chromium to skip painting
  off-viewport cards)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 11:10:08 +01:00
Dorian
c6b9097f3d fix: add Claude model ID normalization to AIUI proxy in ISO build
Sync MODEL_MAP from deploy script to ISO build's inline claude-api-proxy.
Maps short model names (claude-sonnet-4) to full API IDs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 11:01:58 +01:00
Dorian
7409cdaac2 fix: nginx AIUI SPA routing and session gate cleanup
Backport from .228 live server:
- AIUI: use SPA fallback (try_files → /aiui/index.html) for client-side routing
- Remove cookie_session gates from AIUI proxies (API key managed by proxy)
- Apply to both HTTP and HTTPS server blocks

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 10:59:54 +01:00
Dorian
07808a95c4 fix: first-boot container creation, remote input relay, ISO packages
Critical first-boot fixes (root cause: ALL 25 containers failed on install):
- Fix image-versions.sh sourcing: multi-path fallback for /opt/archipelago/scripts/
- Fix --add-host host-gateway: resolve actual gateway IP (podman 4.3 compat)
- Fix disk size detection: check /var/lib/archipelago not / (was forcing prune on 428GB disk)
- Fix Bitcoin health check: expand $RPC vars at creation, not inside container
- Add --network-alias to all containers (aardvark-dns reliability)
- Add --network-alias to backend RPC install handler

ISO build:
- Add apache2-utils for htpasswd (Fedimint gateway password hashing)

Remote input:
- Add broadcast relay channel for companion app → browser input forwarding
- Add /ws/remote-relay WebSocket endpoint
- Android: NES controller improvements, server connect flow updates

Container images:
- Fix lnd-ui Dockerfile: listen on 8080, run as root user (rootless compat)
- Fix bitcoin-ui, electrs-ui Dockerfiles: root user for rootless podman

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 10:34:58 +01:00
Dorian
051d3b1375 fix: version 1.3.0-alpha (alpha until beta testing complete)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 08:54:39 +01:00
Dorian
c62d7f77b5 fix: container orchestration stability, AIUI inclusion, lnd-ui port, version 1.3.0
Container stability:
- Merge scan results instead of full replacement (prevents UI flapping)
- Absence threshold: 3 consecutive missed scans before removing from state
- container-list RPC uses cached scanner state for consistency
- Increased Podman API timeout 30s → 60s (scanner + health monitor)
- Keep crashed containers visible as "exited" instead of podman rm -f
- Resolve host-gateway IP via ip route (podman 4.3.x compatibility)

ISO build fixes:
- AIUI web app inclusion: searches 5 paths + CI step to copy from build server
- Claude API proxy: systemctl enable with symlink fallback
- AIUI nginx: try_files =404 (was /aiui/index.html redirect loop)
- Build version set to 1.3.0

Container fixes:
- lnd-ui: nginx listens on 8080 (was 80, Permission denied in rootless)
- first-boot: image-versions.sh sourced from correct path with validation
- first-boot: host-gateway resolved to actual gateway IP

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 01:28:11 +01:00
Dorian
134de9fe3f fix: remove broken nginx if-block for AIUI Claude proxy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 00:08:49 +01:00
Dorian
4b82b2a87e fix: unbundled ISO uses full first-boot script with all container fixes
The unbundled build was generating a 73-line inline script that only
created FileBrowser. This meant no lnd.conf, no UI sidecars, no
--add-host DNS fix for any app. Now uses the full first-boot-containers.sh
which handles both bundled (load tarballs) and unbundled (pull from
registry) modes, and includes all fixes for LND config, nginx sidecars,
and DNS resolution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 22:31:45 +01:00
Dorian
ada035f1b8 fix: reduce TimeoutStopSec from 660s to 15s
The backend shuts down in <1s. The 660s timeout was left from when
Bitcoin Core was managed by this service. With 660s, systemctl stop
hangs for 11 minutes if the process is already dead but systemd
hasn't noticed, blocking all deploys and restarts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 18:25:13 +01:00
Dorian
dad184cfc6 fix: container DNS, nginx chown, onboarding guard, seed UX, install flow
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>
2026-04-01 13:06:57 +01:00
Dorian
19587687b4 fix: copy scripts/lib/ for unbundled ISO builds (TUI lib was missing)
The UNBUNDLED build path didn't copy scripts/lib/ to the ISO,
so install-tui.sh was never available on unbundled installs.
The installer sourced it but the file wasn't there — no animations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 10:38:41 +01:00
Dorian
4e0fc38612 feat: sequential build versioning, LND NET_RAW, status labels
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>
2026-03-31 23:43:32 +01:00
Dorian
7070410b49 feat: integrate demo TUI animations into real installer
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>
2026-03-31 21:23:29 +01:00
Dorian
08f7f58a9d fix: bulletproof first-boot container creation and install reliability
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>
2026-03-31 18:31:00 +01:00
Dorian
a896ecd431 fix: container security hardening, onboarding viewport scaling, boot screen cleanup
Container security:
- Add --cap-drop ALL + --security-opt no-new-privileges:true to 12 containers
  missing hardening in first-boot-containers.sh (mempool-db, electrumx,
  mempool-api, mempool-web, electrs-ui, btcpay-db, nbxplorer, nostr-rs-relay,
  strfry, tailscale, bitcoin-ui, lnd-ui)
- Mirror same hardening in deploy-to-target.sh for consistency
- Add --read-only + tmpfs to nostr-rs-relay
- Fix filebrowser deploy to include security flags
- Remove duplicate UI image definitions in image-versions.sh
- Separate Jellyfin capabilities (needs FOWNER, exec tmpfs for CoreCLR JIT)
- Harden archy-net creation with existence check and error handling

UI fixes:
- Fix onboarding viewport scaling: all 7 screens now use h-full + max-h-full
  pattern so containers never overflow viewport regardless of padding
- Remove path-option-card wrappers from seed verify inputs, left-justify labels
- Remove batteries/barbarian icons from boot screen (keep bitcoin, cloud, github, save)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 17:35:34 +01:00
Dorian
9a556d7819 fix: CSRF race condition, UI containers, Tor ordering, seed layout
- 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>
2026-03-31 11:06:19 +01:00
Dorian
1e283daf13 fix: overhaul container lifecycle — recovery, health, uninstall, UI state
Container recovery:
- Health monitor: MAX_RESTART_ATTEMPTS 3→10, interval 60s→120s
- Dependency-aware restarts: won't restart services before their deps
- Reset dependent counters when a dependency recovers
- Handle "created" state containers (were invisible to health monitor)
- Added IndeedHub, mempool-api, mysql to tier system
- Crash recovery: podman start timeout 30s→120s with retry
- Podman client: socket timeout 5s→30s, added restart policy

UI state representation:
- Exit code 0 shows "stopped" (gray), not "crashed" (red)
- Exit code 137 shows "killed (OOM)"
- Non-zero exit shows "crashed" (red)
- Added exit_code field to PackageDataEntry

Install/uninstall fixes:
- Install returns error when container doesn't start (was silent success)
- Post-install hooks awaited instead of fire-and-forget tokio::spawn
- Uninstall: graceful rm before force, volume prune, network cleanup
- Uninstall returns error on partial failure (was 200 OK)

Config consistency:
- DB passwords read from /var/lib/archipelago/secrets/ (was hardcoded)
- Bitcoin: added ZMQ ports 28332/28333 for LND block notifications
- IndeedHub port 7777→8190 (was conflicting with strfry)
- Marketplace versions: LND 0.17.4→0.18.4, Mempool 2.5.0→3.0.0

Performance:
- Metrics collector interval 60s→300s (was duplicating health monitor)
- Podman client: proper error propagation instead of unwrap_or_default

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 07:03:57 +01:00
Dorian
f6c41f9052 fix: add python3 to ISO packages, set Claude API key in proxy service
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>
2026-03-31 05:01:13 +01:00
Dorian
72d8101045 fix: add python3 to ISO packages for Claude API proxy
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>
2026-03-31 04:52:30 +01:00
Dorian
c3bd30c148 perf: reduce CPU — Chromium GPU flags, healthcheck 30s to 120s, app card fixed height
- 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>
2026-03-31 02:42:44 +01:00
Dorian
adeb57edbf fix: force UTF-8 console with Terminus font for ASCII logo
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>
2026-03-30 23:47:15 +01:00
Dorian
afda9897f1 fix: embed netavark/aardvark-dns in ISO at build time
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>
2026-03-30 20:52:01 +01:00
Dorian
87bc0baa94 fix: add debian-tor group to backend service for onion address access
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>
2026-03-30 19:14:27 +01:00
Dorian
b515d3883f fix: install netavark + aardvark-dns for container DNS resolution
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>
2026-03-30 18:57:17 +01:00
Dorian
44bffee473 fix: container installs, Tor, kiosk, GRUB, LUKS display, error messages
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>
2026-03-30 16:35:06 +01:00
Dorian
fdd69ce1b5 fix: auth, container resilience, ISO build, gamepad polish
- 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>
2026-03-30 13:35:02 +01:00
Dorian
0f646a99d3 fix: CSRF 403 blocking all operations + reboot after install
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>
2026-03-29 22:42:09 +01:00
Dorian
ca646afd37 fix: version display, FileBrowser auto-login, nostr relay, UID mappings
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>
2026-03-29 21:56:38 +01:00
Dorian
610e51500b fix: container orchestration overhaul — names, errors, Tor, restart
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>
2026-03-29 19:26:21 +01:00
Dorian
fbabbd0722 fix: auto-build UI containers for Bitcoin, LND, Electrumx
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>
2026-03-29 17:48:13 +01:00
Dorian
c6ae14d09c feat: TUI updates — ASCII block logo, install demo script
- archipelago-menu.sh: replace box-drawing banner with ASCII block
  letter logo (ARCHIPELAGO in chunky block chars)
- scripts/install-tui-demo.sh: standalone TUI demo with all animations
  (boot scan, decrypt reveal, progress bars, bouncing BTC symbol,
  CRT transitions, celebration effects)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 16:08:41 +01:00
Dorian
2049707986 fix: redirect container storage to LUKS encrypted partition
Container image pulls were filling the 29GB root partition (100% full
after 6 images). Now podman graphroot points to /var/lib/archipelago/
containers/storage on the 400GB+ LUKS encrypted data partition.

Added storage.conf with graphroot redirect + symlink for compat.
Also create containers/storage dir on encrypted partition during install.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 15:43:57 +01:00
Dorian
c0347c7592 fix: align image-versions.sh with registry, PATH for reboot
- image-versions.sh: fix 15+ tag mismatches against actual registry
  (bitcoin-knots:28.1→latest, lnd:v0.18.5→v0.18.4, grafana:11.4→10.2,
  vaultwarden:1.32.5→1.30.0-alpine, nextcloud:29→28, etc.)
- .bashrc: add /sbin:/usr/sbin to PATH so reboot/shutdown work
- Tailscale: add Arch Atob node (100.113.33.31)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 14:25:13 +01:00
Dorian
00428071f1 fix: UEFI ESP partition type, WebSocket cookie, password UX
UEFI boot:
- xorriso now uses -append_partition with ESP type GUID
  (C12A7328-F81F-11D2-BA4B-00A0C93EC93B) instead of -isohybrid-gpt-basdat
  which only creates "basic data" partitions. Strict UEFI firmware
  requires the correct ESP type to find BOOTX64.EFI.
- Uses Arch Linux ISO approach: -append_partition + appended_part_as_gpt

WebSocket/login from LAN browser:
- HTTPS nginx /ws block was missing proxy_set_header Cookie $http_cookie
  Session cookie wasn't forwarded → backend returned 401 → WS failed

Password UX:
- Renamed "Change Password" → "Set Password" with description explaining
  default password is password123

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 12:44:13 +01:00
Dorian
f9f54254c1 fix: suppress verbose command output in installer TUI
All mkfs, cryptsetup, grub-install, tar, update-initramfs output now
goes to log file only via run() wrapper. Console shows only clean TUI
status messages (step/ok/warn/fail/spinner).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 12:06:19 +01:00
Dorian
e9903e7b4b fix: UEFI boot fallback — search by file when label fails
The embedded GRUB EFI config only searched by volume label ARCHIPELAGO.
Some UEFI firmware presents USB devices differently, causing the search
to fail and GRUB to stall.

Added fallbacks:
1. search --file /archipelago/auto-install.sh (known ISO file)
2. Fall back to $cmdpath (EFI partition itself)
3. Use configfile before normal for explicit config loading
4. Added search_fs_file module to grub-mkstandalone

Also added same fallback to the main ISO grub.cfg.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:58:42 +00:00
Dorian
6e356412b8 fix: batch beta fixes — 13 issues from 2026-03-28 testing
Frontend (neode-ui):
- Login double-enter: change @keyup.enter to @keydown.enter (#10)
- Login loop on LAN: post-login session verify before navigation (#12)
- Splash flash: reorder isReady/showSplash, add black fallback div (#7)
- Skip button text: remove "skip this step" from onboarding (#8)
- Password UI: import existing ChangePasswordSection in Settings (#11)
- Arrow key focus trap: add tab-order fallback when spatial nav fails (#13)

ISO/Boot (image-recipe):
- Step counter: TOTAL_STEPS=7 → 8 to match actual step count
- GRUB theme: add desktop-image-scale-method stretch, widen menu
- Boot noise: add loglevel=0, rd.systemd.show_status=false to kernel
- USB removal: copy reboot script to tmpfs, exec from there
- Tor setup: rewrite python3 JSON generation as bash heredoc
- Doctor/reconcile: copy scripts into rootfs, fix missing file errors
- zstd: add to rootfs packages for initramfs compression

Docs:
- BETA-ISSUES-20260328.md: full issue tracker
- INSTALL-SCREENS-DESIGN.md: editable TUI mockups

522 tests pass, vue-tsc clean.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:41:40 +00:00
Dorian
bdd9578bf8 fix: root podman D-Bus cgroup issue in ISO build
When running as sudo, root podman can't reach the systemd D-Bus
session, causing "Transport endpoint is not connected" errors.
Auto-detect and fall back to cgroupfs cgroup manager.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 21:01:10 +00:00
Dorian
717733522b fix: heredoc quoting in installer profile.d (boot media not found)
The profile.d script used <<'PROFILE' (single-quoted heredoc) inside
a bash -c '...' single-quoted block. The inner quotes broke the outer
quoting, causing all $ variables to expand to empty at build time.
The for loop checked if [ -f "/archipelago/auto-install.sh" ] instead
of if [ -f "$dev/archipelago/auto-install.sh" ] — never matching.

Fix: use <<PROFILE with \$ escaping (matching .228's working version).
Also adds fallback device scanning if standard mount points are empty,
and fixes same quoting issue in grub-embed.cfg ($root variable).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 18:44:36 +00:00
Dorian
1b49257d95 fix: heredoc escaping in installer profile.d (build failure)
The z99-archipelago-installer.sh heredoc used $'\033[...]' ANSI-C
quoting inside an unquoted <<PROFILE heredoc. Bash misparses this
during expansion, treating multi-line content as a single ANSI-C
quoted string.

Fix: switch to <<'PROFILE' (quoted, no expansion) and use raw
\033 escape codes in echo -e instead of $'...' variables.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:15:42 +00:00
Dorian
5507112981 fix: UEFI boot, TUI installer steps, clean progress output
UEFI boot fix:
- Write proper EFI grub.cfg with root UUID after update-grub
  (was missing — GRUB dropped to grub> prompt because it couldn't
  find its config on the EFI FAT partition)

Installer TUI (Claude Code-inspired):
- Step counter [1/7] through [7/7] with clean progress display
- Helper functions: step(), ok(), warn(), fail(), spinner()
- Centered output with cc() helper
- Clean status messages instead of emoji + raw echo

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 13:39:10 +00:00
Dorian
8dffe807dd fix: onboarding "Set Password" label, reboot sequence, initramfs noise
- OnboardingDone: "Go to Login" → "Set Password" with context text
- Reboot: lazy-unmount live FS before USB removal prompt, suppress
  kernel SquashFS messages, auto-reboot after 10s countdown
- Initramfs: filter "Possible missing firmware" warnings (cosmetic)
- ISOLINUX: menu centered at bottom (VSHIFT 18, HSHIFT 32, WIDTH 18)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 13:14:33 +00:00
Dorian
9636bac96b fix: auto-create default user, force reboot, i915 firmware, first boot info
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>
2026-03-28 13:06:34 +00:00
Dorian
99400a7165 feat: container orchestration, branding overhaul, onboarding logging
Container orchestration:
- Health monitor with crash recovery and auto-restart
- Doctor service (periodic health checks via systemd timer)
- Reconcile service (desired-state convergence)
- Stack-aware install/uninstall with dependency tracking

Branding:
- Custom GRUB background (designer artwork, 1024x768)
- ISOLINUX boot menu: centered, orange accents, clean labels
- Terminal banners: adaptive width, basic ANSI colors, fits 80-col
- Removed auto-generated splash scripts (designer provides assets)
- GRUB theme: lowercase branding

Frontend:
- 401 handler clears localStorage immediately (prevents cascade)

Backend:
- Onboarding/auth logging ([onboarding] tag in journalctl)
- Cookie Secure flag logging for debugging HTTP/HTTPS issues

ISO fixes:
- Install log saved before unmount (was silently failing)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 11:34:29 +00:00
Dorian
6311aa563e feat: UEFI boot fix, graphical ISOLINUX menu, instant boot
UEFI (#5): grub-mkstandalone embedded config now insmod's all needed
modules (iso9660, search_label, normal, linux) and uses 'normal' to
load the full grub.cfg. Previous config couldn't find the ISO root.

ISOLINUX (#6, #7): Switch from menu.c32 to vesamenu.c32 for background
image support. Copies splash.png from branding. TIMEOUT 0 for instant
boot (no keyboard lag, no menu flicker). Dark theme with transparent
background over the splash image.

Also: added vesamenu.c32 and libcom32.c32 to build artifacts.
Removed console=ttyS0 from quiet boot (interferes with Plymouth).
Added splash to quiet boot kernel params.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 11:34:29 +00:00
Dorian
10bf53bc83 fix: add uidmap/slirp4netns for rootless Podman, fix Tor permissions
Two critical issues found on fresh .198 install:

1. Podman broken — uidmap package missing from rootfs because
   --no-install-recommends dropped it. Without newuidmap, rootless
   Podman can't create user namespaces. Also add slirp4netns and
   fuse-overlayfs which are required for rootless networking and
   storage.

2. Tor hidden service dirs created with 750 permissions (setgid).
   Tor requires exactly 700. Added explicit mkdir + chmod 700 for
   all hidden service dirs before starting Tor.

Both issues fixed on .198 live. Build script updated for future installs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 11:34:29 +00:00
Dorian
5790fb97fe fix: remove sudo from installer (already root), reduce ISOLINUX timeout
- sudo not installed in minbase squashfs — caused "command not found"
  when pressing Enter to install. We're already root via auto-login.
- ISOLINUX timeout from 5s to 1s — reduces menu flicker/duplication

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 11:34:29 +00:00
Dorian
8d01572894 fix: installer auto-start via profile.d, revert to embedded EFI, dark ISOLINUX
Three fixes from real hardware testing:

1. Installer auto-start: replace systemd service with profile.d script.
   The service and getty raced on tty1 — service output was overwritten
   by the login prompt. Profile.d runs AFTER auto-login, same approach
   the working Debian Live build used.

2. xorriso: revert from -append_partition to embedded -e boot/grub/efi.img.
   The appended partition approach produces cyl-align-off with zero CHS
   geometry, which is why BIOS wouldn't recognize the USB. The embedded
   approach matches the working main ISO (cyl-align-on, proper CHS).

3. ISOLINUX: dark theme instead of ugly blue. Black background, orange
   title, dark selection highlight. No blue boxes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 11:34:29 +00:00
Dorian
6cfb8082c5 fix: xorriso append_partition for real USB boot + grub-mkstandalone
Root cause of USB boot failure: our xorriso used -e boot/grub/efi.img
to embed the EFI image inside the ISO. This works for CD-ROM and QEMU
but NOT for USB on real UEFI hardware.

Fix: use the Will Haley / Debian live-build approach:
- -append_partition 2 (GPT type EFI) appends efi.img AFTER ISO data
- -e --interval:appended_partition_2:all:: references the appended partition
- --mbr-force-bootable forces MBR active flag
- grub-mkstandalone with embedded bootstrap config (searches for grub.cfg)
- grub.cfg placed in both /boot/grub/ AND /EFI/BOOT/ on ISO
- grub.cfg uses search --label ARCHIPELAGO to find the ISO root

This is the exact approach used by StartOS, TAILS, and every production
custom Debian live ISO that boots from USB.

Also: iso-debug, iso-branding skills + reference docs, dev-start.sh
option 0 for branding dev, improved dev-branding.sh and test-iso-qemu.sh.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 11:34:29 +00:00
Dorian
436f337a13 feat: custom boot branding, MBR fix, Plymouth theme, CI smoke tests
Boot fix:
- Ship proven Debian Live MBR (4552) as branding/isohdpfx.bin — the
  ISOLINUX package MBR (33ed) doesn't boot on all hardware. This was
  the root cause of "machine doesn't pick up the USB".

Branding:
- Custom GRUB background: pixel-art floating island (1024x574)
- Archipelago pixel-art logo for Plymouth boot splash
- GRUB theme: dark background, orange selected item, no broken font refs
- Plymouth theme: script-based with progress bar, LUKS prompt support
- Plymouth + splash added to target rootfs packages
- GRUB theme installed on both installer ISO and target system
- Serial console (ttyS0) added to kernel params for QEMU debugging

CI improvements:
- Smoke test step: mounts ISO, verifies all critical files, checks
  initrd has live-boot, confirms boot=live in grub.cfg. Fails build
  before copying to Builds if any check fails.

Dev workflow:
- dev-branding.sh: extract ISO, swap branding, repackage, boot in QEMU
  (~10 seconds vs 20 min full rebuild)
- generate-grub-background.py: procedural cyberpunk background generator
- generate-plymouth-logo.py: procedural logo generator
- Improved test-iso-qemu.sh: --bios/--nographic flags, serial logging

Build:
- Simplified live-boot install (clean chroot, no complex fallbacks)
- Static branding images preferred, generators as fallback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 11:34:29 +00:00