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>
- 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>
- BUG-33: CPU load alert threshold increased from 2x to 4x core count
(8→16 on 4-core machine) to reduce false alerts during container ops
- TASK-27: Launch buttons for new-tab apps now show external link icon
(BTCPay, Grafana, PhotoPrism, Portainer, OnlyOffice, etc.)
- TASK-36: Iframe error screen now distinguishes between X-Frame-Options
blocked vs container not reachable, with appropriate messaging
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
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>
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>
- 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>
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>
- 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>
Switch IndeedHub to staging API, add _next asset caching in nginx,
simplify NostrIdentityPicker component, and update Apps/Web5/Marketplace views.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: sd_notify::notify(true, ...) cleared NOTIFY_SOCKET env var,
so watchdog pings never reached systemd. Backend killed every 60s.
Fixes:
- Change sd_notify::notify first param to false (keep socket)
- Increase WatchdogSec from 60 to 300 (5min) for crash recovery
- Add TimeoutStartSec=300 for slow container startups
- Adjust watchdog ping interval to 120s
This was causing 47 restarts/day on .198 and blocking REBOOT-03,
FLEET-03, FLEET-04, VC-04.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Simplify DHT encoding: use JSON instead of DNS packets (drop simple-dns)
- Fix mainline crate API: SigningKey takes 32 bytes, get_mutable returns Result
- Add missing dht_did field to IdentityRecord constructor
- Store DID Document as JSON in DHT (DNS encoding deferred)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MEM-01: OOM kill detection via dmesg checks every 5 minutes
MEM-03: Disk growth rate tracking (288 samples over 24h), warns at >1GB/day
MEM-04: Systemd watchdog (WatchdogSec=60, sd_notify::Watchdog every 30s)
Service Type=notify for proper startup notification
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add /content and /dwn proxy locations to nginx config (both HTTP and HTTPS)
so peer requests reach the backend instead of the SPA catch-all
- Update content_file_path() to check FileBrowser data dir as fallback when
files aren't in the dedicated content/files/ directory
- Populate size_bytes from actual file metadata in content.add
- Filter out availability:nobody items from the public catalog endpoint
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added nostrudel.ninja as a web-only app in Marketplace (community category).
Configured nginx reverse proxy at /ext/nostrudel/ with NIP-07 provider
injection in both HTTP and HTTPS blocks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added new dependencies: `adler2`, `crc32fast`, `flate2`, `miniz_oxide`, and `libredox`.
- Updated existing dependencies: `tokio-rustls` to version 0.26.4 and `filetime` to version 0.2.27.
- Removed the `backup.rs` file as it is no longer needed.
- Introduced tests for configuration and credential management.
- Enhanced the `identity` module to generate W3C compliant DID documents.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace sh -c echo with tokio::fs::write for bitcoin.conf generation
- Add client_max_body_size 1m to /rpc/ in both HTTP and HTTPS nginx blocks
- Document full audit findings in docs/security-audit-2026-03-11.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Security headers already present in nginx config (X-Content-Type-Options,
X-Frame-Options, CSP, Referrer-Policy, Permissions-Policy). Removed
Access-Control-Allow-Origin: * from electrs-status — CORS is now handled
by the backend with origin validation. Deployed and verified all headers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The My Apps page went blank after installing apps because pkg['static-files'].icon
was accessed without optional chaining on dynamically installed packages that lack
the static-files property.
- Make static-files optional in PackageDataEntry type
- Add defensive ?.icon access with fallback in Apps.vue and AppDetails.vue
- Add filebrowser to mock backend staticDevApps (enables Cloud page in demo)
- Expand portMappings and marketplaceMetadata for all marketplace apps
- installPackage now uses staticApp() format for consistent data shape
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Set http1_keep_alive(false) on hyper server to prevent connection
reuse issues with nginx reverse proxy
- Clean up nginx proxy config: remove upstream block, use direct
proxy_pass to 127.0.0.1:5678
- Update AppLauncherOverlay and appLauncher store with UI fixes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The credential issuance and verification handlers used
Handle::block_on() directly inside the tokio runtime, causing a
deadlock. Wrapped with block_in_place() to properly yield the
runtime thread.
Also completed full feature verification across all 25 test groups
(~175 checks) on live server.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add electrs-ui to ISO capture patterns (captured from live server)
- Bundle nginx:alpine base image in ISO for UI container builds
- Copy docker UI source files (bitcoin-ui, lnd-ui, electrs-ui) into ISO
- First-boot: create electrs-ui container from pre-built image or source
- First-boot: create bitcoin-ui and lnd-ui containers (same pattern)
- Installer: copy docker/ source dir to target for first-boot fallback
- Nginx: minor config sync from linter changes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add electrs to marketplace as standalone installable app
- Add dependency check: refuse install if no bitcoin node is running
- Use container DNS (bitcoin-knots:8332) on archy-net instead of host IP
- Auto-create bitcoin.conf with txindex + RPC on bitcoin-knots install
- Auto-build and start electrs-ui container post-install
- Show index size and estimated progress during initial sync
- Add /electrs-status and /health nginx proxy routes
- Remove Tailwind CDN from electrs-ui, use inline styles
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create Ollama provider plugin in AIUI (ollama-provider.ts)
- Register Ollama alongside Claude in plugin system
- Auto-detect installed models via /api/tags endpoint
- Add Ollama proxy in mock backend (forwards to localhost:11434)
- Add nginx proxy rules for /aiui/api/ollama/ (both HTTP and HTTPS)
- Rebuild AIUI dist with Ollama provider included
- Qwen 2.5 Coder 3B installed on dev server via Ollama
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Convert "Choose Your Path" screen to informative (read-only cards)
- Harden "Choose Your Setup" (gray out Coming Soon options, auto-select Fresh Start)
- Auto-fetch DID on mount with retry and auto-advance after success
- Improve backup download for mobile compatibility
- Add retry logic to verify step with graceful skip option
- Route verify → done → login for complete onboarding flow
- Add AIUI install confirmation via custom event (SEC-001)
- Add file path whitelist for AIUI file access (SEC-002)
- Add log redaction for container logs sent to AIUI (SEC-003)
- Add Secure flag to session cookie in production (SEC-004)
- Fix ISO build script to handle zstd compression errors gracefully
- Sync archipelago.service from live server
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Redesign favicon SVG with gradient border matching splash screen
- Rename all icon files with -v2 suffix to bypass browser/SW/PWA caches
- Delete 9 old/duplicate icon files (~13MB removed)
- Add nginx cache-control headers for icons and manifest
- Rename assets-cache to assets-cache-v2 to orphan stale SW cache
- Update all HTML, manifest, and component icon references
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added proxy configurations for Grafana (3000), Jellyfin (8096), Uptime Kuma
(3001), Portainer (9000), OnlyOffice (9980), and all remaining apps (SearXNG,
LND, Mempool, PhotoPrism, Fedimint, Tailscale, Ollama, Bitcoin UI, Electrs,
Endurain, Nginx Proxy Manager, BTCPay, Home Assistant) to the HTTP server
block. Previously these were only available via HTTPS. Also added
client_max_body_size and proxy_request_buffering to the HTTPS filebrowser
snippet for large file uploads.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add native Cloud file browser with FileBrowser API integration
- Add cloud store, filebrowser-client, useAudioPlayer, useFileType composables
- Add Cloud components: FileGrid, FileCard, FileCardGrid, CloudToolbar
- Add Claude authentication section to Settings with OAuth status check
- Harden deploy script to preserve /aiui/ and claude-login.html
- Add nginx proxies for btcpay, homeassistant, filebrowser (HTTPS block)
- Add app configs for filebrowser, searxng, penpot in package.rs
- Update goal progress tracking with app aliases
- Improve mobile back button composable with ResizeObserver
- Update various views with cloud integration and UI refinements
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Protocol: 10 context categories (apps, system, network, bitcoin, media, files, notes, search, ai-local, wallet)
- ContextBroker: real data wiring for all categories with sanitization
- Permissions: user toggles for all categories in Settings
- Nginx: Claude API, OpenRouter, SearXNG proxy pass-through
- Actions: launch-app, search-web, install-app handlers
- Chat.vue: loading state + connection indicator
- Integration test page: test-aiui.html
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>