feat(deploy): auto-configure system nginx HTTPS on ssl obtain

- Add configure_system_nginx_ssl() function to generate nginx HTTPS config
- HTTP 80 redirects to HTTPS, HTTPS 443 proxies to Docker nginx 8080
- Include TLS 1.2/1.3, secure ciphers, HSTS headers
- Update renew_ssl_cert() to reload both system and Docker nginx
- Update auto-renew cron to reload system nginx

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-25 06:36:48 -08:00
parent 50481efa49
commit 17e887653a
1 changed files with 98 additions and 5 deletions

103
deploy.sh
View File

@ -1150,7 +1150,8 @@ obtain_ssl_cert() {
# 创建证书目录
mkdir -p "$PROJECT_ROOT/nginx/ssl"
# 停止 Nginx (释放 80 端口)
# 停止系统 Nginx 和 Docker Nginx (释放 80 端口)
systemctl stop nginx 2>/dev/null || true
$DOCKER_COMPOSE stop nginx 2>/dev/null || true
# 使用 standalone 模式申请证书
@ -1176,12 +1177,103 @@ obtain_ssl_cert() {
return 1
fi
# 重启 Nginx
# 配置系统 nginx HTTPS
configure_system_nginx_ssl "$domain"
# 重启 Docker Nginx
$DOCKER_COMPOSE up -d nginx
log_success "SSL 证书配置完成"
}
# 配置系统 nginx 启用 HTTPS
configure_system_nginx_ssl() {
local domain=${1:-$DOMAIN}
local nginx_conf="/etc/nginx/sites-available/iconsulting.conf"
log_step "配置系统 nginx HTTPS..."
# 备份原配置
cp "$nginx_conf" "${nginx_conf}.bak" 2>/dev/null || true
# 生成新的 nginx 配置 (HTTP + HTTPS)
cat > "$nginx_conf" << EOF
# iConsulting Nginx 配置 (HTTP 重定向 + HTTPS)
# 自动生成于 $(date)
# HTTP - 重定向到 HTTPS
server {
listen 80;
listen [::]:80;
server_name $domain;
# Let's Encrypt 验证
location /.well-known/acme-challenge/ {
root /var/www/html;
}
# 其他请求重定向到 HTTPS
location / {
return 301 https://\$host\$request_uri;
}
}
# HTTPS
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name $domain;
# SSL 证书
ssl_certificate /etc/letsencrypt/live/$domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$domain/privkey.pem;
# SSL 安全配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 安全头
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
# 代理到 Docker nginx (端口 8080)
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
EOF
# 确保 sites-enabled 链接存在
ln -sf "$nginx_conf" /etc/nginx/sites-enabled/iconsulting.conf
# 测试配置
if nginx -t; then
systemctl start nginx
systemctl reload nginx
log_success "系统 nginx HTTPS 配置完成"
else
log_error "nginx 配置测试失败,恢复备份"
cp "${nginx_conf}.bak" "$nginx_conf" 2>/dev/null || true
systemctl start nginx
return 1
fi
}
# 续期 SSL 证书
renew_ssl_cert() {
log_step "续期 SSL 证书..."
@ -1193,8 +1285,9 @@ renew_ssl_cert() {
cp "/etc/letsencrypt/live/$DOMAIN/fullchain.pem" "$PROJECT_ROOT/nginx/ssl/"
cp "/etc/letsencrypt/live/$DOMAIN/privkey.pem" "$PROJECT_ROOT/nginx/ssl/"
# 重载 Nginx
$DOCKER_COMPOSE exec nginx nginx -s reload
# 重载系统 Nginx 和 Docker Nginx
systemctl reload nginx 2>/dev/null || true
$DOCKER_COMPOSE exec nginx nginx -s reload 2>/dev/null || true
log_success "SSL 证书续期完成"
fi
}
@ -1206,7 +1299,7 @@ setup_ssl_auto_renew() {
# 创建续期脚本
cat > /etc/cron.d/certbot-renew << EOF
# 每天凌晨 3 点检查证书续期
0 3 * * * root certbot renew --quiet && cp /etc/letsencrypt/live/$DOMAIN/*.pem $PROJECT_ROOT/nginx/ssl/ && docker-compose -f $PROJECT_ROOT/docker-compose.yml exec -T nginx nginx -s reload
0 3 * * * root certbot renew --quiet && cp /etc/letsencrypt/live/$DOMAIN/*.pem $PROJECT_ROOT/nginx/ssl/ && systemctl reload nginx && docker-compose -f $PROJECT_ROOT/docker-compose.yml exec -T nginx nginx -s reload
EOF
log_success "自动续期已配置 (每天 3:00 检查)"