Nginx 虚拟主机:在一台服务器上托管多个网站

利用 Nginx 虚拟主机(server blocks)的强大功能,在单台服务器上高效托管多个网站或子域名。本指南提供了一个全面的分步教程,涵盖目录设置、配置文件创建、启用服务器块以及 Nginx 测试。学习子域名、默认服务器块、HTTPS 集成和专用日志记录的最佳实践。实用的示例和必要的故障排除技巧将帮助您掌握多站点 Nginx 托管,优化资源使用并简化 Web 服务器管理。

35 浏览量

Nginx 虚拟主机:在单个服务器上托管多个网站

现代的 Web 基础设施通常需要能够在单个服务器实例上提供多个网站或 Web 应用程序。这不仅优化了资源利用率,还简化了管理并降低了运营成本。Nginx 以其高性能、稳定性、丰富的功能集和低资源消耗而闻名,它通过其所谓的 服务器块 (server blocks) 来实现这一目标,这在 Apache 世界中通常被称为 虚拟主机 (virtual hosts)

本综合指南将引导您完成设置 Nginx 虚拟主机的过程,以有效地从单个 Nginx 服务器管理和提供多个不同的域名或子域名。无论您是托管 example.comanothersite.org,还是一个主站点带有 blog.example.comshop.example.com 等子域名,掌握 Nginx 服务器块都是任何系统管理员或开发人员的基本技能。在本文结束时,您将对如何配置 Nginx 服务器进行多站点托管有清晰的理解和实际示例。

理解 Nginx 服务器块(虚拟主机)

核心上,Nginx 的 服务器块 (server block) 是 Nginx 配置文件(nginx.conf 或包含的文件)中定义的一个配置指令。每个 server 块定义了一个特定虚拟主机的配置,指示 Nginx 如何响应对特定域或一组域的请求。Nginx 使用 listen 指令指定它应该监听的 IP 地址和端口,并使用 server_name 指令识别此服务器块应该响应的域名或主机名。

当请求到来时,Nginx 检查 HTTP 请求的 Host 头,并将其与配置的服务器块的 server_name 指令进行比较。然后,它提供匹配的服务器块中定义的内容。如果没有 server_name 匹配,Nginx 通常会回退到 默认服务器块 (default server block)(第一个 server 块或明确标记为 default_server 的块)。

先决条件

在开始之前,请确保您具备以下条件:

  1. Nginx 已安装:Nginx 应该已安装并在您的服务器上运行。如果尚未安装,您通常可以通过系统的包管理器进行安装(例如,在 Ubuntu/Debian 上使用 sudo apt update && sudo apt install nginx,在 CentOS/RHEL 上使用 sudo yum install nginx)。
  2. 域名:您需要至少两个要托管的域名(例如 example1.comexample2.com)或子域名(例如 blog.example.comapp.example.com)。这些域名的 DNS A/AAAA 记录必须指向您服务器的公共 IP 地址。
  3. 基本目录结构:您的网站文件将存放在何处。常见的做法是 /var/www/yourdomain.com/html
  4. Sudo 权限:您将需要 sudo 访问权限来修改 Nginx 配置文件。

分步设置指南

让我们设置两个虚拟主机:example1.comexample2.com

1. 为网站创建目录结构

首先,为您的每个网站创建根目录。HTML、CSS、JavaScript 和其他静态文件将存储在此处。一个常见的存放位置是 /var/www/

sudo mkdir -p /var/www/example1.com/html
sudo mkdir -p /var/www/example2.com/html

# 设置文件所有权给你的用户(将 $USER 替换为你的用户名),以便允许编辑
sudo chown -R $USER:$USER /var/www/example1.com/html
sudo chown -R $USER:$USER /var/www/example2.com/html

# 为 Web 服务器设置读取权限
sudo chmod -R 755 /var/www

接下来,在每个目录中创建一个简单的 index.html 文件来测试设置:

对于 /var/www/example1.com/html/index.html

<!-- /var/www/example1.com/html/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>欢迎访问 Example1.com!</title>
</head>
<body>
    <h1>成功!这是 Example1.com。</h1>
    <p>此虚拟主机正常工作。</p>
</body>
</html>

对于 /var/www/example2.com/html/index.html

<!-- /var/www/example2.com/html/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>欢迎访问 Example2.com!</title>
</head>
<body>
    <h1>成功!这是 Example2.com。</h1>
    <p>此虚拟主机也正常工作!</p>
</body>
</html>

2. 创建 Nginx 服务器块配置文件

