87 Commits

Author SHA1 Message Date
Dorian
a0a7aadcb3 chore: Debian 12 → 13 (Trixie) migration, service hardening
- Update all references from Debian 12 (Bookworm) to Debian 13 (Trixie)
- Enable SystemCallArchitectures, RestrictAddressFamilies, RestrictRealtime
  in archipelago.service (safe on systemd 256+ which respects NoNewPrivileges=no)
- Update GLIBC compatibility checks from 2.36 to 2.40
- ISO filename, build container, and docs updated throughout

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 21:32:08 +02:00
Dorian
fe3c844fe6 fix: AIUI /aiui/ base path, nginx alias cycle, VPN auth, container boot
- AIUI: rebuild with /aiui/ base path (router, chunk loader, SW scope)
- nginx: remove alias from /aiui/ location (caused try_files redirect cycle)
- VPN: WireGuard standalone setup, auth improvements
- ISO: build script hardening, service file updates
- first-boot-containers: networking stack fixes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 20:42:09 +02:00
Dorian
2d1536f016 feat: standalone WireGuard from first install, fix networking stack
Standalone WireGuard (wg0:51820):
- New archipelago-wg.service creates wg0 independent of NostrVPN
- Keypair generated on first-boot, persisted on LUKS partition
- vpn.create-peer uses wg genkey/pubkey (no nvpn dependency)
- wg-address service depends on archipelago-wg, not nostr-vpn

Networking fixes:
- Remove nos.lol from default relays (requires PoW, events rejected)
- Add Tor hidden service for private relay (port 7777) — NAT'd peers
  can reach relay over Tor for NostrVPN signaling
- Fix Tor hostname sync race: wait loop before copying hostname files
- Add tor-hostnames + wireguard dirs to LUKS partition setup
- Include relay in hostname sync loops (setup-tor.sh + first-boot)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 20:27:38 +02:00
Dorian
5427d4ec5d feat: NostrVPN add-device guided wizard
Replace disconnected "Generate Invite" + "Add participant" with a 2-step
wizard: enter phone npub → get invite QR + mesh details. Backend vpn.invite
now accepts optional npub param to add participant in the same call. Modal
shows network ID, node npub, and relay URLs for manual app configuration.

