From 37f32f4e542cd2d4dd13d46cd2e736847c8a7935 Mon Sep 17 00:00:00 2001 From: Dorian Date: Sun, 29 Mar 2026 21:56:38 +0100 Subject: [PATCH] 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) --- .gitea/workflows/build-iso-dev.yml | 1 + core/archipelago/src/api/rpc/dispatcher.rs | 2 +- core/archipelago/src/api/rpc/package/install.rs | 8 +++++--- image-recipe/build-auto-installer-iso.sh | 15 +++++++++++++++ neode-ui/src/api/filebrowser-client.ts | 10 ++++++++-- neode-ui/src/views/marketplace/marketplaceData.ts | 2 +- 6 files changed, 31 insertions(+), 7 deletions(-) diff --git a/.gitea/workflows/build-iso-dev.yml b/.gitea/workflows/build-iso-dev.yml index 116448de..bf23a479 100644 --- a/.gitea/workflows/build-iso-dev.yml +++ b/.gitea/workflows/build-iso-dev.yml @@ -26,6 +26,7 @@ jobs: - name: Build backend run: | source $HOME/.cargo/env 2>/dev/null || true + export GIT_HASH=$(git rev-parse --short HEAD) cargo build --release --manifest-path core/Cargo.toml - name: Build frontend diff --git a/core/archipelago/src/api/rpc/dispatcher.rs b/core/archipelago/src/api/rpc/dispatcher.rs index 0fed132c..70d04788 100644 --- a/core/archipelago/src/api/rpc/dispatcher.rs +++ b/core/archipelago/src/api/rpc/dispatcher.rs @@ -393,7 +393,7 @@ impl RpcHandler { "status": status, "crash_recovery_complete": recovery_complete, "uptime_seconds": uptime, - "version": env!("CARGO_PKG_VERSION"), + "version": format!("{}-{}", env!("CARGO_PKG_VERSION"), option_env!("GIT_HASH").unwrap_or("dev")), })) } } diff --git a/core/archipelago/src/api/rpc/package/install.rs b/core/archipelago/src/api/rpc/package/install.rs index 0f871440..0efa8f3d 100644 --- a/core/archipelago/src/api/rpc/package/install.rs +++ b/core/archipelago/src/api/rpc/package/install.rs @@ -452,11 +452,13 @@ impl RpcHandler { /// Default subuid start for archipelago user is 100000. fn mapped_uid(package_id: &str) -> u32 { let container_uid = match package_id { - "bitcoin-knots" | "bitcoin" => 101, + "bitcoin-knots" | "bitcoin" | "bitcoin-core" => 101, "grafana" => 472, "lnd" => 1000, - "mariadb" | "mysql" => 999, - "postgres" | "btcpay-postgres" | "immich-postgres" | "penpot-postgres" => 70, + "mariadb" | "mysql" | "mysql-mempool" | "archy-mempool-db" => 999, + "postgres" | "btcpay-postgres" | "immich-postgres" | "penpot-postgres" + | "archy-btcpay-db" | "nextcloud-db" => 70, + "electrumx" | "electrs" => 1000, _ => 0, // Most containers run as root (UID 0) }; 100000 + container_uid diff --git a/image-recipe/build-auto-installer-iso.sh b/image-recipe/build-auto-installer-iso.sh index e97c69bf..e9c0d9f9 100755 --- a/image-recipe/build-auto-installer-iso.sh +++ b/image-recipe/build-auto-installer-iso.sh @@ -1285,6 +1285,15 @@ loginctl enable-linger archipelago 2>/dev/null || true runuser -u archipelago -- bash -c 'export XDG_RUNTIME_DIR=/run/user/1000 && systemctl --user enable --now podman.socket' 2>>"$LOG" || true # Create FileBrowser container as archipelago user (rootless podman) +# Generate random FileBrowser password and store for auto-login +FB_PASS_DIR="/var/lib/archipelago/secrets/filebrowser" +mkdir -p "$FB_PASS_DIR" +if [ ! -f "$FB_PASS_DIR/password" ]; then + head -c 24 /dev/urandom | base64 | tr -d '/+=' | head -c 24 > "$FB_PASS_DIR/password" + chmod 600 "$FB_PASS_DIR/password" + chown 1000:1000 "$FB_PASS_DIR/password" +fi + if ! runuser -u archipelago -- bash -c 'export XDG_RUNTIME_DIR=/run/user/1000 && podman ps -a --format "{{.Names}}"' 2>/dev/null | grep -q filebrowser; then echo "[$(date)] Creating FileBrowser container ($FILEBROWSER_IMAGE)..." >> "$LOG" runuser -u archipelago -- bash -c "export XDG_RUNTIME_DIR=/run/user/1000 && podman run -d --name filebrowser --restart unless-stopped \ @@ -1305,6 +1314,12 @@ if ! runuser -u archipelago -- bash -c 'export XDG_RUNTIME_DIR=/run/user/1000 && --database=/data/database.db --root=/srv --address=0.0.0.0 --port=80" 2>>"$LOG" && \ echo "[$(date)] FileBrowser created successfully" >> "$LOG" || \ echo "[$(date)] WARNING: FileBrowser creation failed" >> "$LOG" + # Set FileBrowser password to match the stored random password + sleep 5 + FB_PASS=$(cat "$FB_PASS_DIR/password" 2>/dev/null || echo "admin") + runuser -u archipelago -- bash -c "export XDG_RUNTIME_DIR=/run/user/1000 && podman exec filebrowser filebrowser users update admin --password '$FB_PASS' --database /data/database.db" 2>>"$LOG" && \ + echo "[$(date)] FileBrowser admin password set" >> "$LOG" || \ + echo "[$(date)] WARNING: Could not set FileBrowser password" >> "$LOG" fi echo "[$(date)] Minimal first-boot complete" >> "$LOG" FBUNBUNDLED diff --git a/neode-ui/src/api/filebrowser-client.ts b/neode-ui/src/api/filebrowser-client.ts index c65a94f0..18c91af9 100644 --- a/neode-ui/src/api/filebrowser-client.ts +++ b/neode-ui/src/api/filebrowser-client.ts @@ -55,11 +55,17 @@ class FileBrowserClient { async login(): Promise { try { // Get a filebrowser JWT via the authenticated backend (no credentials exposed to browser) + // Use credentials: 'include' and CSRF token for proper auth + const csrfMatch = document.cookie.match(/(?:^|;\s*)csrf_token=([^;]+)/) + const csrfToken = csrfMatch ? csrfMatch[1]! : '' + const headers: Record = { 'Content-Type': 'application/json' } + if (csrfToken) headers['X-CSRF-Token'] = csrfToken + const rpcRes = await fetch('/rpc/v1', { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers, body: JSON.stringify({ method: 'app.filebrowser-token' }), - credentials: 'same-origin', + credentials: 'include', }) if (!rpcRes.ok) return false const rpcData = await rpcRes.json() diff --git a/neode-ui/src/views/marketplace/marketplaceData.ts b/neode-ui/src/views/marketplace/marketplaceData.ts index 91f3a747..1e23e571 100644 --- a/neode-ui/src/views/marketplace/marketplaceData.ts +++ b/neode-ui/src/views/marketplace/marketplaceData.ts @@ -412,7 +412,7 @@ export function getCuratedAppList(): MarketplaceApp[] { description: 'Run your own Nostr relay. Store your events locally, relay for friends, and publish over Tor. A sovereign relay for your sovereign node.', icon: '/assets/img/app-icons/nostr-rs-relay.svg', author: 'scsiblade', - dockerImage: `${REGISTRY}/nostr-rs-relay:0.9.0`, + dockerImage: 'docker.io/scsibug/nostr-rs-relay:0.9.0', manifestUrl: undefined, repoUrl: 'https://sr.ht/~gheartsfield/nostr-rs-relay/' },