Nginx 模块化多业务站点通用配置模板

Nginx 模块化多业务站点通用配置模板

在生产环境中,Nginx 配置不建议全部堆积在一个文件里。随着站点、API、WebSocket 和 PHP 服务逐渐增多,单个配置文件会越来越难以维护。

本文设计一套适用于源码编译安装 Nginx 的通用配置模板,主要目标如下:

  • Nginx 安装目录统一为 /usr/local/nginx
  • 主配置只保存全局通用配置;
  • nginx.conf 中不写 server {}
  • 虚拟主机按照业务类型分类;
  • HTTPS 证书统一放到 /usr/local/nginx/conf/ssl/
  • 日志统一放到 /usr/local/nginx/logs/
  • 通过一个 include 规则加载所有业务主机配置。

一、整体目录结构

各目录作用如下:

目录 用途
conf/ Nginx 配置文件
conf/snippets/ 可复用的公共配置片段
conf/ssl/ HTTPS 证书和私钥
conf/vhost/ 虚拟主机配置
logs/ Nginx 全局日志和站点日志
html/ Nginx 默认网页目录

vhost 目录按照业务类型继续划分:

vhost/static/:静态网站

vhost/proxy/:反向代理服务

vhost/php/:PHP 网站

vhost/websocket/:WebSocket 服务

vhost/default/:默认拒绝站点

二、部署前准备

在启动 Nginx 之前,需要先完成以下准备工作。源码编译安装的 Nginx 不会自动创建运行用户和目录,这些都需要手动处理。

1、创建 nginx 用户

bash 复制代码
id nginx &>/dev/null || useradd -r -s /sbin/nologin nginx

2、创建所需目录

bash 复制代码
mkdir -p /usr/local/nginx/logs
mkdir -p /usr/local/nginx/conf/snippets
mkdir -p /usr/local/nginx/conf/ssl
mkdir -p /usr/local/nginx/conf/vhost/{default,static,proxy,php,websocket}

3、设置日志目录权限

bash 复制代码
chown -R nginx:nginx /usr/local/nginx/logs
chmod 750 /usr/local/nginx/logs

三、主配置文件

主配置文件为:/usr/local/nginx/conf/nginx.conf

这里不写任何 server {},只保留 Nginx 的全局配置、HTTP 通用配置以及 vhost 加载规则。

nginx 复制代码
user nginx;

worker_processes auto;
worker_rlimit_nofile 65535;

error_log /usr/local/nginx/logs/error.log warn;
pid        /usr/local/nginx/logs/nginx.pid;

events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}