Nginx 通常从 /etc/nginx/sites-enabled/ 目录中的文件加载服务器块配置。这些文件通常是 /etc/nginx/sites-available/ 中存储的配置的符号链接。这种分离允许您存储尚未激活的配置,或轻松启用/禁用站点。

example1.com 创建一个新的配置文件:

sudo nano /etc/nginx/sites-available/example1.com.conf

添加以下内容:

# /etc/nginx/sites-available/example1.com.conf
server {
    listen 80;
    listen [::]:80;

    root /var/www/example1.com/html;
    index index.html index.htm index.nginx-debian.html;

    server_name example1.com www.example1.com;

    location / {
        try_files $uri $uri/ =404;
    }

    access_log /var/log/nginx/example1.com_access.log;
    error_log /var/log/nginx/example1.com_error.log;
}

指令说明:

  • listen 80;:Nginx 监听端口 80(标准 HTTP)。listen [::]:80; 用于 IPv6。
  • root /var/www/example1.com/html;:指定此服务器块的文档根目录。Nginx 将在此目录中查找文件。
  • index index.html ...;:定义当请求目录时(例如,当有人访问 example1.com/ 时)Nginx 应该提供的默认文件。
  • server_name example1.com www.example1.com;:这至关重要。它告诉 Nginx 使用此服务器块的配置来响应对 example1.comwww.example1.com 的请求。
  • location / { ... }:一个定义如何处理特定 URI 请求的块。try_files 尝试直接提供文件($uri),然后是目录($uri/),最后返回 404 Not Found 错误。
  • access_logerror_log:为此特定站点指定单独的日志文件,这是为了更轻松地调试和分析的良好实践。

现在,为 example2.com 创建一个类似的配置文件:

sudo nano /etc/nginx/sites-available/example2.com.conf

添加以下内容:

# /etc/nginx/sites-available/example2.com.conf
server {
    listen 80;
    listen [::]:80;

    root /var/www/example2.com/html;
    index index.html index.htm index.nginx-debian.html;

    server_name example2.com www.example2.com;

    location / {
        try_files $uri $uri/ =404;
    }

    access_log /var/log/nginx/example2.com_access.log;
    error_log /var/log/nginx/example2.com_error.log;
}

3. 启用服务器块

要启用这些配置,请从 sites-available 目录创建到 sites-enabled 目录的符号链接。这会告诉 Nginx 在启动时包含这些文件。

sudo ln -s /etc/nginx/sites-available/example1.com.conf /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/example2.com.conf /etc/nginx/sites-enabled/

4. 测试 Nginx 配置

在重新加载之前测试 Nginx 配置是否存在语法错误至关重要。这可以防止 Nginx 因拼写错误而无法重新启动。

sudo nginx -t

您应该会看到类似以下的输出,表示成功:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

如果看到任何错误,请在相应的配置文件中修复它们,并重新运行 sudo nginx -t,直到通过。

5. 重启 Nginx

通过重新启动或重新加载 Nginx 来应用新配置。通常更推荐使用 reload,因为它允许 Nginx 在不中断活动连接的情况下加载新配置。

sudo systemctl reload nginx
# 或者,如果 reload 不起作用或对于全新安装:
sudo systemctl restart nginx

6. 更新 DNS 记录

确保 example1.comwww.example1.comexample2.comwww.example2.com 的 DNS A 记录都指向您的 Nginx 服务器的 IP 地址。如果没有正确的 DNS 条目,您的浏览器将不知道在哪里找到您的网站。

一旦 DNS 传播完成(可能需要几分钟到几个小时),您应该能够在 Web 浏览器中访问 http://example1.comhttp://example2.com,并看到各自的 index.html 页面。

高级场景和最佳实践

托管子域名

托管子域名(例如 blog.example.comshop.example.com)的工作方式与托管单独的域名完全相同。您只需使用子域名作为 server_name 定义一个新的服务器块。

blog.example.com 的示例:

# /etc/nginx/sites-available/blog.example.com.conf
server {
    listen 80;
    listen [::]:80;

    root /var/www/blog.example.com/html;
    index index.html;

    server_name blog.example.com;

    location / {
        try_files $uri $uri/ =404;
    }
}

请记住创建目录(/var/www/blog.example.com/html)、创建 index.html、创建符号链接并重新加载 Nginx。

默认服务器块

最好有一个默认服务器块,用于捕获服务器上与任何其他 server_name 指令不匹配的域名请求。这可以防止未知请求被 Nginx 找到的“第一个”虚拟主机服务,或者允许您提供一个通用的“找不到站点”页面。