Also includes nostr-vpn service hardening (rate-limit restarts, reset-failed
before enable).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 19:04:53 +02:00
Dorian
7741dc8652 feat: ISO networking stack — relay + nvpn v0.3.7 + WireGuard
Add nostr-rs-relay as native system service (port 7777) for VPN
signaling. Every node runs its own private relay from first boot.
Update nvpn binary from v0.3.4 to v0.3.7 (fixes mesh event
processing). Add WireGuard helper and address service for peer VPN.
First-boot script configures relay, nvpn identity, relay URLs
(direct + Tor onion), and syncs daemon config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 15:06:27 +02:00
Dorian
e977600471 feat: NostrVPN mesh + VPN card UI + nvpn v0.3.7
- VPN card: relay URLs, device management, invite QR, add participant
- Backend: vpn.invite, vpn.add-participant, vpn.peer-config RPCs
- nvpn v0.3.7 system service (fixes event processing bug in v0.3.4)
- First-boot: auto-configure nvpn with node identity and endpoint
- Service: AF_NETLINK for WireGuard, NoNewPrivileges=no for sudo wg
- TASK-50: networking stack reliability from first install

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 15:00:00 +02:00
Dorian
37b6b376b2 fix: nostr-vpn service crash on reboot, detect activating state
- Remove ReadWritePaths sandbox (causes namespace error when /run/nostr-vpn
  doesn't exist after reboot — /run is tmpfs)
- Detect both 'active' and 'activating' states in VPN status check

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 22:05:08 +01:00
Dorian
e10893e3c1 fix: nostr-vpn service — set HOME, create dirs, remove strict sandbox
nvpn binary writes to $HOME/.config/nvpn. Set HOME to data dir,
create runtime dirs in ExecStartPre, remove overly restrictive
ProtectSystem/ProtectHome that blocked the binary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:57:38 +01:00
Dorian
0aefacf3b9 fix: restore FIPS as installable container app
FIPS stays in the marketplace as an installable container app.
NostrVPN is the native system service; FIPS is a separate optional app.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 14:51:13 +01:00
Dorian
324405006d feat: NostrVPN as native system service, remove FIPS
- Convert NostrVPN from container app to native systemd service
- Auto-configure VPN with node's Nostr identity after onboarding
- Add nostr-vpn.service with proper capabilities (NET_ADMIN, NET_RAW)
- Remove FIPS from marketplace, container config, nginx, image-versions
  (consolidated into NostrVPN — same mesh VPN concept)
- Add AIUI inclusion step to dev CI workflow
- AIUI installed on VPS build server for ISO inclusion

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 14:49:34 +01:00
Dorian
e97fee2d7e feat: NostrVPN as native system service, Claude API key input, fix duplicate password
- Add NostrVPN as a native systemd service (extracted from container)
- Add VPN status detection for nostr-vpn in backend vpn.rs
- ISO build extracts nvpn binary from container image
- First-boot auto-configures NostrVPN with node's Nostr identity
- Change Claude Auth from login iframe to API key input field
- Remove duplicate ChangePasswordSection from Settings.vue
- FIPS and Routstr remain as installable container apps

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 14:40:33 +01:00
Dorian
b07bf574ef fix: service file crash on fresh installs, CI workflow portability
- Remove MemoryDenyWriteExecute=yes from archipelago.service — ring
  (rustls) and secp256k1 (bitcoin/nostr) crypto libraries need
  executable memory mappings that this restriction blocks
- Add + prefix to ExecStartPre so mkdir/chown run as root
- Use $HOME/archy instead of /home/archipelago/archy in CI workflows
  so builds work on both .228 and VPS CI runners

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:08:21 +01:00
Dorian
1989014dd5 feat: add Nostr VPN, FIPS, Routstr apps with status UIs
Add three new marketplace apps:
- Routstr (v0.4.3): Decentralized AI inference proxy with Cashu payments
- Nostr VPN (v0.3.4): Mesh VPN with Nostr signaling + WireGuard tunnels
- FIPS (v0.1.0): Self-organizing encrypted mesh network

Includes status UI dashboards for headless apps (nostr-vpn-ui, fips-ui)
with usage instructions, node identity display, and container logs.
Nostr identity injected via env vars for all three apps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 05:06:45 +01:00
Dorian
449f47da49 fix: BUILD_VERSION from Cargo.toml, kiosk scaling, new apps, Rust warnings
Critical:
- BUILD_VERSION was hardcoded as "1.3.0-alpha" — now reads from Cargo.toml
  This caused ALL ISOs to show v1.3.0 regardless of actual binary version

Kiosk:
- Remove --disable-gpu flags (broke display scaling on some monitors)
- Add --start-fullscreen --window-size for reliable fullscreen

New apps:
- Nostr VPN, FIPS, Routstr, noStrudel, BotFights, NWNN, 484 Kitchen,
  Call the Operator, Arch Presentation, Syntropy Institute, T-0

Rust: suppress dead_code and unused_assignments warnings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 00:35:52 +01:00
Dorian
69f52f7260 fix: v1.3.3 — firmware, fedimint perms, GRUB fallback, data dirs, Rust warnings
- Add firmware-linux-nonfree to ISO (fixes missing Realtek NIC firmware)
- Pre-create nbxplorer/Main and btcpay/Main data directories
- Fix fedimint data dir permissions (chmod 775 for non-root container)
- GRUB GFX fallback: gfxpayload=keep + console fallback for incompatible hardware
- Kill stale Chromium before kiosk restart (prevents duplicate processes)
- Suppress Rust warnings: #[allow(dead_code)] on run_boot_reconciliation,
  #[allow(unused_assignments)] on history_dirty
- Version bump to 1.3.3

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 20:28:53 +01:00
Dorian
c6e55e9dd0 fix: container stability, OnlyOffice removal, node bootstrapping, UI fixes
Container orchestration:
- Add --network-alias to all archy-net containers (fixes Podman DNS)
- Fix bitcoin-knots health check: expand $BITCOIN_RPC_PASS at creation
- Increase bitcoin-knots memory limit to 4g, reduce dbcache to 2048
- Enable podman-restart.service in ISO for auto-start on boot
- Fix UI container Dockerfiles: ENTRYPOINT [], user root for rootless

App changes:
- Remove OnlyOffice (incompatible with rootless Podman)
- Replace with CryptPad reference (single-process, e2e encrypted)
- Fix NPM port mapping: 8181 → 81
- Fix OnlyOffice port mapping: 8044 → 9980 (now CryptPad: 3003)

AIUI & proxy:
- Add MODEL_MAP to claude-api-proxy (ISO + deploy)
- Map legacy model IDs (claude-haiku-4.5 → claude-haiku-4-5-20251001)

Kiosk:
- Move chromium-kiosk data dir to /var/lib/archipelago (data partition)
- Remove --metrics-recording-only (contradicted --disable-metrics)

Node bootstrapping:
- Add bootstrap-switchover.sh for live node updates
- ElectrumX UI improvements and nginx proxy fixes
- LND UI nginx config updates

Backend:
- Bitcoin health check uses .cookie auth (no plaintext creds)
- ElectrumX status endpoint improvements
- Network alias flag in install.rs for DNS reliability

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 16:15:04 +01:00
Dorian
94524e150a 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
7982714588 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
ee7b5980dd 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
9d4fb805f5 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
02f73a4789 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
6d3704fff5 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
4b0e1cfbe3 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
92a429535a 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
c191dddd2b 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
cb1f252e4d 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
9db55b0b34 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
320c9f5b19 fix: container install flow, filebrowser auth, AppCard enrichment
- Fix .198-style fresh installs: systemd service ExecStartPre creates
  /run/user/1000, enable podman.socket, chmod 644 /etc/hosts
- Filebrowser: add /data volume for database (fixes read-only crash),
  secure auth with random password via backend RPC (no more admin/admin)
- AppCard: enrich installing state with marketplace metadata (icon,
  title, description, tier badge, author, version)
- Registry: btcpayserver 1.13.5 → 1.13.7, images mirrored
- ReadWritePaths: add home container paths for rootless podman

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:32:54 +00:00
Dorian
fad79ff955 fix: nginx startup, kiosk fullscreen, reboot errors, kiosk toggle
- Remove hardcoded Tailscale IP from nginx listen (broke fresh install)
- Generate SSL cert in installer if rootfs missed it (safety net)
- Kiosk: add --start-fullscreen --start-maximized --window-size flags
- Kiosk: remove --disable-gpu (can prevent fullscreen rendering)
- Kiosk: add toggle command and Ctrl+Alt+F1/F7 docs in MOTD
- Reboot: suppress stderr during cleanup to hide flashing errors

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 18:30:13 +00:00
Dorian
0e0c97c203 feat: architecture review fixes, self-update system, CI pipeline, supply chain hardening
Architecture review (all P0+P1 issues now fixed):
- Add 10s timeout to 6 bare Nostr client.connect() calls
- Pin all 12 crypto deps to exact versions from Cargo.lock
- Pin all 15 floating container image tags to exact patch versions
- Add CI pipeline (cargo fmt + clippy + tests, frontend type-check + build)

Self-update system (git.tx1138.com):
- scripts/self-update.sh: pull, build, install, restart with rollback
- systemd timer checks daily at 3 AM
- update.check RPC does git-based checks when repo is present
- update.git-apply RPC triggers self-update from UI
- Default update URL changed from GitHub to git.tx1138.com
- Git added to ISO package list for fresh installs

Documentation:
- CHANGELOG v1.3.1 with all changes
- README updated (version, update system section)
- BETA-PROGRESS session #6 logged
- architecture-review.html: 4 issues marked FIXED, 8/12 refactoring done

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 15:52:26 +00:00
Dorian
13e4a738be bug fixing and deploy and build diagnostics 2026-03-22 03:30:21 +00:00
Dorian
5c3a3ffa8e fix: systemd resource limits, Tor rotation transition, unwrap elimination, RPC timeouts
- I2: Add MemoryMax=4G, LimitNOFILE=65535, TasksMax=2048 to systemd service
- I3: Tor rotation keeps old service for 1h transition before cleanup
- R14: Replace .parse().unwrap() with .unwrap_or(localhost) in rate limiter
- R15: Replace 7 unwrap/expect in mesh protocol with proper error propagation
- R27: Add 10s timeouts to mesh Bitcoin RPC calls

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 01:46:40 +00:00
Dorian
c299199d37 fix: add health RPC handler, Nostr connect timeouts, atomic backup restore, nginx rate limits
- R1: Add health RPC endpoint with crash recovery status, uptime, and version
- R2: Wrap all 5 Nostr client.connect() calls in 10s timeout
- R3: Make backup restore atomic with staging dir and rollback on failure
- I1: Add rate limiting, body size, and proxy timeouts to unauthenticated nginx endpoints

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 01:02:16 +00:00
Dorian
fc1120338d fix: Tor management system, bug fixes, federation name sync
Major changes:
- Full Tor hidden service management via systemd path unit pattern
  (tor-helper.sh + archipelago-tor-helper.path/service) — respects
  NoNewPrivileges=yes, no sudo needed from backend
- Container doctor: prefer system Tor over container, remove archy-tor
- Deploy script: fix torrc generation (read correct services.json path),
  web apps map port 80→local port, enable both tor and tor@default
- Federation: server rename pushes name to peers via background sync
- Server name: fix root-owned file, optimistic store update
- Mesh: local echo for sent messages, sendingArch loading state
- Web5: Message button → Mesh redirect, node name lookup in messages
- PeerFiles: show DID not onion in header
- Connected Nodes: flex-1 instead of fixed max-h
- Toast notifications route to Mesh
- Deploy script: fix single-quote syntax in SSH block

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 02:59:29 +00:00
Dorian
9fe680def1 fix: CORS headers on /lnd-connect-info for cross-origin LND UI fetch
The LND UI runs on port 8081 (separate nginx container) but fetches
/lnd-connect-info from port 80. This is cross-origin, so browsers
block reading the response without CORS headers. Added dynamic
Access-Control-Allow-Origin from $http_origin.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:11:40 +00:00
Dorian
9e15444228 fix: LND Connect — remove nginx cookie gate, rebuild LND UI with credentials
- Nginx cookie check removed for /lnd-connect-info — backend is
  localhost-only so no external access possible. Browsers (especially
  Brave) don't reliably send SameSite=Lax cookies from iframe fetches.
- LND UI source restored from archive with credentials: 'include'
- Discover.vue install banner removed (inline card progress only)
- Server.vue: Connectivity → Tor Status, using tor.list-services

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:02:17 +00:00
Dorian
f20f0650cf feat: Discover view, Fleet dashboard, MeshMap, type fixes
- New Discover.vue (app store redesign)
- Fleet.vue dashboard for .228
- MeshMap.vue component
- Fixed Discover.vue type errors (unused var, type predicate)
- Various UI updates (Apps, Dashboard, Marketplace, Mesh, Web5)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 16:12:01 +00:00
Dorian
c037db9d42 fix: What's New v1.3.0, backend bind 127.0.0.1 in deploy + systemd, dead man's switch permissions
- Added v1.3.0 release notes to Settings "What's New" modal
- Deploy script now auto-fixes backend bind address (0.0.0.0 → 127.0.0.1)
- All image-recipe systemd/service files updated to 127.0.0.1
- Fixed dead man's switch: alert-config.json owned by root, now chown'd
- Removed unused toggleAutoSync function (build error)
- Deploy script adds LND REST port 8080 to Tor config generation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:55:31 +00:00
Dorian
1a74a930f7 security+feat: v1.3.0 — pentest remediation, container reliability, UI overhaul
Security (33 pentest findings addressed):
- CRITICAL: backend binds 127.0.0.1, path traversal in tor.rs/dwn fixed
- HIGH: federation requires signatures, XSS login redirect, RBAC viewer restricted
- HIGH: tar slip prevention, S3 SSRF validation, backup ID validation
- MEDIUM: remember-me random secret, TOTP session rotation, password re-auth
- LOW: CSP unsafe-inline removed, CORS dev-only, onion/webhook validation

Container reliability:
- Memory limits on all 37 containers (OOM prevention)
- Exited vs stopped state distinction with health-aware status badges
- Crash recovery coordination (no more restart cascade)
- User-stopped tracking survives reboots
- Tiered boot recovery (databases → core → services → apps)

UI:
- Wallet TransactionsModal, health-aware app status badges
- Restart button on containers, exited/crashed red state
- Mesh view overhaul, glass button updates, BaseModal/ToggleSwitch
- Apps sticky header removed, dev faucet, mutable mock wallet

Infrastructure:
- LND REST port 8080 exposed over Tor (LND Connect fix)
- Nginx cookie_session fix, deploy script Tor config updated
- Dev environment: podman auto-start, boot mode simulation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:44:31 +00:00
Dorian
c1db74ed28 security(TASK-8): fix M3 AIUI session check + H4 prep
M3: AIUI nginx proxy now checks session_id cookie (actual auth
cookie) instead of generic session cookie. Prevents bypass with
arbitrary cookie values.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 19:46:59 +00:00
Dorian
27f205f38a security(TASK-8): fix 8 pentest findings — C1/C3/H1/M1/M2/L2
CRITICAL:
- C1: /lnd-connect-info now requires session auth, CORS wildcard removed
- C3: DEV_MODE removed from production service file (dev override only)

HIGH:
- H1: node-message endpoint now verifies ed25519 signatures when
  provided, logs warning for unsigned messages

MEDIUM:
- M1: content.add rejects filenames containing ".." (path traversal)
- M2: NIP-07 postMessage responses use specific origin instead of '*'

LOW:
- L2: Onion validation now enforces strict v3 format (56 base32 chars
  + ".onion", exactly 62 chars, no colons)

Previously fixed: C2 (RPC creds generated per-install from secrets)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 19:45:10 +00:00
Dorian
9f90c2cc91 fix: Fedimint Guardian UI on port 8175 (not 8174 API)
Fedimintd serves JSON-RPC API on 8174 and Guardian web UI on 8175.
Updated all port mappings: frontend AppSession, nginx HTTP/HTTPS
proxies, PodmanClient static map.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 17:31:07 +00:00
Dorian
db472691c9 fix: correct port mappings for all container iframes/tabs
Nginx (HTTP+HTTPS): OnlyOffice 9980→8044, Fedimint 8175→8174,
NPM 81→8181, Tailscale removed (no web UI).

Frontend: corrected APP_PORTS, added HTTPS_PROXY_PATHS for portainer/
npm/uptime-kuma/homeassistant/vaultwarden/photoprism/fedimintd.
Added portainer/onlyoffice/npm to NEW_TAB_APPS (X-Frame-Options).

Backend: PodmanClient + docker_packages port corrections.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 16:56:17 +00:00
Dorian
0c8dd582fa fix: rootless podman scanning — relax namespace/syscall restrictions
RestrictNamespaces and SystemCallFilter block rootless podman from
creating user namespaces needed for container isolation. Removed these
along with RestrictSUIDSGID (implied by NoNewPrivileges). ProtectHome
set to no (rootless podman needs ~/.local/share/containers writable).

Remaining active protections: NoNewPrivileges, ProtectSystem=strict,
ReadWritePaths, RestrictAddressFamilies, MemoryDenyWriteExecute,
RestrictRealtime, SystemCallArchitectures=native.

Also reduced initial scan delay from 15s to 3s for faster container
visibility after boot, and removed Ollama from auto-deploy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 14:22:00 +00:00
Dorian
870ff095d8 feat: rootless podman, session hardening, boot stability, sidebar fix
Rootless podman migration (TASK-11):
- Remove sudo from all podman calls in PodmanClient + 8 backend files
- Remove sudo from all podman/docker calls in deploy script
- Restore full systemd security hardening: NoNewPrivileges,
  RestrictAddressFamilies, MemoryDenyWriteExecute, RestrictRealtime,
  RestrictNamespaces, RestrictSUIDSGID, SystemCallFilter, ProtectSystem=strict
- Enable loginctl linger for rootless container persistence
- Remove Ollama from auto-deploy (marketplace-only)

Session & auth hardening:
- Increase MAX_CONCURRENT_SESSIONS 20→50 (prevents eviction storms)
- Debounced 401 redirect in rpc-client.ts (prevents redirect storms)

Boot stability:
- optimize-debian.sh: adds chrony, swap, removes policy-rc.d
- deploy script: pre-restart chrony + swap setup
- ISO build: chrony package, swap file creation
- BootScreen: no longer clears localStorage (prevents splash replay)
- RootRedirect: sole owner of localStorage clearing on server ready

UI fixes:
- Sidebar opacity default changed from 0→visible (fixes missing sidebar
  after page-persistence login without entrance animation)
- Console.log/error wrapped in import.meta.env.DEV guards
- Remove unused route import from RootRedirect

Beta tracking:
- CLAUDE.md: beta freeze protocol added
- MASTER_PLAN.md: TASK-11, TASK-17, phase structure
- BETA-PROGRESS.md: initial tracking doc
- Tagged v1.2.0-alpha.1 as pre-rootless baseline

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:53:27 +00:00
Dorian
934d120243 fix: restore container scanning — relax systemd sandbox for podman
The security hardening (NoNewPrivileges, RestrictAddressFamilies,
MemoryDenyWriteExecute, RestrictRealtime, ProtectSystem=strict) all
blocked podman container management via sudo. These are temporarily
disabled until TASK-11 (rootless podman migration) is complete.

Remaining active protections: ProtectSystem=true (/usr, /boot),
ProtectHome=yes, PrivateTmp=yes, PrivateDevices=no (mesh radio).

Also adds TASK-11 to MASTER_PLAN.md for tracking the rootless podman
migration that will allow re-enabling full security hardening.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:06:35 +00:00
Dorian
b9c9881e4b feat: external iframes, container startup UX, release notes modal
- Add https: to CSP frame-src so external site iframes (BotFights,
  484 Kitchen, etc.) load without being blocked by Content-Security-Policy
- Show spinner + "Starting..." on marketplace cards for containers that
  are booting up, preventing users from re-installing running apps
- Add spinner to transitional state badges (starting/stopping/installing)
  on installed app cards in Apps view
- Add "What's New" button to Settings version card with release notes
  modal covering recent highlights in layman-friendly language

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 11:15:32 +00:00
Dorian
7278397209 fix: bulletproof mesh serial connection — PrivateDevices, auto-detect fallback, backoff
Root cause: systemd PrivateDevices=yes hid /dev/ttyUSB* from the service,
preventing .198 from connecting to its Heltec V3 after the security hardening.

Changes:
- Set PrivateDevices=no in systemd service (serial access needs physical devices;
  other hardening layers remain: NoNewPrivileges, ProtectSystem, RestrictNamespaces)
- Add SupplementaryGroups=dialout for explicit serial permissions
- Add fallback auto-detect when configured serial path fails to open
- Add exponential backoff on reconnect (5s→60s cap) to reduce log spam
- Add pre-open device existence check with actionable error messages
- Add udev rule (99-mesh-radio.rules) for stable /dev/mesh-radio symlink
- Add /dev/mesh-radio to serial candidate list (checked first)
- Add Connect button per detected device in Mesh UI
- Deploy udev rule to both servers and ISO build
- Fix FEDI_HASH unbound variable in deploy script
- Fix deploy binary step to handle hung service stop gracefully

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:50:13 +00:00
Dorian
428d11c8e2 security hardening 2026-03-18 09:56:40 +00:00
Dorian
022e7e484a feat: Phase 6 — nginx security headers, CSP hardening, rate limiting
- CSP: removed unsafe-eval, tightened frame-src to self + host ports,
  added frame-ancestors, base-uri, form-action directives
- X-Frame-Options: SAMEORIGIN added after proxy_hide_header on all app proxies
- HSTS: max-age=31536000; includeSubDomains on all server blocks
- Rate limiting: 20r/s on /rpc/ with burst=40, 3r/s auth zone
- Added X-DNS-Prefetch-Control, Permissions-Policy payment=() header

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 00:57:16 +00:00