http {
    include       /usr/local/nginx/conf/mime.types;
    default_type  application/octet-stream;

    # 隐藏 Nginx 版本号
    server_tokens off;

    # 访问日志格式
    log_format main
        '$remote_addr - $remote_user [$time_local] '
        '"$request" $status $body_bytes_sent '
        '"$http_referer" "$http_user_agent" '
        'request_time=$request_time '
        'upstream_response_time=$upstream_response_time';

    # 全局访问日志
    access_log /usr/local/nginx/logs/access.log main;

    # 文件传输
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    # 长连接
    keepalive_timeout 65;
    keepalive_requests 1000;

    # 请求超时
    client_header_timeout 15s;
    client_body_timeout 60s;
    send_timeout 60s;

    # 默认请求体大小
    # 上传业务可以在具体 server 中单独调整
    client_max_body_size 10m;

    # 请求头缓冲
    large_client_header_buffers 4 16k;

    # Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 5;
    gzip_min_length 1k;

    gzip_types
        text/plain
        text/css
        text/xml
        application/xml
        application/json
        application/javascript
        application/x-javascript
        application/rss+xml
        application/atom+xml
        image/svg+xml;

    # WebSocket 的 Upgrade 映射必须放在 http 上下文
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    # HTTPS 通用参数
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_session_cache shared:SSL:20m;
    ssl_session_timeout 10m;
    ssl_session_tickets off;
    ssl_prefer_server_ciphers off;

    # 全局安全响应头
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

    # 加载所有业务子目录下的虚拟主机配置
    include /usr/local/nginx/conf/vhost/*/*.conf;
}

四、公共配置片段

如果把全部http配置放到 nginx.conf,就会让主配置包含很多并非所有站点都使用的内容,我们把HTTP配置拆分成模块化,需要接入的站点通过include放入

1、反向代理

/usr/local/nginx/conf/snippets/proxy-common.conf

nginx 复制代码
proxy_http_version 1.1;

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 10s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;

proxy_buffering on;
proxy_buffer_size 16k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;

反向代理站点中使用:

nginx 复制代码
location / {
    proxy_pass http://127.0.0.1:3000;

    include /usr/local/nginx/conf/snippets/proxy-common.conf;
}

2、WebSocket

WebSocket 本质上也是反向代理,但相比普通 HTTP 反向代理,需要额外处理 UpgradeConnection 请求头。

/usr/local/nginx/conf/snippets/websocket-common.conf

nginx 复制代码
#引入上面的反向代理公共配置
include /usr/local/nginx/conf/snippets/proxy-common.conf;

proxy_set_header Upgrade    $http_upgrade;
proxy_set_header Connection $connection_upgrade;

#用于延长长连接的读写超时时间,避免 WebSocket 连接长时间没有数据传输时被 Nginx 关闭。
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;

WebSocket 站点中使用:

nginx 复制代码
location / {
    proxy_pass http://127.0.0.1:8080;

    include /usr/local/nginx/conf/snippets/websocket-common.conf;
}

3、PHP-FPM

PHP 网站使用 FastCGI 协议与 PHP-FPM 通信。

Nginx 安装目录中通常会有一个文件:/usr/local/nginx/conf/fastcgi_params,它用于向 PHP-FPM 传递请求参数。

创建 PHP-FPM 公共配置:/usr/local/nginx/conf/snippets/fastcgi-common.conf

nginx 复制代码
include /usr/local/nginx/conf/fastcgi_params;

fastcgi_connect_timeout 10s;
fastcgi_send_timeout 60s;
fastcgi_read_timeout 60s;

#用于告诉 PHP-FPM 当前需要执行的 PHP 文件的完整路径
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT   $document_root;

PHP 站点中使用:

nginx 复制代码
location ~ \.php$ {
    try_files $uri =404;

    include /usr/local/nginx/conf/snippets/fastcgi-common.conf;

    fastcgi_pass unix:/run/php/php-fpm.sock;
}

4、静态文件缓存

静态文件缓存主要用于静态网站,例如 HTML、CSS、JavaScript、图片和字体文件。

创建公共配置:/usr/local/nginx/conf/snippets/static-cache.conf

nginx 复制代码
open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;

静态网站中引入:

nginx 复制代码
server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name example.com;

    root /data/www/example.com;
    index index.html;

    include /usr/local/nginx/conf/snippets/static-cache.conf;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

静态资源还可以单独设置浏览器缓存:

nginx 复制代码
location ~* \.(jpg|jpeg|png|gif|svg|ico|webp|avif|css|js|woff|woff2|ttf)$ {
    expires 7d;
    add_header Cache-Control "public, max-age=604800, immutable";

    try_files $uri =404;
}

五、虚拟主机配置

1、默认拒绝站点

为了避免没有匹配到域名的请求访问到默认站点,可以创建一个默认拒绝配置。

创建文件:/usr/local/nginx/conf/vhost/default/default.conf

nginx 复制代码
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;

    return 444;
}

server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    server_name _;

    ssl_reject_handshake on;
}

444 是 Nginx 特有的状态码,表示直接关闭连接,不向客户端返回正常响应内容。

2、静态 HTTPS 网站

文件:/usr/local/nginx/conf/vhost/static/example.com.conf

nginx 复制代码
server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name example.com www.example.com;

    root /data/www/example.com;
    index index.html;

    ssl_certificate     /usr/local/nginx/conf/ssl/example.com/fullchain.pem;
    ssl_certificate_key /usr/local/nginx/conf/ssl/example.com/privkey.key;

    access_log /usr/local/nginx/logs/example.com.access.log main;
    error_log  /usr/local/nginx/logs/example.com.error.log warn;

    add_header Strict-Transport-Security "max-age=31536000" always;

    include /usr/local/nginx/conf/snippets/static-cache.conf;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location ~* \.(jpg|jpeg|png|gif|svg|ico|webp|avif|css|js|woff|woff2|ttf)$ {
        expires 7d;
        add_header Cache-Control "public, max-age=604800, immutable";

        try_files $uri =404;
    }

    location ~ /\.(?!well-known) {
        deny all;
    }
}

3、反向代理网站

假设后端服务监听:127.0.0.1:3000

创建反向代理虚拟主机配置:/usr/local/nginx/conf/vhost/proxy/api.example.com.conf

nginx 复制代码
server {
    listen 80;
    listen [::]:80;

    server_name api.example.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name api.example.com;

    ssl_certificate     /usr/local/nginx/conf/ssl/api.example.com/fullchain.pem;
    ssl_certificate_key /usr/local/nginx/conf/ssl/api.example.com/privkey.key;

    access_log /usr/local/nginx/logs/api.example.com.access.log main;
    error_log  /usr/local/nginx/logs/api.example.com.error.log warn;

    client_max_body_size 50m;

    location / {
        proxy_pass http://127.0.0.1:3000;

        include /usr/local/nginx/conf/snippets/proxy-common.conf;
    }
}

4、WebSocket 网站

假设 WebSocket 服务监听:127.0.0.1:8080

创建虚拟主机文件:/usr/local/nginx/conf/vhost/websocket/ws.example.com.conf

nginx 复制代码
server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name ws.example.com;

    ssl_certificate     /usr/local/nginx/conf/ssl/ws.example.com/fullchain.pem;
    ssl_certificate_key /usr/local/nginx/conf/ssl/ws.example.com/privkey.key;

    access_log /usr/local/nginx/logs/ws.example.com.access.log main;
    error_log  /usr/local/nginx/logs/ws.example.com.error.log warn;

    location / {
        proxy_pass http://127.0.0.1:8080;

        include /usr/local/nginx/conf/snippets/websocket-common.conf;
    }
}

5、PHP网站

假设网站目录为:/data/www/php.example.com/public

创建虚拟主机文件:/usr/local/nginx/conf/vhost/php/php.example.com.conf

nginx 复制代码
server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name php.example.com;

    root /data/www/php.example.com/public;
    index index.php index.html;

    ssl_certificate     /usr/local/nginx/conf/ssl/php.example.com/fullchain.pem;
    ssl_certificate_key /usr/local/nginx/conf/ssl/php.example.com/privkey.key;

    access_log /usr/local/nginx/logs/php.example.com.access.log main;
    error_log  /usr/local/nginx/logs/php.example.com.error.log warn;

    client_max_body_size 50m;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $uri =404;

        include /usr/local/nginx/conf/snippets/fastcgi-common.conf;

        fastcgi_pass unix:/run/php/php-fpm.sock;
    }

    location ~ /\.(?!well-known) {
        deny all;
    }
}

如果需要 HTTP 自动跳转 HTTPS,可以在同一个文件中增加:

nginx 复制代码
server {
    listen 80;
    listen [::]:80;

    server_name php.example.com;

    return 301 https://$host$request_uri;
}

六、初始化模版目录脚本

bash 复制代码
#!/bin/bash
#=============================================================================
# Nginx 模块化多业务站点配置模板 - 初始化脚本
# 适用:源码编译安装,安装目录 /usr/local/nginx
#=============================================================================
set -e

NGINX_ROOT="/usr/local/nginx"
CONF_DIR="${NGINX_ROOT}/conf"
LOGS_DIR="${NGINX_ROOT}/logs"
HTML_DIR="${NGINX_ROOT}/html"


echo "============================================"
echo " Nginx 目录与配置模板初始化"
echo " 安装目录: ${NGINX_ROOT}"
echo "============================================"
echo ""


#=============================================================================
# 1. 创建 nginx 用户
#=============================================================================
echo ">>> 1. 检查 nginx 用户"
if id nginx &>/dev/null; then
    echo "    nginx 用户已存在,跳过"
else
    useradd -r -s /sbin/nologin nginx
    echo "    nginx 用户创建完成"
fi
echo ""


#=============================================================================
# 2. 创建目录结构
#=============================================================================
echo ">>> 2. 创建目录结构"


mkdir -p "${LOGS_DIR}"
mkdir -p "${HTML_DIR}"
mkdir -p "${CONF_DIR}/snippets"
mkdir -p "${CONF_DIR}/ssl"
mkdir -p "${CONF_DIR}/vhost/default"
mkdir -p "${CONF_DIR}/vhost/static"
mkdir -p "${CONF_DIR}/vhost/proxy"
mkdir -p "${CONF_DIR}/vhost/php"
mkdir -p "${CONF_DIR}/vhost/websocket"


echo "    目录结构创建完成"
echo ""


#=============================================================================
# 3. 设置权限
#=============================================================================
echo ">>> 3. 设置目录权限"


chown -R nginx:nginx "${LOGS_DIR}"
chmod 750 "${LOGS_DIR}"


chown -R root:root "${CONF_DIR}/ssl"
chmod 700 "${CONF_DIR}/ssl"


echo "    权限设置完成"
echo ""


#=============================================================================
# 4. 写入主配置文件
#=============================================================================
echo ">>> 4. 写入主配置文件 nginx.conf"


cat > "${CONF_DIR}/nginx.conf" << 'NGINX_CONF'
user nginx;


worker_processes auto;
worker_rlimit_nofile 65535;


error_log /usr/local/nginx/logs/error.log warn;
pid        /usr/local/nginx/logs/nginx.pid;


events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}


http {
    # ==============================
    # 基础配置
    # ==============================


    include       /usr/local/nginx/conf/mime.types;
    default_type  application/octet-stream;


    server_tokens off;


    # ==============================
    # 日志配置
    # ==============================


    log_format main
        '$remote_addr - $remote_user [$time_local] '
        '"$request" $status $body_bytes_sent '
        '"$http_referer" "$http_user_agent" '
        'request_time=$request_time '
        'upstream_response_time=$upstream_response_time';


    access_log /usr/local/nginx/logs/access.log main;


    # ==============================
    # 网络与请求配置
    # ==============================


    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;


    keepalive_timeout 65;
    keepalive_requests 1000;


    client_header_timeout 15s;
    client_body_timeout 60s;
    send_timeout 60s;


    client_max_body_size 10m;
    large_client_header_buffers 4 16k;


    # ==============================
    # Gzip 压缩
    # ==============================


    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 5;
    gzip_min_length 1k;


    gzip_types
        text/plain
        text/css
        text/xml
        application/xml
        application/json
        application/javascript
        application/x-javascript
        application/rss+xml
        application/atom+xml
        image/svg+xml;


    # ==============================
    # HTTPS 通用配置
    # ==============================


    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_session_cache shared:SSL:20m;
    ssl_session_timeout 10m;
    ssl_session_tickets off;
    ssl_prefer_server_ciphers off;


    # ==============================
    # 全局安全响应头
    # ==============================


    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;


    # ==============================
    # WebSocket 升级映射
    # ==============================


    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }


    # ==============================
    # 加载虚拟主机配置
    # ==============================


    include /usr/local/nginx/conf/vhost/*/*.conf;
}
NGINX_CONF


