Nginx 虚拟主机配置

Nginx 虚拟主机(Server Block)配置详解


📋 目录


虚拟主机基础

什么是虚拟主机

虚拟主机允许在同一台服务器上运行多个网站,共享服务器资源。

服务器 IP: 192.168.1.100
    ├─ 网站 1: www.example1.com
    ├─ 网站 2: www.example2.com
    └─ 网站 3: www.example3.com

Nginx 虚拟主机类型

  1. 基于域名的虚拟主机 - 最常用的方式
  2. 基于端口的虚拟主机 - 不同端口
  3. 基于 IP 的虚拟主机 - 不同 IP 地址

基于域名的虚拟主机

基本配置

# 虚拟主机 1
server {
    listen 80;
    server_name www.example1.com example1.com;
 
    root /var/www/example1;
    index index.html index.htm;
 
    location / {
        try_files $uri $uri/ =404;
    }
}
 
# 虚拟主机 2
server {
    listen 80;
    server_name www.example2.com example2.com;
 
    root /var/www/example2;
    index index.html index.htm;
 
    location / {
        try_files $uri $uri/ =404;
    }
}

通配符域名

# 匹配所有子域名
server {
    listen 80;
    server_name *.example.com;
 
    root /var/www/example;
    index index.html;
 
    location / {
        try_files $uri $uri/ =404;
    }
}
 
# 匹配所有以 example 开头的域名
server {
    listen 80;
    server_name example.*;
 
    # ...
}

正则表达式域名

# 使用正则匹配域名
server {
    listen 80;
    server_name ~^www\.example\.com$;
 
    # ...
}
 
# 捕获域名部分
server {
    listen 80;
    server_name ~^(www\.)?(?<domain>.+)$;
 
    root /var/www/$domain;
    index index.html;
}

多域名共享配置

server {
    listen 80;
    server_name example1.com www.example1.com
                example2.com www.example2.com
                example3.com www.example3.com;
 
    root /var/www/shared;
    index index.html;
}

基于端口的虚拟主机

不同端口不同网站

# HTTP 网站
server {
    listen 80;
    server_name example.com;
 
    root /var/www/http;
    index index.html;
}
 
# HTTPS 网站
server {
    listen 443 ssl;
    server_name example.com;
 
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
 
    root /var/www/https;
    index index.html;
}
 
# 管理后台
server {
    listen 8080;
    server_name example.com;
 
    root /var/www/admin;
    index index.html;
 
    # 访问控制
    allow 192.168.1.0/24;
    deny all;
}

同一域名不同端口

# 网站端口
server {
    listen 80;
    listen 8080;
    server_name example.com;
 
    root /var/www/website;
    index index.html;
}
 
