From 4f11addcfd6657e7e63eed0570b1d4d9bca75698 Mon Sep 17 00:00:00 2001 From: Markos Gogoulos Date: Mon, 11 May 2026 15:25:23 +0300 Subject: [PATCH] fix: better place secret key settings --- .gitignore | 1 + cms/settings.py | 38 +++++++++++++------------------------ cms/version.py | 2 +- deploy/docker/entrypoint.sh | 25 ++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index 1ec2398e..15f9193b 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ static/chapters_editor/videos/sample-video.mp3 static/video_editor/videos/sample-video.mp3 templates/todo-MS4.md .secret_key +.secret_key.lock diff --git a/cms/settings.py b/cms/settings.py index 1e32df32..bda55ef0 100644 --- a/cms/settings.py +++ b/cms/settings.py @@ -1,7 +1,6 @@ import os from celery.schedules import crontab -from django.core.management.utils import get_random_secret_key from django.utils.translation import gettext_lazy as _ DEBUG = False @@ -172,30 +171,19 @@ REST_FRAMEWORK = { } -# Set the SECRET_KEY env var in production. If unset, a fresh random key is -# generated or read from a .secret_key file to ensure all workers share the same key. -def get_secret_key(): - key = os.getenv('SECRET_KEY') - if key: - return key - - base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - secret_path = os.path.join(base_dir, '.secret_key') - - if os.path.exists(secret_path): - with open(secret_path) as f: - return f.read().strip() - - key = get_random_secret_key() - try: - with open(secret_path, 'w') as f: - f.write(key) - except Exception: - pass - return key - - -SECRET_KEY = get_secret_key() +# In docker, deploy/docker/entrypoint.sh ensures the SECRET_KEY env var is +# set (generating .secret_key once on first start if needed). Outside docker, +# either set SECRET_KEY in the environment or create a .secret_key file at the +# project root, e.g.: +# python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())' > .secret_key +SECRET_KEY = os.getenv('SECRET_KEY') +if not SECRET_KEY: + _secret_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.secret_key') + if os.path.exists(_secret_path): + with open(_secret_path) as _f: + SECRET_KEY = _f.read().strip() +if not SECRET_KEY: + raise RuntimeError("SECRET_KEY is not set. Set the SECRET_KEY env var or create a .secret_key file at the project root.") TEMP_DIRECTORY = "/tmp" # Don't use a temp directory inside BASE_DIR!!! BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) diff --git a/cms/version.py b/cms/version.py index 509281d4..f3bb0ca5 100644 --- a/cms/version.py +++ b/cms/version.py @@ -1 +1 @@ -VERSION = "8.0.4" +VERSION = "8.0.6" diff --git a/deploy/docker/entrypoint.sh b/deploy/docker/entrypoint.sh index 4e80e4c4..0c25f050 100755 --- a/deploy/docker/entrypoint.sh +++ b/deploy/docker/entrypoint.sh @@ -35,4 +35,29 @@ find /home/mediacms.io/mediacms ! \( -path "*.git*" -o -name "package-lock.json" chmod +x /home/mediacms.io/mediacms/deploy/docker/start.sh /home/mediacms.io/mediacms/deploy/docker/prestart.sh +# Generate or read SECRET_KEY once, shared across all containers via the +# host-mounted project volume. Atomic create-or-read so parallel container +# starts (web + celery_worker + celery_beat + migrations) can't race. +# Uses `mkdir` as the lock primitive (POSIX-atomic, no dependency on flock). +SECRET_KEY_FILE="${SECRET_KEY_FILE:-/home/mediacms.io/mediacms/.secret_key}" +SECRET_KEY_LOCK="${SECRET_KEY_FILE}.lock" + +if [ -z "${SECRET_KEY:-}" ]; then + if [ ! -s "$SECRET_KEY_FILE" ]; then + # Spin-acquire the lock. mkdir is atomic; first caller wins, others retry. + while ! mkdir "$SECRET_KEY_LOCK" 2>/dev/null; do + sleep 0.2 + done + # Re-check inside the lock: another container may have just written it. + if [ ! -s "$SECRET_KEY_FILE" ]; then + python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())' > "$SECRET_KEY_FILE" + chown www-data:www-data "$SECRET_KEY_FILE" + chmod 600 "$SECRET_KEY_FILE" + echo "entrypoint.sh: generated new SECRET_KEY at $SECRET_KEY_FILE" + fi + rmdir "$SECRET_KEY_LOCK" + fi + export SECRET_KEY="$(cat "$SECRET_KEY_FILE")" +fi + exec "$@"