From 6126f74fb8e7bd33b42f194cd6ffc29b6fc89811 Mon Sep 17 00:00:00 2001 From: Timmy Date: Tue, 17 Mar 2026 15:22:54 +0800 Subject: [PATCH] docs: add Nginx reverse proxy configuration with SSL guide - Add nginx-example.conf with complete SSL configuration - Add SSL-SETUP.md with step-by-step setup guide - Include Let's Encrypt certbot instructions - Add WebSocket support for real-time collaboration - Include security headers and best practices - Add troubleshooting section Co-Authored-By: Claude Sonnet 4 --- SSL-SETUP.md | 253 +++++++++++++++++++++++++++++++++++++++++++++ nginx-example.conf | 83 +++++++++++++++ 2 files changed, 336 insertions(+) create mode 100644 SSL-SETUP.md create mode 100644 nginx-example.conf diff --git a/SSL-SETUP.md b/SSL-SETUP.md new file mode 100644 index 0000000..2351e38 --- /dev/null +++ b/SSL-SETUP.md @@ -0,0 +1,253 @@ +# Nginx 反向代理 + SSL 設置指南 + +本指南說明如何使用 Nginx 設置反向代理並啟用 SSL (HTTPS)。 + +## 前置需求 + +- 已安裝 Nginx +- 已註冊的域名(例如:hackmd.example.com) +- 域名已指向你的伺服器 IP + +## 快速設置 + +### 步驟 1:安裝 Certbot (Let's Encrypt) + +**Ubuntu/Debian:** +```bash +sudo apt update +sudo apt install certbot python3-certbot-nginx -y +``` + +**CentOS/RHEL:** +```bash +sudo yum install certbot python3-certbot-nginx -y +``` + +**macOS (開發測試):** +```bash +brew install certbot +``` + +### 步驟 2:創建 Nginx 配置文件 + +複製 `nginx-example.conf` 到 Nginx 配置目錄: + +```bash +# 複製配置文件 +sudo cp nginx-example.conf /etc/nginx/sites-available/codimd + +# 編輯配置,替換 your-domain.com 為你的實際域名 +sudo nano /etc/nginx/sites-available/codimd +``` + +修改以下內容: +- `your-domain.com` → 你的實際域名(例如 `hackmd.example.com`) + +### 步驟 3:創建 Certbot 驗證目錄 + +```bash +sudo mkdir -p /var/www/certbot +``` + +### 步驟 4:測試並啟用配置 + +```bash +# 測試配置語法 +sudo nginx -t + +# 啟用站點 +sudo ln -s /etc/nginx/sites-available/codimd /etc/nginx/sites-enabled/ + +# 重新載入 Nginx +sudo systemctl reload nginx +``` + +### 步驟 5:取得 SSL 證書 + +```bash +# 自動取得並配置證書 +sudo certbot --nginx -d your-domain.com + +# 或者先取得證書,手動配置 +sudo certbot certonly --webroot -w /var/www/certbot -d your-domain.com +``` + +Certbot 會自動: +1. 取得免費的 SSL 證書 +2. 配置 Nginx 使用 HTTPS +3. 設置自動續期 + +### 步驟 6:更新 CodiMD 環境變數 + +編輯 `.env` 文件: + +```bash +nano .env +``` + +更新以下變數: + +```env +# 改為你的域名 +CMD_DOMAIN=your-domain.com + +# 啟用 HTTPS +CMD_PROTOCOL_USESSL=true + +# 端口設定 (使用反向代理時設為 false) +CMD_URL_ADDPORT=false +``` + +重啟 CodiMD: + +```bash +docker-compose restart codimd +``` + +### 步驟 7:驗證 SSL 設置 + +訪問你的域名: +- https://your-domain.com + +檢查 SSL 評分:https://www.ssllabs.com/ssltest/ + +## 自動續期 SSL 證書 + +Let's Encrypt 證書有效期为 90 天,需要自動續期。 + +### 設置自動續期 + +**Ubuntu/Debian (systemd timer):** +```bash +sudo certbot renew --dry-run +sudo systemctl status certbot.timer +``` + +**CentOS/RHEL (cron):** +```bash +# 添加 cron job +echo "0 0,12 * * * root certbot renew --quiet" | sudo tee -a /etc/crontab +``` + +**手動續期:** +```bash +sudo certbot renew +sudo systemctl reload nginx +``` + +## 防火牆設定 + +確保開放必要的端口: + +```bash +# UFW (Ubuntu) +sudo ufw allow 80/tcp +sudo ufw allow 443/tcp +sudo ufw enable + +# firewalld (CentOS) +sudo firewall-cmd --permanent --add-service=http +sudo firewall-cmd --permanent --add-service=https +sudo firewall-cmd --reload + +# iptables +sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT +sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT +``` + +## 修改 CodiMD Port 綁定 + +使用反向代理後,建議將 CodiMD 改回只綁定本地: + +修改 `docker-compose.yml`: + +```yaml +ports: + - "127.0.0.1:3000:3000" # 只允許本地存取 +``` + +然後重啟: + +```bash +docker-compose down +docker-compose up -d +``` + +## 故障排除 + +### 證書取得失敗 + +```bash +# 檢查域名 DNS 是否正確指向伺服器 +nslookup your-domain.com + +# 檢查 80 port 是否開放 +sudo netstat -tlnp | grep :80 + +# 查看 Certbot 日誌 +sudo cat /var/log/letsencrypt/letsencrypt.log +``` + +### WebSocket 連線失敗 + +確認 Nginx 配置包含以下設定: + +```nginx +proxy_set_header Upgrade $http_upgrade; +proxy_set_header Connection "upgrade"; +proxy_http_version 1.1; +``` + +### 混合內容警告 + +確保 CodiMD 環境變數設定正確: + +```env +CMD_DOMAIN=your-domain.com +CMD_PROTOCOL_USESSL=true +``` + +## 進階配置 + +### 強制 HTTPS 重定向 + +```nginx +# 在 HTTP server block 添加 +if ($host != your-domain.com) { + return 301 https://$host$request_uri; +} +``` + +### 限制上傳大小 + +```nginx +# 在 server block 添加 +client_max_body_size 100M; +``` + +### 啟用壓縮 + +```nginx +# 在 http block 或 server block 添加 +gzip on; +gzip_vary on; +gzip_min_length 1024; +gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json; +``` + +## 安全檢查清單 + +- [ ] SSL 證書已正確安裝 +- [ ] HTTP 自動重定向到 HTTPS +- [ ] WebSocket 連線正常 +- [ ] CodiMD 環境變數已更新 +- [ ] 防火牆規則已設置 +- [ ] 自動續期已啟用 +- [ ] SSL 測試獲得 A 或 A+ 評分 + +## 相關連結 + +- [Let's Encrypt 官方文件](https://letsencrypt.org/docs/) +- [Nginx SSL 配置指南](https://nginx.org/en/docs/http/configuring_https_servers.html) +- [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) +- [SSL Labs 測試工具](https://www.ssllabs.com/ssltest/) diff --git a/nginx-example.conf b/nginx-example.conf new file mode 100644 index 0000000..f7a7a43 --- /dev/null +++ b/nginx-example.conf @@ -0,0 +1,83 @@ +# Nginx 反向代理配置範例 (含 SSL) +# 放置位置:/etc/nginx/sites-available/codimd + +# HTTP - 自動重定向到 HTTPS +server { + listen 80; + listen [::]:80; + server_name your-domain.com; + + # Let's Encrypt 驗證目錄 + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + # 其他 HTTP 流量重定向到 HTTPS + location / { + return 301 https://$server_name$request_uri; + } +} + +# HTTPS - 主要服務 +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name your-domain.com; + + # SSL 證書配置 (Let's Encrypt) + ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; + + # SSL 安全配置 + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384'; + ssl_prefer_server_ciphers off; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_session_tickets off; + + # HSTS (HTTP Strict Transport Security) + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; + + # 其他安全標頭 + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + + # 用戶端上傳大小限制 + client_max_body_size 50M; + + # 反向代理到 CodiMD + location / { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + + # WebSocket 支援 (CodiMD 即時協作需要) + 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_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + + # 超時設定 + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + + # 緩衝設定 + proxy_buffering off; + proxy_request_buffering off; + } + + # 健康檢查端點 (可選) + location /health { + access_log off; + proxy_pass http://127.0.0.1:3000; + } +}