echo "    nginx.conf 写入完成"
echo ""


#=============================================================================
# 5. 写入公共配置片段
#=============================================================================
echo ">>> 5. 写入公共配置片段 snippets"


cat > "${CONF_DIR}/snippets/proxy-common.conf" << 'EOF'
proxy_http_version 1.1;


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_buffering on;
proxy_buffer_size 16k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
EOF


cat > "${CONF_DIR}/snippets/websocket-common.conf" << 'EOF'
include /usr/local/nginx/conf/snippets/proxy-common.conf;


proxy_set_header Upgrade    $http_upgrade;
proxy_set_header Connection $connection_upgrade;


proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
EOF


cat > "${CONF_DIR}/snippets/fastcgi-common.conf" << 'EOF'
include /usr/local/nginx/conf/fastcgi_params;


fastcgi_connect_timeout 10s;
fastcgi_send_timeout 60s;
fastcgi_read_timeout 60s;


fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT   $document_root;
EOF


cat > "${CONF_DIR}/snippets/static-cache.conf" << 'EOF'
open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
EOF


echo "    snippets 写入完成"
echo ""


#=============================================================================
# 6. 写入默认拒绝站点
#=============================================================================
echo ">>> 6. 写入默认拒绝站点 vhost/default/default.conf"


cat > "${CONF_DIR}/vhost/default/default.conf" << 'EOF'
server {
    listen 80 default_server;
    listen [::]:80 default_server;


    server_name _;


    return 444;
}


