mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix(docker): make storage writable under non-root/foreign UIDs (TrueNAS, OpenShift) (#299)
The entrypoint only fixed volume permissions when started as root (chown +
gosu-drop to snapotter). Launched under a non-root/foreign UID (TrueNAS app
user, Kubernetes runAsUser, OpenShift) it did no permission setup, so /data and
/tmp/workspace -- owned by uid 999 from the image -- were not writable by the
running user. Uploads and processing then failed with a cryptic EACCES
("workspace folder is not writable") and AI bundle installs failed the same way,
while health checks still reported the container healthy.
- entrypoint: source new entrypoint-lib.sh; verify writability up front when
non-root, and as snapotter after chown when root (catches root-squashed
mounts), failing fast with an actionable message (which dir, uid/gid, how to
fix) instead of a late, cryptic EACCES
- Dockerfile: own /data and /tmp/workspace as snapotter:0, group-writable with
setgid, so an arbitrary UID with the root supplementary group (OpenShift /
Kubernetes fsGroup) can write; keep /opt/venv world-readable for the AI venv
bootstrap under arbitrary UIDs
- api: assert storage writability at boot (lib/storage-writable.ts), failing
fast with the same guidance even when the entrypoint is bypassed
- docs: add a Storage permissions section (named volumes, bind mounts, TrueNAS,
Kubernetes/OpenShift) and cross-link it from the security guide
Fixes #230
This commit is contained in:
+14
-2
@@ -393,10 +393,22 @@ ENV PYTHONWARNINGS=default \
|
||||
|
||||
# Create non-root user for runtime
|
||||
RUN groupadd -r snapotter && useradd -r -g snapotter -d /app -s /sbin/nologin snapotter
|
||||
RUN chown -R snapotter:snapotter /app /data /tmp/workspace /opt/venv
|
||||
# /app and /opt/venv are read-only at runtime -> owned by snapotter.
|
||||
# /data and /tmp/workspace are written at runtime: make them group-0 (root group)
|
||||
# owned and group-writable with the setgid bit so the app can still write when the
|
||||
# container is launched under an arbitrary/foreign UID (Kubernetes runAsUser,
|
||||
# OpenShift, TrueNAS), which always lands in the root (GID 0) supplementary group.
|
||||
# The root entrypoint re-chowns these to snapotter for the default gosu path.
|
||||
RUN chown -R snapotter:snapotter /app /opt/venv && \
|
||||
chmod -R a+rX /opt/venv && \
|
||||
chown -R snapotter:0 /data /tmp/workspace && \
|
||||
chmod -R g+rwX /data /tmp/workspace && \
|
||||
find /data /tmp/workspace -type d -exec chmod g+s {} +
|
||||
|
||||
# Entrypoint fixes volume permissions then drops to snapotter via gosu
|
||||
# Entrypoint fixes volume permissions then drops to snapotter via gosu.
|
||||
# entrypoint-lib.sh holds the writability helpers it sources at startup.
|
||||
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
COPY docker/entrypoint-lib.sh /usr/local/bin/entrypoint-lib.sh
|
||||
COPY docker/wait-for-postgres.mjs /app/docker/wait-for-postgres.mjs
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
|
||||
|
||||
Reference in New Issue
Block a user