Contain the Litestream sidecar's write access to the database volume

Review finding F-01: the litestream service mounts nestquest-db
read-write. A read-only mount is not possible: Litestream 0.5.17 fails
with "unable to open database file (14)" on a :ro mount, even with
meta-path moved to a separate writable volume, because it writes its
_litestream_seq/_litestream_lock tables into the database, opens the
-wal/-shm files for writing and checkpoints the WAL.

Keep the write mount and contain it instead: run as the API's non-root
volume owner (999:999) with a read-only root filesystem (tmpfs /tmp),
no-new-privileges and all capabilities dropped. Document why in
compose and api/README.md, including the key chown the uid change needs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-24 08:28:57 -04:00
co-authored by Claude Opus 5.5
parent 89a10edc38
commit 442339f887
2 changed files with 29 additions and 1 deletions
+12 -1
View File
@@ -59,7 +59,18 @@ box and is git-ignored. Create it once, before ``up``:
then append ``restrict `` + the contents of ``deploy/litestream_key.pub``
to ``joshua@10.60.1.50:~/.ssh/authorized_keys``. Compose mounts the
private key read-only at ``/etc/litestream/sftp_key``.
private key read-only at ``/etc/litestream/sftp_key``. The sidecar runs
as uid/gid 999 (the API's ``nestquest`` user), so give it the key:
sudo chown 999:999 deploy/litestream_key && chmod 600 deploy/litestream_key
The sidecar needs WRITE access to the database volume: Litestream adds
its own ``_litestream_seq``/``_litestream_lock`` tables to the database,
writes the ``-wal``/``-shm`` files and checkpoints the WAL, and fails
with "unable to open database file" on a read-only mount. That access
is contained rather than removed — the sidecar runs as the non-root
volume owner with a read-only root filesystem, ``no-new-privileges``
and all Linux capabilities dropped.
Check replication with
``docker compose -f deploy/compose.yaml logs litestream`` or
+17
View File
@@ -46,10 +46,27 @@ services:
# volume to the Synology NAS over SFTP (config: deploy/litestream.yml).
# The SFTP private key deploy/litestream_key is git-ignored and must be
# created on the API box before starting (see api/README.md).
#
# The database volume is mounted READ-WRITE on purpose: Litestream
# cannot run against a read-only mount ("unable to open database file
# (14)", even with its metadata moved elsewhere) because it writes its
# _litestream_seq/_litestream_lock tables into the database, opens the
# -wal/-shm files for writing, and checkpoints the WAL. The write
# access is contained instead: it runs as the API's own non-root user
# (uid/gid 999, owner of the volume) with a read-only root filesystem,
# no privilege escalation and no Linux capabilities.
litestream:
image: litestream/litestream:0.5.17
restart: unless-stopped
command: ["replicate", "-config", "/etc/litestream.yml"]
user: "999:999"
read_only: true
tmpfs:
- /tmp
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
depends_on:
api:
condition: service_healthy