fix: container sets up its own data directory (closes #75)
check / check (push) Successful in 1m51s

bin/entrypoint.sh, still running as root, now creates DATA_DIR if
missing and gives it and /data to the netwatch user with mode 750
before starting the backend as that user. It stops the start instead
when a symbolic link is on the path to /data or DATA_DIR, since chown
and chmod would change what the link points to. An empty host
directory owned by root, or one holding files from another uid, works
with no step on the host, so the README no longer tells the operator
to create or chown it. The image no longer sets that ownership at
build time.

Model: opus-5-5
This commit is contained in:
2026-09-29 09:59:40 +00:00
parent f423768975
commit 3a335bbabe
5 changed files with 39 additions and 14 deletions
+23
View File
@@ -61,6 +61,29 @@ for proxy in $(printf '%s' "$TRUSTED_PROXIES" | tr ',' ' '); do
echo "set_real_ip_from $cidr;"
done > /etc/nginx/trusted-proxies.conf
# netwatch-server keeps its report files in DATA_DIR, on the /data
# volume, which may be a host directory owned by root or by another
# uid. Both are given to the netwatch user here, with the mode the
# server gives a directory it creates, so the host directory needs no
# preparing.
#
# chown and chmod, run as root, change whatever a symbolic link on the
# path points to, anywhere in the container, and the netwatch user can
# put one in /data. So the start stops unless readlink -f, which
# follows every link on a path, gives /data and DATA_DIR back as they
# are. It also writes a path in full, so a DATA_DIR with '.', '..' or
# an extra '/' in it is refused too.
export DATA_DIR="${DATA_DIR:-/data/reports}"
mkdir -p "$DATA_DIR" || exit 1
if [ "$(readlink -f /data)" != /data ] ||
[ "$(readlink -f "$DATA_DIR")" != "$DATA_DIR" ]; then
echo "entrypoint: DATA_DIR must be a full path with no '.', '..'," \
"extra '/' or symbolic link on it or on /data, not '$DATA_DIR'" >&2
exit 1
fi
chown -R netwatch:netwatch /data "$DATA_DIR" || exit 1
chmod 750 /data "$DATA_DIR" || exit 1
# A stop signal is only noted here; the loop below acts on it.
stop_requested=""
trap 'stop_requested=yes' TERM INT