diff --git a/.env.production.example b/.env.production.example index 52fd928..5f98d53 100644 --- a/.env.production.example +++ b/.env.production.example @@ -4,6 +4,7 @@ DJANGO_SETTINGS_MODULE=config.settings DJANGO_SECRET_KEY='replace-with-at-least-50-random-characters' DJANGO_DEBUG=false +DJANGO_USE_HTTPS=true DJANGO_ALLOWED_HOSTS=math.example.com DATABASE_URL='mysql://hulumath:replace-password@127.0.0.1:3307/hulumath' diff --git a/.gitignore b/.gitignore index d9f1b7b..cee49b3 100644 --- a/.gitignore +++ b/.gitignore @@ -130,6 +130,8 @@ celerybeat.pid # Environments .env +.env.production +.env.local .venv .venv-production/ env/ diff --git a/backend/config/settings.py b/backend/config/settings.py index afeea01..8a2caeb 100644 --- a/backend/config/settings.py +++ b/backend/config/settings.py @@ -10,6 +10,10 @@ PROJECT_ROOT = BASE_DIR.parent SECRET_KEY = os.getenv("DJANGO_SECRET_KEY", "dev-only-change-before-production") DEBUG = os.getenv("DJANGO_DEBUG", "true").lower() == "true" +USE_HTTPS = os.getenv( + "DJANGO_USE_HTTPS", + "false" if DEBUG else "true", +).lower() == "true" if not DEBUG and SECRET_KEY == "dev-only-change-before-production": raise ImproperlyConfigured("生产环境必须设置 DJANGO_SECRET_KEY") ALLOWED_HOSTS = [ @@ -175,12 +179,14 @@ CSRF_COOKIE_SAMESITE = "Lax" SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") SECURE_CONTENT_TYPE_NOSNIFF = True X_FRAME_OPTIONS = "DENY" -SECURE_SSL_REDIRECT = not DEBUG -SESSION_COOKIE_SECURE = not DEBUG -CSRF_COOKIE_SECURE = not DEBUG -SECURE_HSTS_SECONDS = int(os.getenv("SECURE_HSTS_SECONDS", "31536000" if not DEBUG else "0")) -SECURE_HSTS_INCLUDE_SUBDOMAINS = not DEBUG -SECURE_HSTS_PRELOAD = not DEBUG +SECURE_SSL_REDIRECT = USE_HTTPS +SESSION_COOKIE_SECURE = USE_HTTPS +CSRF_COOKIE_SECURE = USE_HTTPS +SECURE_HSTS_SECONDS = int( + os.getenv("SECURE_HSTS_SECONDS", "31536000" if USE_HTTPS else "0") +) +SECURE_HSTS_INCLUDE_SUBDOMAINS = USE_HTTPS +SECURE_HSTS_PRELOAD = USE_HTTPS LOGGING = { "version": 1, diff --git a/docs/BAOTA_UBUNTU_FROM_ZERO.md b/docs/BAOTA_UBUNTU_FROM_ZERO.md index 3cbb9e3..ebf91dd 100644 --- a/docs/BAOTA_UBUNTU_FROM_ZERO.md +++ b/docs/BAOTA_UBUNTU_FROM_ZERO.md @@ -252,6 +252,7 @@ nano .env.production DJANGO_SETTINGS_MODULE=config.settings DJANGO_SECRET_KEY='替换为 openssl 生成的密钥' DJANGO_DEBUG=false +DJANGO_USE_HTTPS=true DJANGO_ALLOWED_HOSTS=math.example.com DATABASE_URL='mysql://hulumath:ReplaceWithStrongPassword@127.0.0.1:3307/hulumath' @@ -278,6 +279,20 @@ chown root:root .env.production chmod 600 .env.production ``` +仅使用 IP、尚未配置域名和证书时,可临时改为: + +```dotenv +DJANGO_USE_HTTPS=false +DJANGO_ALLOWED_HOSTS=117.72.28.96,127.0.0.1,localhost +CORS_ALLOWED_ORIGINS=http://117.72.28.96 +CSRF_TRUSTED_ORIGINS=http://117.72.28.96 +SECURE_HSTS_SECONDS=0 +DEPLOY_HEALTH_HOST=117.72.28.96 +``` + +绑定域名并申请 SSL 后,必须把 `DJANGO_USE_HTTPS` 改回 `true`,并将 +Allowed Hosts、CORS、CSRF 和健康检查 Host 全部替换为正式域名。 + ## 9. 在宝塔创建网站 宝塔 `网站` → `添加站点`: diff --git a/scripts/deploy_production.sh b/scripts/deploy_production.sh index dd8847d..71cbb3a 100755 --- a/scripts/deploy_production.sh +++ b/scripts/deploy_production.sh @@ -231,7 +231,12 @@ if [ -d "$PROJECT_DIR/backend/staticfiles" ]; then $SUDO chown -R "$DEPLOY_OWNER" "$PROJECT_DIR/backend/staticfiles" fi cd "$PROJECT_DIR/backend" -"$VENV_DIR/bin/python" manage.py check --deploy --fail-level WARNING --database default +if [ "${DJANGO_USE_HTTPS:-true}" = "true" ]; then + "$VENV_DIR/bin/python" manage.py check --deploy --fail-level WARNING --database default +else + log "临时 HTTP 模式:部署安全检查只阻断 ERROR;绑定域名后应启用 HTTPS" + "$VENV_DIR/bin/python" manage.py check --deploy --fail-level ERROR --database default +fi "$VENV_DIR/bin/python" manage.py check_mysql "$VENV_DIR/bin/python" manage.py migrate --noinput "$VENV_DIR/bin/python" manage.py collectstatic --noinput