fix: write the generated secret key to DATA_DIR

start.sh cd's to its own directory, so the generated .webui_secret_key lands in
an image layer instead of the mounted volume. It is therefore lost on every
container recreate, signing all users out, and the directory is not writable
when the container does not run as root, which aborts the boot outright:

    start.sh: line 46: .webui_secret_key: Permission denied

Resolve to WEBUI_SECRET_KEY_FILE, then an existing ./.webui_secret_key, then
DATA_DIR. Regeneration triggers on missing or empty rather than absent, since an
empty key now persists; an unreadable one is left alone, as it may belong to
another UID and also encrypts OAuth sessions and valves.

Closes #26662

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sebastian Danielsson 2026-08-21 00:30:27 +02:00
parent 8a42aa53e8
commit 72f210c0e1
No known key found for this signature in database
2 changed files with 20 additions and 3 deletions

View file

@ -18,3 +18,4 @@ uploads
**/*.db
_test
backend/data/*
backend/.webui_secret_key

View file

@ -29,7 +29,16 @@ fi
# ── Secret key setup ─────────────────────────────────────────────────────────
KEY_FILE="${WEBUI_SECRET_KEY_FILE:-.webui_secret_key}"
# The script cd's to its own directory, which lives in the image: a key written
# there is lost on every container recreate and is not writable when the
# container does not run as root. Fall back to DATA_DIR instead.
if [[ -n "${WEBUI_SECRET_KEY_FILE:-}" ]]; then
KEY_FILE="$WEBUI_SECRET_KEY_FILE"
elif [[ -f .webui_secret_key && -s .webui_secret_key ]]; then
KEY_FILE=".webui_secret_key"
else
KEY_FILE="${DATA_DIR:-./data}/.webui_secret_key"
fi
WEBUI_SECRET_KEY_LENGTH="${WEBUI_SECRET_KEY_LENGTH:-24}"
PORT="${PORT:-8080}"
HOST="${HOST:-0.0.0.0}"
@ -37,13 +46,20 @@ HOST="${HOST:-0.0.0.0}"
if [[ -z "${WEBUI_SECRET_KEY:-}" && -z "${WEBUI_JWT_SECRET_KEY:-}" ]]; then
echo "No WEBUI_SECRET_KEY environment variable set, loading from file."
if [[ ! -f "$KEY_FILE" ]]; then
# Regenerate when missing or empty, never when merely unreadable: such a key may
# belong to another UID, and it also encrypts OAuth sessions and valves.
if [[ ! -s "$KEY_FILE" ]]; then
echo "Generating new WEBUI_SECRET_KEY..."
if ! [[ "$WEBUI_SECRET_KEY_LENGTH" =~ ^[1-9][0-9]*$ ]]; then
echo "WEBUI_SECRET_KEY_LENGTH must be a positive integer." >&2
exit 1
fi
head -c "$WEBUI_SECRET_KEY_LENGTH" /dev/random | base64 > "$KEY_FILE"
# 0640/0750: a volume remounted under a different arbitrary UID keeps group 0.
(
umask 027
mkdir -p -- "$(dirname -- "$KEY_FILE")"
head -c "$WEBUI_SECRET_KEY_LENGTH" /dev/random | base64 > "$KEY_FILE"
)
fi
echo "Loading WEBUI_SECRET_KEY from ${KEY_FILE}"