Nginx 虚拟主机配置
Virtual Host Configuration
概述
虚拟主机允许在单个服务器上托管多个网站或应用程序。Nginx提供了灵活强大的虚拟主机配置功能,支持基于域名、IP地址和端口的虚拟主机。本文将详细介绍各种虚拟主机配置方法。
1. 虚拟主机基础概念
1.1 虚拟主机类型
虚拟主机类型:
├── 基于域名 (Name-based)
│ ├── 单域名
│ ├── 多域名
│ └── 通配符域名
├── 基于IP (IP-based)
├── 基于端口 (Port-based)
└── 混合模式
1.2 配置文件组织结构
/etc/nginx/
├── nginx.conf # 主配置文件
├── sites-available/ # 可用站点配置
│ ├── default
│ ├── example.com
│ ├── blog.example.com
│ └── api.example.com
├── sites-enabled/ # 启用站点配置(符号链接)
│ ├── default -> ../sites-available/default
│ └── example.com -> ../sites-available/example.com
└── conf.d/ # 其他配置文件
└── ssl-params.conf
2. 基于域名的虚拟主机
2.1 单域名配置
# /etc/nginx/sites-available/example.com
server {
listen 80;
listen [::]:80;
server_name example.com;
root /var/www/example.com;
index index.html index.htm index.php;
# 日志配置
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
location / {
try_files $uri $uri/ =404;
}
# PHP支持
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# 静态文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# 安全配置
location ~ /\.ht {
deny all;
}
}
2.2 多域名配置
# 主域名和www域名
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
# 多个不同域名指向同一内容
server {
listen 80;
server_name example.com example.net example.org;
root /var/www/shared;
location / {
try_files $uri $uri/ =404;
}
}
2.3 子域名配置
# 博客子域名
server {
listen 80;
server_name blog.example.com;
root /var/www/blog;
index index.html index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
# API子域名
server {
listen 80;
server_name api.example.com;
# API通常代理到后端服务
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}
2.4 通配符域名配置
# 通配符子域名
server {
listen 80;
server_name *.example.com;
# 使用正则捕获子域名
if ($host ~* ^([^.]+)\.example\.com$) {
set $subdomain $1;
}
root /var/www/subdomains/$subdomain;
# 如果目录不存在,重定向到主站
location / {
try_files $uri $uri/ @fallback;
}
location @fallback {
return 301 http://example.com$request_uri;
}
}
# 使用正则表达式的域名匹配
server {
listen 80;
server_name ~^(?<user>\w+)\.example\.com$;
root /var/www/users/$user;
# 为每个用户创建独立的日志
access_log /var/log/nginx/users/$user.access.log;
error_log /var/log/nginx/users/$user.error.log;
location / {
try_files $uri $uri/ =404;
}
}
3. 基于IP的虚拟主机
3.1 多IP配置
# IP 192.168.1.10的虚拟主机
server {
listen 192.168.1.10:80;
server_name _;
root /var/www/site1;
location / {
try_files $uri $uri/ =404;
}
}
# IP 192.168.1.11的虚拟主机
server {
listen 192.168.1.11:80;
server_name _;
root /var/www/site2;
location / {
try_files $uri $uri/ =404;
}
}
3.2 IPv6支持
server {
# 同时监听IPv4和IPv6
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
# IPv6特定配置
location / {
# 记录客户端IP类型
set $ip_version "IPv4";
if ($remote_addr ~* "^([0-9a-f]*:){2,}") {
set $ip_version "IPv6";
}
add_header X-IP-Version $ip_version;
try_files $uri $uri/ =404;
}
}
4. 基于端口的虚拟主机
4.1 不同端口配置
# 端口8080的虚拟主机
server {
listen 8080;
server_name example.com;
root /var/www/app1;
location / {
try_files $uri $uri/ =404;
}
}
# 端口8081的虚拟主机
server {
listen 8081;
server_name example.com;
root /var/www/app2;
location / {
try_files $uri $uri/ =404;
}
}
# 管理接口(非标准端口)
server {
listen 9000;
server_name admin.example.com;
# 限制访问来源
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
5. HTTPS虚拟主机配置
5.1 SSL证书配置
# HTTPS虚拟主机
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
# 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-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
root /var/www/example.com;
index index.html index.php;
location / {
try_files $uri $uri/ =404;
}
}
# HTTP重定向到HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
5.2 多域名SSL配置
# 使用通配符证书
server {
listen 443 ssl http2;
server_name *.example.com;
ssl_certificate /etc/ssl/certs/wildcard.example.com.crt;
ssl_certificate_key /etc/ssl/private/wildcard.example.com.key;
# 根据子域名路由
set $subdomain "";
if ($host ~* ^([^.]+)\.example\.com$) {
set $subdomain $1;
}
location / {
if ($subdomain = "api") {
proxy_pass http://api-backend;
break;
}
if ($subdomain = "blog") {
root /var/www/blog;
try_files $uri $uri/ /index.php?$query_string;
break;
}
# 默认处理
root /var/www/default;
try_files $uri $uri/ =404;
}
}
6. 默认虚拟主机配置
6.1 默认服务器配置
# 默认虚拟主机(捕获所有未匹配的请求)
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# 默认拒绝访问或重定向
return 444; # 关闭连接
# 或者返回自定义页面
# root /var/www/default;
# location / {
# return 200 "Default server";
# add_header Content-Type text/plain;
# }
}
# HTTPS默认服务器
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name _;
# 使用自签名证书或默认证书
ssl_certificate /etc/ssl/certs/default.crt;
ssl_certificate_key /etc/ssl/private/default.key;
return 444;
}
6.2 错误处理虚拟主机
# 专门处理错误的虚拟主机
server {
listen 80;
server_name error.example.com;
root /var/www/error-pages;
location / {
internal;
try_files $uri /error.html;
}
location /error.html {
internal;
}
}
# 在其他虚拟主机中使用
server {
listen 80;
server_name example.com;
error_page 404 = @error404;
error_page 500 502 503 504 = @error50x;
location @error404 {
return 302 http://error.example.com/404;
}
location @error50x {
return 302 http://error.example.com/500;
}
}
7. 动态虚拟主机
7.1 基于目录的动态虚拟主机
server {
listen 80;
server_name ~^(?<domain>.+)$;
set $domain_path "";
if ($domain ~* ^([^.]+)\.([^.]+)\.([^.]+)$) {
set $domain_path $2.$3/$1;
}
if ($domain ~* ^([^.]+)\.([^.]+)$) {
set $domain_path $1.$2;
}
root /var/www/vhosts/$domain_path;
# 检查目录是否存在
location / {
try_files $uri $uri/ @notfound;
}
location @notfound {
return 301 http://main-site.com;
}
}
7.2 使用Lua脚本的动态虚拟主机
server {
listen 80;
server_name ~.*;
set_by_lua_block $document_root {
local host = ngx.var.host
local domain = string.gsub(host, "^www%.", "")
-- 检查域名是否在允许列表中
local allowed_domains = {
["example.com"] = "/var/www/example.com",
["test.com"] = "/var/www/test.com"
}
return allowed_domains[domain] or "/var/www/default"
}
root $document_root;
location / {
try_files $uri $uri/ =404;
}
}
8. 虚拟主机管理
8.1 站点启用和禁用
# 创建新的虚拟主机配置
sudo nano /etc/nginx/sites-available/new-site.com
# 启用站点(创建符号链接)
sudo ln -s /etc/nginx/sites-available/new-site.com /etc/nginx/sites-enabled/
# 禁用站点(删除符号链接)
sudo rm /etc/nginx/sites-enabled/new-site.com
# 测试配置
sudo nginx -t
# 重新加载配置
sudo systemctl reload nginx
8.2 批量管理脚本
#!/bin/bash
# 虚拟主机管理脚本
SITES_AVAILABLE="/etc/nginx/sites-available"
SITES_ENABLED="/etc/nginx/sites-enabled"
case "$1" in
enable)
if [ -f "$SITES_AVAILABLE/$2" ]; then
ln -s "$SITES_AVAILABLE/$2" "$SITES_ENABLED/"
echo "Site $2 enabled"
else
echo "Site $2 not found"
fi
;;
disable)
if [ -L "$SITES_ENABLED/$2" ]; then
rm "$SITES_ENABLED/$2"
echo "Site $2 disabled"
else
echo "Site $2 not enabled"
fi
;;
list)
echo "Available sites:"
ls -1 "$SITES_AVAILABLE"
echo "Enabled sites:"
ls -1 "$SITES_ENABLED"
;;
*)
echo "Usage: $0 {enable|disable|list} [site-name]"
;;
esac
# 测试配置
nginx -t && systemctl reload nginx
9. 性能优化
9.1 虚拟主机级别的优化
server {
listen 80;
server_name example.com;
# 单独的工作进程
# 注意:这需要在http块中配置
# 连接保持优化
keepalive_timeout 65;
keepalive_requests 1000;
# 压缩配置
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/javascript
application/xml+rss
application/json;
# 缓冲区优化
client_body_buffer_size 128k;
client_max_body_size 50m;
location / {
# 开启sendfile
sendfile on;
tcp_nopush on;
tcp_nodelay on;
try_files $uri $uri/ =404;
}
}
9.2 资源限制
http {
# 限制每个IP的连接数
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
# 限制每个服务器名的连接数
limit_conn_zone $server_name zone=conn_limit_per_server:10m;
server {
listen 80;
server_name example.com;
# 应用连接限制
limit_conn conn_limit_per_ip 10;
limit_conn conn_limit_per_server 100;
# 请求频率限制
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=5r/s;
limit_req zone=req_limit burst=10 nodelay;
location / {
try_files $uri $uri/ =404;
}
}
}
10. 故障排除
10.1 常见问题诊断
# 检查虚拟主机配置
nginx -T | grep -A 20 "server_name example.com"
# 测试域名解析
nslookup example.com
dig example.com
# 检查端口监听
netstat -tulpn | grep :80
ss -tulpn | grep :80
# 测试虚拟主机
curl -H "Host: example.com" http://localhost/
curl -I http://example.com/
10.2 日志分析
# 查看特定虚拟主机的日志
tail -f /var/log/nginx/example.com.access.log
# 分析错误日志
grep "example.com" /var/log/nginx/error.log
# 统计访问量
awk '{print $1}' /var/log/nginx/example.com.access.log | sort | uniq -c | sort -nr
小结
通过本文的学习,你应该掌握:
- 不同类型虚拟主机的配置方法
- 域名、IP和端口的虚拟主机配置
- HTTPS虚拟主机的配置技巧
- 动态虚拟主机的实现方法
- 虚拟主机的管理和优化
- 常见问题的诊断和解决
下一篇文章将介绍Nginx的日志配置与管理。