From cd6f8bad70ab51796b21691e40f7f9fd8bf849b0 Mon Sep 17 00:00:00 2001 From: archipelago Date: Thu, 23 Apr 2026 12:02:46 -0400 Subject: [PATCH] fix(install-log): pre-create /var/log/archipelago/ so non-root backend can write The backend runs as `archipelago` and calls `install_log()` to append audit lines to the install log on every install / update / remove / start / stop / restart. Target path was /var/log/archipelago-container-installs.log, which does not exist and cannot be created by the service because /var/log/ is root-owned. OpenOptions errors were silently swallowed, so the log was never written on any node. Ship a tmpfiles.d rule that pre-creates /var/log/archipelago/ and container-installs.log with archipelago:archipelago ownership. Move the const path to match, keeping logs inside the directory logrotate already rotates (image-recipe/configs/logrotate.conf). Install the rule from both the ISO build and self-update, and apply it immediately on self-update so existing nodes get a working log without needing a reboot. Verified on .228: file created, backend user can write, backend binary rebuilt with new const. --- core/archipelago/src/api/rpc/package/install.rs | 2 +- core/archipelago/src/api/rpc/transitional.rs | 2 +- image-recipe/build-auto-installer-iso.sh | 8 ++++++++ image-recipe/configs/archipelago-tmpfiles.conf | 10 ++++++++++ scripts/self-update.sh | 11 +++++++++++ 5 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 image-recipe/configs/archipelago-tmpfiles.conf diff --git a/core/archipelago/src/api/rpc/package/install.rs b/core/archipelago/src/api/rpc/package/install.rs index 8a2c903d..ab9f44d6 100644 --- a/core/archipelago/src/api/rpc/package/install.rs +++ b/core/archipelago/src/api/rpc/package/install.rs @@ -14,7 +14,7 @@ use anyhow::{Context, Result}; use tokio::io::{AsyncBufReadExt, BufReader}; use tracing::{debug, info, warn}; -const INSTALL_LOG: &str = "/var/log/archipelago-container-installs.log"; +const INSTALL_LOG: &str = "/var/log/archipelago/container-installs.log"; /// Append a timestamped line to the persistent install log. pub(in crate::api::rpc) async fn install_log(msg: &str) { diff --git a/core/archipelago/src/api/rpc/transitional.rs b/core/archipelago/src/api/rpc/transitional.rs index 63b3758c..2f330cf4 100644 --- a/core/archipelago/src/api/rpc/transitional.rs +++ b/core/archipelago/src/api/rpc/transitional.rs @@ -15,7 +15,7 @@ //! 3. on success, writes the final state (`Stopped` / `Running`). //! 4. on error, reverts to the pre-transition state and logs via //! `install_log()` so the incident shows up in -//! `/var/log/archipelago-container-installs.log`. +//! `/var/log/archipelago/container-installs.log`. //! //! The server.rs package-scan loop must also be taught to preserve //! transitional states — see `server.rs:scan_and_update_packages`'s merge diff --git a/image-recipe/build-auto-installer-iso.sh b/image-recipe/build-auto-installer-iso.sh index e5aba26f..bf9675fa 100755 --- a/image-recipe/build-auto-installer-iso.sh +++ b/image-recipe/build-auto-installer-iso.sh @@ -2993,6 +2993,14 @@ chown -R 1000:1000 /mnt/target/home/archipelago/.config 2>/dev/null || true mkdir -p /mnt/target/etc/tmpfiles.d echo 'd /run/user/1000 0700 archipelago archipelago -' > /mnt/target/etc/tmpfiles.d/archipelago-runtime.conf +# Pre-create /var/log/archipelago/ and container-installs.log so the +# backend (running as `archipelago`) can append to them without needing +# root. Logrotate rotates files in this directory daily. +cat > /mnt/target/etc/tmpfiles.d/archipelago-logs.conf <<'LOGSTMPFILES' +d /var/log/archipelago 0755 archipelago archipelago - - +f /var/log/archipelago/container-installs.log 0644 archipelago archipelago - - +LOGSTMPFILES + # Bootstrap switchover — checks when local Bitcoin finishes IBD and switches services cat > /mnt/target/etc/systemd/system/archipelago-bootstrap-switchover.service <<'BSSERVICE' [Unit] diff --git a/image-recipe/configs/archipelago-tmpfiles.conf b/image-recipe/configs/archipelago-tmpfiles.conf new file mode 100644 index 00000000..8531c1f4 --- /dev/null +++ b/image-recipe/configs/archipelago-tmpfiles.conf @@ -0,0 +1,10 @@ +# Archipelago persistent log directory and files +# Runtime log destination. Backend runs as `archipelago`, but /var/log/ +# is root-owned, so we pre-create the directory and log files with the +# right ownership at boot / install-time. +# +# Logrotate (image-recipe/configs/logrotate.conf) rotates files in this +# directory daily, keeping 30 compressed copies. + +d /var/log/archipelago 0755 archipelago archipelago - - +f /var/log/archipelago/container-installs.log 0644 archipelago archipelago - - diff --git a/scripts/self-update.sh b/scripts/self-update.sh index 5549d096..4261cd0e 100755 --- a/scripts/self-update.sh +++ b/scripts/self-update.sh @@ -198,6 +198,17 @@ if [ -f "$REPO_DIR/image-recipe/configs/archipelago.service" ]; then fi fi +# Install/refresh tmpfiles.d rules. The logs rule creates +# /var/log/archipelago/ + container-installs.log with archipelago:archipelago +# ownership so the non-root backend can append install audit lines. +# Apply immediately so existing nodes don't need a reboot. +if [ -f "$REPO_DIR/image-recipe/configs/archipelago-tmpfiles.conf" ]; then + sudo install -m 644 "$REPO_DIR/image-recipe/configs/archipelago-tmpfiles.conf" \ + /usr/lib/tmpfiles.d/archipelago-logs.conf + sudo systemd-tmpfiles --create /usr/lib/tmpfiles.d/archipelago-logs.conf 2>/dev/null || true + ok "Log tmpfiles rule installed" +fi + # Restart service log "Restarting archipelago service..." sudo systemctl restart archipelago