Nginx 网站维护页配置完全指南 🛠️

📖 目录导航
✨ 维护页功能简介
网站维护页面是在服务器维护、升级或出现故障时向用户展示的友好界面,具有以下优势:
- 🚧 友好提示:告知用户网站正在维护中,提升用户体验
- ⏰ 预计时间:提供维护完成的大致时间,管理用户预期
- 📞 联系方式:提供技术支持联系方式,方便用户咨询
- 🎨 品牌展示:保持品牌一致性,即使在维护期间
- 🔧 快速部署:简单配置即可启用,无需修改应用代码
- 📱 响应式设计:适配各种设备屏幕尺寸
- 🌐 多语言支持:支持多种语言,满足国际化需求
🚀 一、创建维护页面目录和文件
1️⃣ 创建 HTML 目录结构
1 2 3 4 5 6 7 8 9 10 11 12 13
| sudo mkdir -p /var/www/html
sudo mkdir -p /var/www/html/errors
sudo chown -R www-data:www-data /var/www/html sudo chmod -R 755 /var/www/html
sudo mkdir -p /var/log/nginx sudo chown -R www-data:www-data /var/log/nginx
|
2️⃣ 创建标准错误页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
| sudo tee /var/www/html/40x.html > /dev/null <<'EOF' <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>400 Bad Request - 请求错误</title> <style> body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: linear-gradient(135deg, height: 100vh; display: flex; justify-content: center; align-items: center; color: white; text-align: center; margin: 0; padding: 20px; } .container { background: rgba(255, 255, 255, 0.1); padding: 3rem; border-radius: 15px; backdrop-filter: blur(10px); max-width: 600px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); } h1 { font-size: 4rem; margin: 0; color: } h2 { margin-top: 0; font-weight: 300; } p { line-height: 1.6; margin-bottom: 2rem; } .btn { display: inline-block; padding: 12px 24px; background: color: white; text-decoration: none; border-radius: 25px; transition: all 0.3s ease; margin: 0 10px 10px 0; } .btn:hover { background: transform: translateY(-2px); } @media (max-width: 600px) { .container { padding: 2rem; } h1 { font-size: 3rem; } .btn { display: block; margin: 10px 0; } } </style> </head> <body> <div class="container"> <h1>400</h1> <h2>糟糕!请求错误</h2> <p>服务器无法理解您的请求,可能是语法格式不正确。</p> <p>请检查您的输入或稍后再试。</p> <a href="/" class="btn">返回首页</a> <a href="mailto:support@example.com" class="btn">联系支持</a> <a href="javascript:location.reload()" class="btn">刷新页面</a> </div> </body> </html> EOF
sudo tee /var/www/html/50x.html > /dev/null <<'EOF' <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>503 Service Unavailable - 服务维护中</title> <style> body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: linear-gradient(135deg, height: 100vh; display: flex; justify-content: center; align-items: center; color: white; text-align: center; margin: 0; padding: 20px; } .container { background: rgba(255, 255, 255, 0.1); padding: 3rem; border-radius: 15px; backdrop-filter: blur(10px); max-width: 600px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); } h1 { font-size: 4rem; margin: 0; color: } h2 { margin-top: 0; font-weight: 300; } p { line-height: 1.6; margin-bottom: 2rem; } .progress { background: rgba(255, 255, 255, 0.2); height: 10px; border-radius: 5px; overflow: hidden; margin: 2rem 0; } .progress-bar { height: 100%; width: 75%; background: border-radius: 5px; animation: progress 2s ease-in-out infinite; } @keyframes progress { 0% { width: 75%; } 50% { width: 85%; } 100% { width: 75%; } } .btn { display: inline-block; padding: 12px 24px; background: color: white; text-decoration: none; border-radius: 25px; transition: all 0.3s ease; margin: 0 10px 10px 0; } .btn:hover { background: transform: translateY(-2px); } @media (max-width: 600px) { .container { padding: 2rem; } h1 { font-size: 3rem; } .btn { display: block; margin: 10px 0; } } </style> </head> <body> <div class="container"> <h1>503</h1> <h2>网站维护中</h2> <p>我们正在对网站进行维护升级,以提供更好的服务体验。</p> <div class="progress"> <div class="progress-bar"></div> </div> <p>预计完成时间: 今天 18:00</p> <a href="javascript:location.reload()" class="btn">刷新页面</a> <a href="mailto:support@example.com" class="btn">联系支持</a> <a href="/status" class="btn">查看状态页</a> </div> </body> </html> EOF
|
⚙️ 二、配置 Nginx 错误页面
1️⃣ 迅雷服务反向代理配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
| sudo tee /etc/nginx/conf.d/xunlei.conf > /dev/null <<'EOF' server { listen 5553 ssl http2; listen [::]:5553 ssl http2;
server_name xunlei.mobufan.eu.org;
ssl_certificate /etc/nginx/keyfile/cert.pem; ssl_certificate_key /etc/nginx/keyfile/key.pem; 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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_session_tickets off; charset utf-8;
root /var/www/html; autoindex off;
access_log /var/log/nginx/xunlei.access.log; error_log /var/log/nginx/xunlei.error.log;
location / { proxy_pass http://10.10.10.245:2345; 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 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 16k; proxy_busy_buffers_size 24k; proxy_cache off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
error_page 400 401 402 403 404 /40x.html; error_page 500 502 503 504 /50x.html; location = /40x.html { root /var/www/html; internal; access_log off; log_not_found off; } location = /50x.html { root /var/www/html; internal; access_log off; log_not_found off; } location /nginx-health { access_log off; return 200 "healthy\n"; add_header Content-Type text/plain; } add_header X-Frame-Options DENY always; add_header X-Content-Type-Options nosniff always; add_header X-XSS-Protection "1; mode=block" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; location ~ /\. { deny all; access_log off; log_not_found off; } location ~* (\.env|composer\.json|composer\.lock|package\.json|package-lock\.json|\.git|\.svn|\.htaccess) { deny all; access_log off; log_not_found off; } location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ { expires 30d; add_header Cache-Control "public, immutable"; add_header Access-Control-Allow-Origin "*"; access_log off; log_not_found off; } } EOF
|
2️⃣ 重启 Nginx 服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| sudo nginx -t
sudo systemctl restart nginx
sudo systemctl status nginx
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.log
|
🎨 三、高级维护页面配置
1️⃣ 多语言维护页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| sudo tee /var/www/html/maintenance-en.html > /dev/null <<'EOF' <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Maintenance Mode</title> <style> body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: linear-gradient(135deg, height: 100vh; display: flex; justify-content: center; align-items: center; color: white; text-align: center; margin: 0; padding: 20px; } .container { background: rgba(255, 255, 255, 0.1); padding: 3rem; border-radius: 15px; backdrop-filter: blur(10px); max-width: 600px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); } h1 { font-size: 4rem; margin: 0; color: } p { line-height: 1.6; margin-bottom: 2rem; } .btn { display: inline-block; padding: 12px 24px; background: color: white; text-decoration: none; border-radius: 25px; transition: all 0.3s ease; margin: 0 10px 10px 0; } .btn:hover { background: transform: translateY(-2px); } @media (max-width: 600px) { .container { padding: 2rem; } h1 { font-size: 3rem; } .btn { display: block; margin: 10px 0; } } </style> </head> <body> <div class="container"> <h1>503</h1> <p>We're currently performing maintenance. Please check back later.</p> <p>Estimated completion time: Today 18:00 (UTC+8)</p> <a href="javascript:location.reload()" class="btn">Refresh Page</a> <a href="mailto:support@example.com" class="btn">Contact Support</a> <a href="/status" class="btn">Status Page</a> </div> </body> </html> EOF
|
2️⃣ 定时维护页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| sudo tee /usr/local/bin/maintenance-mode.sh > /dev/null <<'EOF'
MAINTENANCE_CONF="/etc/nginx/snippets/maintenance.conf" MAINTENANCE_FLAG="/tmp/nginx-maintenance.flag"
case "$1" in on) echo "Enabling maintenance mode..." sudo tee $MAINTENANCE_CONF > /dev/null <<'MAINT' error_page 503 @maintenance; location @maintenance { rewrite ^(.*)$ /50x.html break; } return 503; MAINT touch $MAINTENANCE_FLAG sudo systemctl reload nginx echo "Maintenance mode enabled" ;; off) echo "Disabling maintenance mode..." rm -f $MAINTENANCE_CONF $MAINTENANCE_FLAG sudo systemctl reload nginx echo "Maintenance mode disabled" ;; status) if [ -f $MAINTENANCE_FLAG ]; then echo "Maintenance mode is ON" else echo "Maintenance mode is OFF" fi ;; *) echo "Usage: $0 {on|off|status}" exit 1 ;; esac EOF
sudo chmod +x /usr/local/bin/maintenance-mode.sh
sudo mkdir -p /etc/nginx/snippets
sudo /usr/local/bin/maintenance-mode.sh status
|
3️⃣ 基于 IP 的维护模式例外
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| sudo tee /etc/nginx/snippets/maintenance-whitelist.conf > /dev/null <<'EOF'
geo $maintenance_whitelist { default 0; 192.168.1.100 1; 10.0.0.50 1; }
map $maintenance_whitelist $maintenance_pass { 0 $maintenance_mode; 1 0; } EOF
|
🔧 四、Nginx 维护命令
1️⃣ 常用维护命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| sudo nginx -t
sudo systemctl reload nginx
sudo systemctl restart nginx
sudo systemctl status nginx
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.log
ps aux | grep nginx
sudo netstat -tulnp | grep nginx
|
2️⃣ 性能监控命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| sudo tail -f /var/log/nginx/access.log | awk '{print $1, $4, $7, $9}'
sudo tail -f /var/log/nginx/error.log
sudo netstat -an | grep :5553 | awk '{print $6}' | sort | uniq -c
sudo ngxtop
sudo nginx -T
sudo systemctl status nginx --no-pager -l
|
🛡️ 五、安全加固配置
1️⃣ 增强安全配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| sudo tee /etc/nginx/snippets/security.conf > /dev/null <<'EOF'
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Frame-Options DENY always; add_header X-Content-Type-Options nosniff always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin" always; add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
server_tokens off;
if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 405; }
client_max_body_size 10m; client_body_buffer_size 128k;
client_body_timeout 30s; client_header_timeout 30s; keepalive_timeout 65s; send_timeout 30s;
limit_conn_zone $binary_remote_addr zone=addr:10m; limit_conn addr 10;
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s; limit_req zone=one burst=20 nodelay; EOF
|
2️⃣ 防火墙配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| sudo ufw enable
sudo ufw allow 22/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw allow 5553/tcp
sudo ufw status verbose
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw limit ssh
|
3️⃣ SSL 安全强化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| sudo tee /etc/nginx/snippets/ssl-params.conf > /dev/null <<'EOF'
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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_ecdh_curve secp384r1; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_session_tickets off; ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; EOF
|
📊 总结
通过本指南,你已经成功配置了 Nginx 网站维护页面和相关设置:
- ✅ 创建维护页面:设计了美观的 40x 和 50x 错误页面,支持响应式设计
- ✅ 配置 Nginx:设置了反向代理和错误页面重定向,包括健康检查端点
- ✅ 高级功能:实现了多语言支持和基于 IP 的维护模式例外
- ✅ 安全加固:增强了服务器的安全性配置,包括 SSL 强化和安全头设置
- ✅ 维护工具:创建了维护模式管理脚本和监控命令
- ✅ 防火墙配置:设置了适当的防火墙规则保护服务器
现在你的网站在维护或出现错误时能够向用户展示友好的界面,提升用户体验!🎉
💡 提示:
- 定期测试维护页面确保其正常工作,特别是在进行重大更新之前
- 考虑为不同的服务创建特定的维护页面,提供更精确的状态信息
- 使用监控工具定期检查服务器性能和安全性
- 定期更新 SSL 证书和安全配置以保持最佳安全性