server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;


    server_name _;


    ssl_reject_handshake on;
}
EOF


echo "    default.conf 写入完成"
echo ""


#=============================================================================
# 7. 写入静态网站模板
#=============================================================================
echo ">>> 7. 写入静态网站模板 vhost/static/example.com.conf.example"


cat > "${CONF_DIR}/vhost/static/example.com.conf.example" << 'EOF'
server {
    listen 80;
    listen [::]:80;


    server_name example.com www.example.com;


    return 301 https://$host$request_uri;
}


server {
    listen 443 ssl;
    listen [::]:443 ssl;


    server_name example.com www.example.com;


    root /data/www/example.com;
    index index.html;


    ssl_certificate     /usr/local/nginx/conf/ssl/example.com/fullchain.pem;
    ssl_certificate_key /usr/local/nginx/conf/ssl/example.com/privkey.pem;


    access_log /usr/local/nginx/logs/example.com.access.log main;
    error_log  /usr/local/nginx/logs/example.com.error.log warn;


    add_header Strict-Transport-Security "max-age=31536000" always;


    include /usr/local/nginx/conf/snippets/static-cache.conf;


    location / {
        try_files $uri $uri/ /index.html;
    }


    # 多页面网站请改为: try_files $uri $uri/ =404


    location ~* \.(jpg|jpeg|png|gif|svg|ico|webp|avif|css|js|woff|woff2|ttf)$ {
        expires 7d;
        add_header Cache-Control "public, max-age=604800, immutable";


        try_files $uri =404;
    }


    location ~ /\.(?!well-known) {
        deny all;
    }
}
EOF


