Featured image of post Nginx 网站维护页配置指南 🛠️

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

Nginx 网站维护页配置完全指南 🛠️ 📖 目录导航 ✨ 维护

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
# 创建 40x 错误页面 (客户端错误)
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, #667eea 0%, #764ba2 100%);
            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: #ff6b6b;
        }
        h2 {
            margin-top: 0;
            font-weight: 300;
        }
        p {
            line-height: 1.6;
            margin-bottom: 2rem;
        }
        .btn {
            display: inline-block;
            padding: 12px 24px;
            background: #4ecdc4;
            color: white;
            text-decoration: none;
            border-radius: 25px;
            transition: all 0.3s ease;
            margin: 0 10px 10px 0;
        }
        .btn:hover {
            background: #45b7aa;
            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

# 创建 50x 错误页面 (服务器错误)
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, #f093fb 0%, #f5576c 100%);
            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: #ffeaa7;
        }
        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: #74b9ff;
            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: #6c5ce7;
            color: white;
            text-decoration: none;
            border-radius: 25px;
            transition: all 0.3s ease;
            margin: 0 10px 10px 0;
        }
        .btn:hover {
            background: #5c4bc0;
            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 {
    # 监听 5553 端口并启用 SSL
    listen 5553 ssl http2;
    listen [::]:5553 ssl http2;

    # 服务器名称
    server_name xunlei.mobufan.eu.org;

    # SSL 证书配置
    ssl_certificate /etc/nginx/keyfile/cert.pem;
    ssl_certificate_key /etc/nginx/keyfile/key.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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    
    # SSL 会话设置
    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;
        
        # 启用 Websocket 支持
        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;
    
    # 40x 错误页面位置
    location = /40x.html {
        root /var/www/html;
        internal;
        access_log off;
        log_not_found off;
    }
    
    # 50x 错误页面位置
    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

# 重启 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

🎨 三、高级维护页面配置

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, #667eea 0%, #764ba2 100%);
            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: #ff6b6b;
        }
        p {
            line-height: 1.6;
            margin-bottom: 2rem;
        }
        .btn {
            display: inline-block;
            padding: 12px 24px;
            background: #4ecdc4;
            color: white;
            text-decoration: none;
            border-radius: 25px;
            transition: all 0.3s ease;
            margin: 0 10px 10px 0;
        }
        .btn:hover {
            background: #45b7aa;
            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'
#!/bin/bash

# 维护模式开关脚本
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;
        }
        
        # 返回503状态码
        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

# 创建 snippets 目录(如果不存在)
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
# 创建基于 IP 的维护模式例外配置
sudo tee /etc/nginx/snippets/maintenance-whitelist.conf > /dev/null <<'EOF'
# 允许特定 IP 访问(管理员和测试人员)
geo $maintenance_whitelist {
    default 0;
    # 添加允许访问的 IP 地址
    192.168.1.100 1;  # 管理员 IP
    10.0.0.50 1;      # 测试环境 IP
    # 更多 IP...
}

# 根据 IP 白名单决定是否显示维护页面
map $maintenance_whitelist $maintenance_pass {
    0 $maintenance_mode;  # 非白名单IP受维护模式影响
    1 0;                  # 白名单IP不受影响
}
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
# 检查 Nginx 配置语法
sudo nginx -t

# 重新加载配置(不中断服务)
sudo systemctl reload nginx

# 完全重启 Nginx
sudo systemctl restart nginx

# 查看 Nginx 状态
sudo systemctl status nginx

# 查看 Nginx 错误日志
sudo tail -f /var/log/nginx/error.log

# 查看访问日志
sudo tail -f /var/log/nginx/access.log

# 查看 Nginx 进程
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
# 实时监控 Nginx 访问日志
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

# 使用 ngxtop 监控(需要安装)
sudo ngxtop

# 检查 Nginx 配置包含
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;

# 隐藏 Nginx 版本号
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
# 启用 UFW 防火墙
sudo ufw enable

# 开放必要端口
sudo ufw allow 22/tcp    # SSH
sudo ufw allow 80/tcp    # HTTP
sudo ufw allow 443/tcp   # HTTPS
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
# 创建 SSL 优化配置
sudo tee /etc/nginx/snippets/ssl-params.conf > /dev/null <<'EOF'
# 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: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 网站维护页面和相关设置:

  1. 创建维护页面:设计了美观的 40x 和 50x 错误页面,支持响应式设计
  2. 配置 Nginx:设置了反向代理和错误页面重定向,包括健康检查端点
  3. 高级功能:实现了多语言支持和基于 IP 的维护模式例外
  4. 安全加固:增强了服务器的安全性配置,包括 SSL 强化和安全头设置
  5. 维护工具:创建了维护模式管理脚本和监控命令
  6. 防火墙配置:设置了适当的防火墙规则保护服务器

现在你的网站在维护或出现错误时能够向用户展示友好的界面,提升用户体验!🎉

💡 提示

  • 定期测试维护页面确保其正常工作,特别是在进行重大更新之前
  • 考虑为不同的服务创建特定的维护页面,提供更精确的状态信息
  • 使用监控工具定期检查服务器性能和安全性
  • 定期更新 SSL 证书和安全配置以保持最佳安全性
最后更新于 2025-09-28