From f087fdc056c6c93eeae41219934b97097a1d7425 Mon Sep 17 00:00:00 2001 From: Mitchell R Date: Tue, 19 May 2026 04:00:58 +0200 Subject: [PATCH] fix(nodered): entrypoint runs as root to fix stale /data state, drops to node-red via su-exec Previous deploy left /data/settings.js as a DIRECTORY (Docker auto-mkdir from a failed bind mount earlier). cp from non-root user then failed 'Permission denied' writing inside it. Entrypoint now: - Detects + rm -rf the stale directory - Seeds /data/settings.js from /usr/src/bf-settings.js - Chowns /data to node-red - exec su-exec node-red:node-red to drop privileges before npm start --- deploy/docker/Dockerfile.nodered | 5 ++++- deploy/docker/nodered-entrypoint.sh | 30 +++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/deploy/docker/Dockerfile.nodered b/deploy/docker/Dockerfile.nodered index 573201a..f7b072b 100644 --- a/deploy/docker/Dockerfile.nodered +++ b/deploy/docker/Dockerfile.nodered @@ -23,7 +23,10 @@ RUN cd /usr/src/betterframe-nodes && \ npm install --omit=dev && \ chown -R node-red:root /usr/src/betterframe-nodes /usr/src/bf-settings.js -USER node-red +# Run entrypoint as root so it can fix stale /data state (e.g. /data/settings.js +# left as a directory by a previous broken bind mount). Entrypoint drops to +# node-red via su-exec before launching the actual server. +USER root ENTRYPOINT ["/usr/local/bin/bf-nodered-entrypoint"] CMD [] diff --git a/deploy/docker/nodered-entrypoint.sh b/deploy/docker/nodered-entrypoint.sh index 9356986..3ff5f27 100755 --- a/deploy/docker/nodered-entrypoint.sh +++ b/deploy/docker/nodered-entrypoint.sh @@ -1,16 +1,30 @@ #!/usr/bin/env sh -# Seed /data/settings.js with our BF defaults on first boot. -# /data is volume-mounted, so the COPY in the Dockerfile gets hidden -# unless we plant a copy after the mount comes up. +# Seed /data/settings.js on first boot. The /data named volume overlays +# anything we COPY into /data during image build, so the file has to be +# planted after the volume mounts. +# +# Runs as root, fixes /data ownership + any stale directories left by +# previous bind-mount attempts, then drops to the node-red user. set -eu DATA=/data TPL=/usr/src/bf-settings.js +TARGET="$DATA/settings.js" -if [ ! -f "$DATA/settings.js" ]; then - echo "[bf-nodered] seeding $DATA/settings.js from $TPL" - cp "$TPL" "$DATA/settings.js" +# Clear stale path if a previous broken bind-mount left a directory where +# we expect a file. +if [ -d "$TARGET" ]; then + echo "[bf-nodered] $TARGET is a directory (stale bind mount?). Removing." + rm -rf "$TARGET" fi -# Exec the upstream nodered entrypoint args verbatim. -exec npm start --cache /data/.npm -- --userDir /data "$@" +if [ ! -f "$TARGET" ]; then + echo "[bf-nodered] seeding $TARGET from $TPL" + cp "$TPL" "$TARGET" +fi + +# Ensure the volume + seeded file are owned by node-red. +chown -R node-red:root "$DATA" 2>/dev/null || true + +# Drop to the node-red user before launching. The base image ships su-exec. +exec su-exec node-red:node-red npm start --cache /data/.npm -- --userDir /data "$@"