echo "    example.com.conf.example 写入完成"
echo ""


#=============================================================================
# 8. 写入反向代理模板
#=============================================================================
echo ">>> 8. 写入反向代理模板 vhost/proxy/api.example.com.conf.example"


cat > "${CONF_DIR}/vhost/proxy/api.example.com.conf.example" << 'EOF'
server {
    listen 80;
    listen [::]:80;


    server_name api.example.com;


    return 301 https://$host$request_uri;
}


server {
    listen 443 ssl;
    listen [::]:443 ssl;


    server_name api.example.com;


    ssl_certificate     /usr/local/nginx/conf/ssl/api.example.com/fullchain.pem;
    ssl_certificate_key /usr/local/nginx/conf/ssl/api.example.com/privkey.pem;


    access_log /usr/local/nginx/logs/api.example.com.access.log main;
    error_log  /usr/local/nginx/logs/api.example.com.error.log warn;


    client_max_body_size 50m;


    location / {
        # 修改为实际后端地址
        proxy_pass http://127.0.0.1:3000;


        include /usr/local/nginx/conf/snippets/proxy-common.conf;


        # 普通反向代理超时
        proxy_connect_timeout 10s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}
EOF


echo "    api.example.com.conf.example 写入完成"
echo ""


#=============================================================================
# 9. 写入 WebSocket 模板
#=============================================================================
echo ">>> 9. 写入 WebSocket 模板 vhost/websocket/ws.example.com.conf.example"


cat > "${CONF_DIR}/vhost/websocket/ws.example.com.conf.example" << 'EOF'
server {
    listen 80;
    listen [::]:80;


    server_name ws.example.com;


    return 301 https://$host$request_uri;
}


server {
    listen 443 ssl;
    listen [::]:443 ssl;


    server_name ws.example.com;


    ssl_certificate     /usr/local/nginx/conf/ssl/ws.example.com/fullchain.pem;
    ssl_certificate_key /usr/local/nginx/conf/ssl/ws.example.com/privkey.pem;


    access_log /usr/local/nginx/logs/ws.example.com.access.log main;
    error_log  /usr/local/nginx/logs/ws.example.com.error.log warn;


    location / {
        # 修改为实际 WebSocket 后端地址
        proxy_pass http://127.0.0.1:8080;


        include /usr/local/nginx/conf/snippets/websocket-common.conf;
    }
}
EOF


echo "    ws.example.com.conf.example 写入完成"
echo ""


#=============================================================================
# 10. 写入 PHP-FPM 模板
#=============================================================================
echo ">>> 10. 写入 PHP 模板 vhost/php/php.example.com.conf.example"


cat > "${CONF_DIR}/vhost/php/php.example.com.conf.example" << 'EOF'
server {
    listen 80;
    listen [::]:80;


    server_name php.example.com;


    return 301 https://$host$request_uri;
}


server {
    listen 443 ssl;
    listen [::]:443 ssl;


    server_name php.example.com;


    root /data/www/php.example.com/public;
    index index.php index.html;


    ssl_certificate     /usr/local/nginx/conf/ssl/php.example.com/fullchain.pem;
    ssl_certificate_key /usr/local/nginx/conf/ssl/php.example.com/privkey.pem;


    access_log /usr/local/nginx/logs/php.example.com.access.log main;
    error_log  /usr/local/nginx/logs/php.example.com.error.log warn;


    client_max_body_size 50m;


    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }


    location ~ \.php$ {
        try_files $uri =404;


        include /usr/local/nginx/conf/snippets/fastcgi-common.conf;


        # 修改为实际的 PHP-FPM socket 路径
        fastcgi_pass unix:/run/php/php-fpm.sock;
    }


    location ~ /\.(?!well-known) {
        deny all;
    }
}
EOF


