14 Commits
Author SHA1 Message Date
Jacky 27242aed5e fix: trust system CA in production smoke test (#46) 2026-09-29 01:50:03 +08:00
Jacky e200d850f9 fix: trust system CA in production smoke test
CI / test (pull_request) Successful in 6m38s
PR合并自动部署 / release-check (pull_request) Successful in 3s
PR合并自动部署 / deploy (pull_request) Successful in 19s
2026-09-29 01:41:35 +08:00
Jacky c90858f45c fix: smoke test Hulumath over public TLS (#45) 2026-09-29 01:39:55 +08:00
Jacky 92c456c7d1 fix: smoke test Hulumath over public TLS
CI / test (pull_request) Successful in 6m7s
PR合并自动部署 / release-check (pull_request) Successful in 3s
PR合并自动部署 / deploy (pull_request) Failing after 19s
2026-09-29 01:29:55 +08:00
Jacky 9a5ce6e4af Merge pull request 'fix: decouple edge HSTS from backend health' (#44) from fix/edge-hsts-header-probe into main 2026-09-29 01:13:59 +08:00
Jacky 8825f6c639 fix: decouple edge HSTS from backend health
CI / test (pull_request) Successful in 6m47s
PR合并自动部署 / release-check (pull_request) Successful in 4s
PR合并自动部署 / deploy (pull_request) Failing after 21s
2026-09-29 01:05:24 +08:00
Jacky d87edf0530 Merge pull request 'fix: use certificate host for deployment health checks' (#43) from fix/deploy-health-host into main 2026-09-29 01:00:40 +08:00
Jacky c89b82c6f4 fix: use certificate host for deployment health checks
CI / test (pull_request) Successful in 6m43s
PR合并自动部署 / release-check (pull_request) Successful in 3s
PR合并自动部署 / deploy (pull_request) Failing after 11s
2026-09-29 00:51:01 +08:00
Jacky f7536d3a3f Merge pull request 'fix: verify edge-owned HSTS during deployment' (#42) from fix/edge-hsts-deploy-check into main 2026-09-29 00:47:49 +08:00
Jacky 6d8ed567b0 fix: verify edge-owned HSTS during deployment
CI / test (pull_request) Successful in 6m38s
PR合并自动部署 / release-check (pull_request) Successful in 3s
PR合并自动部署 / deploy (pull_request) Failing after 11s
2026-09-29 00:40:00 +08:00
Jacky 136db1d47e Merge pull request 'fix: use HTTPS for production repository fetches' (#41) from fix/deploy-https-remote into main 2026-09-29 00:35:40 +08:00
Jacky c609cd0d02 fix: use HTTPS for production repository fetches
CI / test (pull_request) Successful in 6m42s
PR合并自动部署 / release-check (pull_request) Successful in 3s
PR合并自动部署 / deploy (pull_request) Failing after 13s
2026-09-29 00:27:54 +08:00
Jacky 848db95623 Merge pull request 'ci: authenticate production checkout' (#40) from fix/deploy-authenticated-checkout into main 2026-09-29 00:25:20 +08:00
Jacky 3d61deefd3 ci: authenticate production checkout
CI / test (pull_request) Successful in 6m54s
PR合并自动部署 / release-check (pull_request) Successful in 3s
PR合并自动部署 / deploy (pull_request) Failing after 3s
2026-09-29 00:16:33 +08:00
7 changed files with 63 additions and 15 deletions
+2
View File
@@ -17,6 +17,8 @@ API_ANON_RATE=120/minute
API_USER_RATE=600/minute
CALCULATOR_RATE=30/minute
SECURE_HSTS_SECONDS=31536000
# Set true only when the HTTPS reverse proxy emits a non-zero HSTS max-age.
DJANGO_HSTS_AT_EDGE=false
# 仅供部署脚本直接访问 127.0.0.1:8000 时设置 Host 头。
DEPLOY_HEALTH_HOST=math.example.com
+15 -10
View File
@@ -19,8 +19,14 @@ jobs:
steps:
- name: 检出 main
env:
REPOSITORY_URL: http://117.72.28.96:8765/Jacky/Hulumath-Web.git
run: git clone --branch main --single-branch "$REPOSITORY_URL" .
CHECKOUT_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
git init .
git remote add origin "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
git -c http.extraHeader="Authorization: token ${CHECKOUT_TOKEN}" \
fetch --depth=1 origin main
git checkout --detach FETCH_HEAD
- name: 检查发布文件和脚本语法
run: |
@@ -63,7 +69,7 @@ jobs:
set -Eeuo pipefail
PROJECT="/www/wwwroot/Hulumath-Web"
REPOSITORY_URL="http://117.72.28.96:8765/Jacky/Hulumath-Web.git"
REPOSITORY_URL="https://git.jacky0987.xyz/Jacky/Hulumath-Web.git"
PYTHON_BIN="/www/server/pyporject_evn/versions/3.12.13/bin/python3"
exec 9>/tmp/hulumath-production-deploy.lock
@@ -94,11 +100,14 @@ jobs:
chmod +x scripts/deploy_production.sh
SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt \
DJANGO_HSTS_AT_EDGE=true \
PROJECT_DIR="$PROJECT" \
PYTHON_BIN="$PYTHON_BIN" \
PREVIOUS_REVISION="$PREVIOUS_REVISION" \
DEPLOY_SMOKE_BASE_URL="http://127.0.0.1:4321" \
DEPLOY_SMOKE_WS_URL="ws://127.0.0.1:4321/ws/health/" \
DEPLOY_HEALTH_HOST="math.jacky0987.xyz" \
DEPLOY_SMOKE_BASE_URL="https://math.jacky0987.xyz" \
DEPLOY_SMOKE_WS_URL="wss://math.jacky0987.xyz/ws/health/" \
bash scripts/deploy_production.sh
echo "========================================"
@@ -108,13 +117,9 @@ jobs:
EOF
- name: 从 Runner 验证 Nginx 健康状态
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_PUBLIC_HOST: 117.72.28.96
run: |
curl --fail --silent --show-error \
--retry 5 \
--retry-delay 2 \
--header "Host: $DEPLOY_PUBLIC_HOST" \
"http://$DEPLOY_HOST:4321/health/" \
"https://math.jacky0987.xyz/health/" \
| grep -q '"status": "ok"'
@@ -0,0 +1,25 @@
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
def test_edge_hsts_ownership_is_explicit_and_verified():
settings = (ROOT / "backend/config/settings.py").read_text(encoding="utf-8")
deploy = (ROOT / "scripts/deploy_production.sh").read_text(encoding="utf-8")
workflow = (ROOT / ".gitea/workflows/deploy.yml").read_text(encoding="utf-8")
example = (ROOT / ".env.production.example").read_text(encoding="utf-8")
assert 'os.getenv("DJANGO_HSTS_AT_EDGE", "false")' in settings
assert '["security.W004"]' in settings
assert "DJANGO_HSTS_AT_EDGE=true" in workflow
assert "SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt" in workflow
assert 'DEPLOY_HEALTH_HOST="math.jacky0987.xyz"' in workflow
assert 'DEPLOY_SMOKE_BASE_URL="https://math.jacky0987.xyz"' in workflow
assert 'DEPLOY_SMOKE_WS_URL="wss://math.jacky0987.xyz/ws/health/"' in workflow
assert '"https://math.jacky0987.xyz/health/"' in workflow
assert "127.0.0.1:4321" not in workflow
assert "curl --silent --show-error --head" in deploy
assert "curl --fail --silent --show-error --head" not in deploy
assert "strict-transport-security:.*max-age=[1-9][0-9]*" in deploy
assert "unverified" not in deploy.lower()
assert "DJANGO_HSTS_AT_EDGE=false" in example
+6
View File
@@ -189,6 +189,12 @@ SECURE_HSTS_SECONDS = int(
)
SECURE_HSTS_INCLUDE_SUBDOMAINS = USE_HTTPS
SECURE_HSTS_PRELOAD = USE_HTTPS
HSTS_AT_EDGE = os.getenv("DJANGO_HSTS_AT_EDGE", "false").lower() == "true"
SILENCED_SYSTEM_CHECKS = (
["security.W004"]
if USE_HTTPS and HSTS_AT_EDGE and SECURE_HSTS_SECONDS == 0
else []
)
LOGGING = {
"version": 1,
+3 -3
View File
@@ -24,7 +24,7 @@ systemd: Gunicorn + UvicornWorker
约定:
- Ubuntu 22.04 或 24.04。
- Gitea 仓库:`http://117.72.28.96:8765/Jacky/Hulumath-Web.git`。
- Gitea 仓库:`https://git.jacky0987.xyz/Jacky/Hulumath-Web.git`。
- 项目目录:`/www/wwwroot/Hulumath-Web`。
- 应用监听:`127.0.0.1:8000`。
- MySQL 8 宿主机端口:`3307`。
@@ -206,7 +206,7 @@ mysql -h 127.0.0.1 -P 3307 \
```bash
git ls-remote \
http://117.72.28.96:8765/Jacky/Hulumath-Web.git \
https://git.jacky0987.xyz/Jacky/Hulumath-Web.git \
refs/heads/main
```
@@ -223,7 +223,7 @@ if [ -d Hulumath-Web ]; then
fi
git clone \
http://117.72.28.96:8765/Jacky/Hulumath-Web.git \
https://git.jacky0987.xyz/Jacky/Hulumath-Web.git \
Hulumath-Web
cd Hulumath-Web
git checkout main
+2 -2
View File
@@ -51,7 +51,7 @@ PR 质量门禁由 `.gitea/workflows/ci.yml` 执行:
自动部署前,服务器必须满足:
- Gitea 仓库为 `http://117.72.28.96:8765/Jacky/Hulumath-Web.git`。
- Gitea 仓库为 `https://git.jacky0987.xyz/Jacky/Hulumath-Web.git`。
- 项目目录为 `/www/wwwroot/Hulumath-Web`。
- Python 位于 `/www/server/pyporject_evn/versions/3.12.13/bin/python3` 或同目录 `python`。
- 已安装 MySQL 8 客户端命令 `mysqldump`。
@@ -76,7 +76,7 @@ chmod 600 .env.production
```bash
cd /www/wwwroot/Hulumath-Web
git remote set-url origin http://117.72.28.96:8765/Jacky/Hulumath-Web.git
git remote set-url origin https://git.jacky0987.xyz/Jacky/Hulumath-Web.git
git fetch origin main
PREVIOUS_REVISION="$(git rev-parse HEAD)"
git reset --hard origin/main
+10
View File
@@ -234,6 +234,16 @@ if [ -d "$PROJECT_DIR/backend/staticfiles" ]; then
fi
cd "$PROJECT_DIR/backend"
if [ "${DJANGO_USE_HTTPS:-true}" = "true" ]; then
if [ "${DJANGO_HSTS_AT_EDGE:-false}" = "true" ]; then
curl --silent --show-error --head \
--noproxy '*' \
--resolve "${HEALTH_HOST}:443:127.0.0.1" \
--max-time 10 \
"https://${HEALTH_HOST}/" |
tr -d '\r' |
grep -Eiq '^strict-transport-security:.*max-age=[1-9][0-9]*'
log "边缘代理 HSTS 已验证"
fi
"$VENV_DIR/bin/python" manage.py check --deploy --fail-level WARNING --database default
else
log "临时 HTTP 模式:部署安全检查只阻断 ERROR;绑定域名后应启用 HTTPS"