# API 端口
server {
    listen 9000;
    server_name example.com;
 
    root /var/www/api;
    index index.php;
 
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
 
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

基于 IP 的虚拟主机

不同 IP 不同网站

# 监听所有 IP 的 80 端口
server {
    listen 80;
    server_name example.com;
 
    root /var/www/example;
    index index.html;
}
 
# 监听特定 IP 的 80 端口
server {
    listen 192.168.1.100:80;
    server_name example.com;
 
    root /var/www/example-ip1;
    index index.html;
}
 
# 监听另一个 IP 的 80 端口
server {
    listen 192.168.1.101:80;
    server_name example.com;
 
    root /var/www/example-ip2;
    index index.html;
}

IPv6 虚拟主机

server {
    listen 80;
    listen [::]:80 ipv6only=on;  # IPv6
    server_name example.com;
 
    root /var/www/example;
    index index.html;
}

默认虚拟主机

配置默认虚拟主机

# 默认虚拟主机(捕获所有未匹配的域名)
server {
    listen 80 default_server;  # default_server 标记
    listen [::]:80 default_server;
 
    server_name _;  # 无效的域名,表示匹配所有
 
    root /var/www/default;
    index index.html;
 
    return 404;  # 或者重定向到主页
}

拒绝未匹配的域名

# 默认虚拟主机 - 拒绝访问
server {
    listen 80 default_server;
    listen [::]:80 default_server;
 
    server_name _;
 
    # 返回 444(Nginx 特殊状态码,立即关闭连接)
    return 444;
}
 
# 或者返回 404
server {
    listen 80 default_server;
    server_name _;
 
    return 404;
}
 
# 或者重定向到主站
server {
    listen 80 default_server;
    server_name _;
 
    return 301 http://www.example.com$request_uri;
}

虚拟主机最佳实践

分离配置文件

# 创建目录结构
/etc/nginx/
├── nginx.conf                    # 主配置文件
├── sites-available/              # 可用站点配置
   ├── example1.com
   ├── example2.com
   └── default
└── sites-enabled/                # 启用站点配置
    ├── example1.com -> ../sites-available/example1.com
    └── example2.com -> ../sites-available/example2.com

Include 方式

# nginx.conf
http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
 
    # 基础配置
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
 
    access_log /var/log/nginx/access.log main;
 
    # 虚拟主机配置
    include /etc/nginx/sites-enabled/*;
}

示例站点配置

# /etc/nginx/sites-available/example.com
server {
    listen 80;
    server_name example.com www.example.com;
 
    root /var/www/example.com;
    index index.html index.htm;
 
    # 访问日志
    access_log /var/log/nginx/example.com.access.log main;
    error_log /var/log/nginx/example.com.error.log warn;
 
    # 字符编码
    charset utf-8;
 
    # Gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript;
 
    location / {
        try_files $uri $uri/ =404;
    }
 
    # 静态文件缓存
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
 
    # 隐藏文件
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
 
    # 错误页面
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
 
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}
 
# 启用站点
# sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

HTTPS 虚拟主机

# HTTP 重定向到 HTTPS
server {
    listen 80;
    server_name example.com www.example.com;
 
    # 重定向到 HTTPS
    return 301 https://$server_name$request_uri;
}
 
# HTTPS 虚拟主机
server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
 
    root /var/www/example.com;
    index index.html;
 
    # SSL 配置
    ssl_certificate /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;
 
    # SSL 优化
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
    ssl_prefer_server_ciphers off;
 
    # SSL 会话缓存
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
 
    location / {
        try_files $uri $uri/ =404;
    }
}

泛域名配置

# 泛域名虚拟主机
server {
    listen 80;
    server_name *.example.com;
 
    # 提取子域名
    if ($host ~* ^(.+)\.example\.com$) {
        set $subdomain $1;
    }
 
    root /var/www/$subdomain;
    index index.html;
 
    location / {
        try_files $uri $uri/ =404;
    }
}
 
# 或者使用正则
server {
    listen 80;
    server_name ~^(?<subdomain>.+)\.example\.com$;
 
    root /var/www/$subdomain;
    index index.html;
 
    location / {
        try_files $uri $uri/ =404;
    }
}

多域名共享配置

# 共享配置的虚拟主机
server {
    listen 80;
    server_name
        example1.com www.example1.com
        example2.com www.example2.com
        example3.com www.example3.com;
 
    root /var/www/shared;
    index index.html;
 
    location / {
        try_files $uri $uri/ =404;
    }
}

开发环境虚拟主机

# 开发环境配置
server {
    listen 80;
    server_name dev.example.com;
 
    root /var/www/dev;
    index index.html;
 
    # 开发环境配置
    error_log /var/log/nginx/dev.error.log debug;
    access_log /var/log/nginx/dev.access.log;
 
    # 禁用缓存
    add_header Cache-Control "no-cache, no-store, must-revalidate";
    add_header Pragma "no-cache";
    add_header Expires "0";
 
    location / {
        try_files $uri $uri/ =404;
    }
 
    # API 代理到开发服务器
    location /api/ {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
 
    # WebSocket 代理
    location /ws/ {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

🔧 高级技巧

动态虚拟主机

# 根据域名自动选择目录
server {
    listen 80;
    server_name ~^(www\.)?(?<domain>.+)$;
 
    root /var/www/$domain;
    index index.html;
 
    location / {
        try_files $uri $uri/ =404;
    }
}

虚拟主机模板

# 使用 map 配置不同参数
map $host $root_path {
    default /var/www/default;
    example1.com /var/www/example1;
    example2.com /var/www/example2;
    ~*\.example\.com /var/www/example;
}
 
server {
    listen 80;
    server_name _;
 
    root $root_path;
    index index.html;
 
    location / {
        try_files $uri $uri/ =404;
    }
}

流量分发

# 根据来源分配不同后端
map $http_referer $backend {
    default backend_main;
    ~*google\.com backend_google;
    ~*baidu\.com backend_baidu;
    ~*wechat backend_wechat;
}
 
upstream backend_main { server 127.0.0.1:8000; }
upstream backend_google { server 127.0.0.1:8001; }
upstream backend_baidu { server 127.0.0.1:8002; }
upstream backend_wechat { server 127.0.0.1:8003; }
 
server {
    listen 80;
    server_name example.com;
 
    location / {
        proxy_pass http://$backend;
    }
}

📚 相关链接


相关笔记