echo "    php.example.com.conf.example 写入完成"
echo ""


#=============================================================================
# 11. 检查必要文件
#=============================================================================
echo ">>> 11. 检查必要文件"


if [ -f "${CONF_DIR}/mime.types" ]; then
    echo "    mime.types 已存在"
else
    echo "    [警告] mime.types 不存在,Nginx 启动将报错"
    echo "    请从 Nginx 源码目录复制:"
    echo "    cp /path/to/nginx-src/conf/mime.types ${CONF_DIR}/"
fi


if [ -f "${CONF_DIR}/fastcgi_params" ]; then
    echo "    fastcgi_params 已存在"
else
    echo "    [警告] fastcgi_params 不存在,PHP 站点将无法运行"
    echo "    请从 Nginx 源码目录复制:"
    echo "    cp /path/to/nginx-src/conf/fastcgi_params ${CONF_DIR}/"
fi


echo ""
echo "============================================"
echo " 初始化完成"
echo "============================================"
echo ""


echo "一、已生效"
echo "   1. 主配置     → ${CONF_DIR}/nginx.conf"
echo "   2. 公共片段   → ${CONF_DIR}/snippets/"
echo "      · proxy-common.conf       反向代理"
echo "      · websocket-common.conf   WebSocket"
echo "      · fastcgi-common.conf     PHP-FPM"
echo "      · static-cache.conf       静态缓存"
echo "   3. 默认站点   → ${CONF_DIR}/vhost/default/default.conf"
echo "      80  未匹配 → return 444"
echo "      443 未匹配 → ssl_reject_handshake"
echo "   4. 日志目录   → ${LOGS_DIR}/"
echo "      · access.log               全局访问日志"
echo "      · error.log                全局错误日志"
echo "      · 域名.access.log          站点独立日志"
echo "      · 域名.error.log           站点错误日志"
echo ""


echo "二、模板(未启用,需复制后使用)"
echo "   1. vhost/static/example.com.conf.example       静态网站"
echo "   2. vhost/proxy/api.example.com.conf.example    反向代理"
echo "   3. vhost/php/php.example.com.conf.example      PHP 网站"
echo "   4. vhost/websocket/ws.example.com.conf.example WebSocket"
echo ""


echo "三、使用(以静态网站为例)"
echo "   cp ${CONF_DIR}/vhost/static/example.com.conf.example \\"
echo "      ${CONF_DIR}/vhost/static/实际域名.conf"
echo ""
echo "   vim ${CONF_DIR}/vhost/static/实际域名.conf"
echo "   ${NGINX_ROOT}/sbin/nginx -t && ${NGINX_ROOT}/sbin/nginx -s reload"
echo ""
相关推荐
snow@li1 小时前
服务器运维:解构我的服务器202609/小白学习
运维
网硕互联的小客服1 小时前
可以把服务器当成DNS服务器使用吗?如何操作?
运维·服务器·网络
辛迪聊物业数字化1 小时前
【拆解智慧物业管理系统架构:从SaaS落地到IoT全链路实现】
大数据·linux·组合模式
j7~1 小时前
【C++微服务项目开发脚手架】(准备篇)从 0 到跑通:Docker 容器开发环境 + 宿主机用户 + Trae 远程连接 全链路踩坑实战
linux·c++·学习·xshell·docker容器·trae
和裕2 小时前
平口开槽箱 vs 飞机盒 vs 扣底盒:自动化、展示效果与成本核心区别
大数据·运维·网络·人工智能·算法·自动化
码上上班2 小时前
tomcat 知识点总结
运维·tomcat
程序员-Benothing2 小时前
Linux用户与组管理命令大全:useradd、usermod、groupadd、passwd
linux·运维·服务器
羑悻的小杀马特2 小时前
从写 YAML 到集群自愈:KES-Operator 把 KES 集群接进 Kubernetes 原生体系
运维·数据库·容器·kubernetes
bksczm2 小时前
MySQL基础篇之事务
linux·数据库·sql·mysql