通常,nginx.confsites-enabled 中的第一个 server 块隐式地是默认块。您可以使用 default_server 明确设置一个:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;
    # 下划线 `_` 是一个不存在的域名,永远不会匹配真实的请求。
    # 您也可以使用 localhost。

    root /var/www/default_site/html;
    index index.html;

    location / {
        return 444; # 对未知主机返回 Nginx 特定的 444 错误(无响应)
        # 或者,提供一个通用的着陆页:
        # try_files $uri $uri/ =404;
    }
}

警告:如果您定义了 default_server 块,请确保给定 listen 端口上只有一个 server 块带有 default_server 标志,否则 Nginx 将记录警告。

使用 HTTPS (SSL/TLS) 保护虚拟主机

对于生产网站,启用 HTTPS 是必不可少的。这涉及到获取 SSL/TLS 证书(例如,通过使用 Certbot 的 Let's Encrypt)并配置 Nginx 在端口 443 上监听并使用该证书。

一个典型的 HTTPS 服务器块看起来像这样(在获取证书后):

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

    server_name example1.com www.example1.com;

    root /var/www/example1.com/html;
    index index.html;

    ssl_certificate /etc/letsencrypt/live/example1.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example1.com/privkey.pem;

    # 包含其他 SSL 配置(密码、协议等)
    include /etc/nginx/snippets/ssl-params.conf;
    include /etc/nginx/snippets/force-ssl.conf; # 可选:将 HTTP 重定向到 HTTPS

    location / {
        try_files $uri $uri/ =404;
    }
}

# 可选:将此域的 HTTP 重定向到 HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name example1.com www.example1.com;
    return 301 https://$host$request_uri;
}

通常会有一个单独的 HTTP 服务器块,其唯一目的是将所有流量重定向到其 HTTPS 对应项。

每个站点的日志记录

如示例所示,为每个虚拟主机分配单独的 access_logerror_log 文件是最佳实践。这使得调试问题和分析各个网站的流量变得更容易,而无需筛选组合日志。

配置文件结构

对于大型部署,请考虑按以下方式组织 Nginx 配置文件:

  • nginx.conf:主配置,包含 conf.d/*.confsites-enabled/*
  • conf.d/:通用服务器范围设置(例如 Gzip、缓存)。
  • snippets/:可重用的 Nginx 配置片段(例如 SSL 参数、通用 location 块)。
  • sites-available/:每个网站的独立 server 块。
  • sites-enabled/:指向 sites-available/ 中活动配置的符号链接。

常见问题排查

  • 403 Forbidden 错误:这通常意味着 Nginx 没有您网站文件或目录的读取权限。请仔细检查文件和目录权限(例如,sudo chmod -R 755 /var/www/yourdomain.com/html 并确保 Nginx 用户,通常是 www-datanginx,可以读取它们)。
  • 404 Not Found 错误:验证服务器块中的 root 指令是否指向正确的目录,以及您的 index.html 文件是否存在于该位置。另外,请确保 try_files 配置正确。
  • 加载了错误的网站:这通常表示 server_name 指令存在问题。确保 server_name 与您尝试访问的域名(包括 www. 或子域名)完全匹配。另外,请检查您的 DNS 记录。
  • Nginx 无法启动/重新加载:在尝试重新加载或重新启动 Nginx 之前,请始终使用 sudo nginx -t 测试您的配置。错误消息将指出发生语法错误的行和文件。
  • DNS 问题:如果您可以通过 IP 地址访问您的网站,但不能通过域名访问,那几乎肯定是 DNS 问题。使用 dignslookup 验证您的域名的 A 记录是否指向正确的服务器 IP。

结论

Nginx 虚拟主机(服务器块)提供了一种强大而灵活的方式,可以在单个服务器上托管多个网站。通过使用适当的 listenserver_namerootlocation 指令正确配置 server 块,您可以有效地管理各种 Web 资产。这种方法不仅节省了资源,还集中了服务器管理。

凭借本指南中概述的基础知识和实践步骤,您现在已能够设置和管理 Nginx 服务器上的多个域。请记住,始终测试您的配置,使用 HTTPS 保护您的站点,并遵循日志记录和目录结构的最佳实践,以构建健壮且可维护的 Web 环境。从这里开始,您可以进一步探索 Nginx 的功能,如反向代理、负载均衡和缓存,以增强您的 Web 服务器的性能和可靠性。