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 <noreply@anthropic.com>
This commit is contained in:
2026-03-17 15:22:54 +08:00
parent 8af2f6f3b9
commit 6126f74fb8
2 changed files with 336 additions and 0 deletions

253
SSL-SETUP.md Normal file
View File

@@ -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/)

83
nginx-example.conf Normal file
View File

@@ -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;
}
}