From 4e93259c047b64bce419557e6ea5082912de507e Mon Sep 17 00:00:00 2001 From: marc Date: Sat, 8 Aug 2026 13:13:45 +0200 Subject: [PATCH] Document putting the data directory under /root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /root is mode 0700 and the container runs as uid 1000, so it cannot even traverse it — the server fails to write no matter who owns the directory underneath. Both ways out are written down, with the trade each makes: chmod o+x /root keeps the unprivileged container and still refuses ls, running as uid 0 avoids the chmod but puts a break-out on root. Also noted that the path has to start with / or ./, since anything else is read as a named volume name. Co-Authored-By: Claude Opus 5 --- .env.example | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index d759239..ec957eb 100644 --- a/.env.example +++ b/.env.example @@ -30,12 +30,37 @@ INKNOTE_ADMIN_USER= INKNOTE_ADMIN_PASSWORD= # ── Where the data lives ── -# A plain directory on the Docker host, so the host's own backup covers it. -# Create it before the first start: +# A plain directory on the Docker host — a bind mount, not a Docker volume, so +# that whatever backs up the host also backs up InkNote. Create it first; the +# container runs unprivileged and cannot create it for you: +# # mkdir -p /srv/inknote/{db,uploads} && chown -R 1000:1000 /srv/inknote +# # INKNOTE_DATA_DIR=/srv/inknote # dev compose defaults to ./data # INKNOTE_UID=1000 # must own the directory above # INKNOTE_GID=1000 +# +# The path must start with / or ./ — anything else Docker reads as the name of +# a named volume, and a name containing a slash simply fails. +# +# ── Putting it under /root ── +# /root is normally mode 0700, and uid 1000 cannot even pass through it, so the +# server would fail to write however the directory itself is owned. Two ways +# out; the first keeps the unprivileged container and is the better trade: +# +# A) let uid 1000 traverse /root, without making it readable: +# mkdir -p /root/inknote/{db,uploads} +# chown -R 1000:1000 /root/inknote +# chmod o+x /root # traverse only — ls /root still refused +# INKNOTE_DATA_DIR=/root/inknote +# +# B) run the container as root instead — no chown, no chmod, but a break-out +# lands on root rather than on an unprivileged user: +# INKNOTE_DATA_DIR=/root/inknote +# INKNOTE_UID=0 +# INKNOTE_GID=0 +# +# Neither is needed under /srv or /opt, which is why those are the default. # ── Optional tuning ── # Leave unset to keep the defaults shown.