Skip to content

fix(logs): retention can delete archived originals — rw mount + dir ownership (#1478)#1509

Merged
vybe merged 1 commit into
devfrom
fix/1478-log-retention-rw-mount
Jul 8, 2026
Merged

fix(logs): retention can delete archived originals — rw mount + dir ownership (#1478)#1509
vybe merged 1 commit into
devfrom
fix/1478-log-retention-rw-mount

Conversation

@dolho

@dolho dolho commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Closes #1478.

Problem

LOG_RETENTION_DAYS archived old logs but never freed disk — every delete failed Errno 30: Read-only file system, volume grew unbounded (~900MB/day; eu2 hit 32G).

Two blocking layers (both fixed)

  1. Read-only mountdocker-compose.prod.yml and docker-compose.yml both mounted trinity-logs:/data/logs:ro on the backend (the issue assumed dev was rw — it wasn't). → changed to rw. Vector stays the sole writer of new lines; backend only reads (gzip) + deletes archived originals.
  2. Directory ownership — Vector runs as root and creates /data/logs root:root 0755, so even rw the backend (UID 1000) can't unlink (deleting needs write on the directory). Vector can't self-fix (cap_drop: ALL → no CAP_CHOWN). → added a one-shot logs-init container (root alpine) that chown 1000:1000 + chmod 775 the dir before the backend starts (depends_on: service_completed_successfully). Chowns the dir only (fast, not -R); Vector's future root-owned files stay deletable via the writable dir.

Plus: log_archive_service.start() now logs a WARNING if LOG_DIR isn't writable — visible at startup instead of silent per-file errors at cleanup_hour.

Verified live (dev)

  • Reproduced :ro: touch /data/logs/... → Read-only file system.
  • After fix: dir 1000:1000 775; backend writes; a root-owned file in /data/logs is deletable by UID 1000 (Errno 30 gone). logs-init exits 0.

Notes

  • logs-init runs as root (needs CAP_CHOWN) but uses a stock alpine image, not a Trinity-built one — Invariant Client/Viewer User Role (AUTH-002) #17 ("Trinity-built images non-root") doesn't apply; it's ephemeral (exits immediately).
  • Alternative considered: run Vector as UID 1000 — rejected because Vector needs root for the Docker-socket / file log sources (dev override reads root-owned /var/lib/docker).

🤖 Generated with Claude Code

…wnership (#1478)

LOG_RETENTION_DAYS archived old log files but never freed disk: the backend
mounted the logs volume read-only, so log_archive_service.unlink() failed per file
(`Errno 30: Read-only file system`) and the volume grew unbounded (~900MB/day; eu2
hit 32G).

Two layers were blocking the delete:

1. **Read-only mount** — docker-compose.prod.yml AND docker-compose.yml both mounted
   `trinity-logs:/data/logs:ro` on the backend. Changed to read-write. Vector stays
   the sole writer of new log lines; the backend only reads (to gzip) + deletes the
   archived originals.

2. **Directory ownership** — Vector runs as root and creates `/data/logs` root:root
   0755, so even rw the backend (UID 1000) can't unlink (deleting a file needs write
   on the *directory*). Vector can't fix it itself (cap_drop: ALL → no CAP_CHOWN).
   Added a one-shot `logs-init` container (root, alpine) that `chown 1000:1000` +
   `chmod 775` the dir before the backend starts (depends_on: completed). Chowns the
   dir only (fast, not -R); Vector's future root-owned files stay deletable via the
   now-writable dir.

Also: log_archive_service.start() logs a WARNING at startup if LOG_DIR isn't
writable, so the failure is visible instead of silent per-file errors at cleanup_hour.

Verified live (dev): reproduced the `:ro` failure; after the fix the dir is
1000:1000 775, backend writes, and a root-owned file in /data/logs is deletable by
UID 1000 (Errno 30 gone).

Closes #1478.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dolho
dolho requested a review from vybe July 7, 2026 13:22
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

⚠️ Nightly unit-suite check skipped — merge conflict against dev.

Resolve by running git merge dev locally and pushing the result. The next nightly run will re-test once the conflict is gone.

@vybe vybe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validated via /validate-pr: required checks green, no secrets/PII, scope focused. Approving for sequential merge to dev.

@vybe
vybe merged commit 60a16d9 into dev Jul 8, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants