精通 Nginx 配置:核心指令详解

理解你最常用的 Nginx 指令:http、server、location、proxy_pass、try_files、gzip、TLS 以及服务重载。

掌握 Nginx 配置:核心指令详解

一旦你理解了每条指令允许出现的位置,Nginx 配置就会变得容易得多。如果你的 proxy_passroottry_files 规则放错了上下文,Nginx 可能会拒绝配置,或者以你意想不到的方式处理请求。

本指南将带你了解在提供静态文件、反向代理应用、启用压缩以及安全重载更改时,你会用到的核心指令。

Nginx 配置结构

在 Linux 发行版中,Nginx 配置文件通常位于 /etc/nginx/ 目录下。主文件通常是 /etc/nginx/nginx.conf,它通常会包含来自 /etc/nginx/conf.d/ 的文件。Debian 和 Ubuntu 发行版通常使用 sites-available/sites-enabled/ 目录;许多其他发行版则不使用。

配置是分层的,组织成指令。关键的块包括:

  • events:配置连接处理。
  • http:包含 HTTP 范围的设置和虚拟服务器。
  • server:为某个端口和主机名定义一个虚拟服务器。
  • location:选择如何处理匹配的请求 URI。

指令是控制 Nginx 行为的键值对。它们可以是全局的,也可以嵌套在块内。

核心指令详解

http

http 块包含全局应用于 HTTP 流量的配置。你将在此处定义 Web 服务器的通用设置。

  • include:此指令允许你包含其他配置文件,有助于模块化你的设置。它通常用于分离不同网站或应用程序的配置。

    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        # 从 conf.d 目录包含服务器配置
        include /etc/nginx/conf.d/*.conf;
    }
    
  • log_format:为 Nginx 访问和错误日志定义自定义日志格式。这对于详细日志记录和分析至关重要。

    http {
        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;
        error_log   /var/log/nginx/error.log;
        # ... 其他 http 指令
    }
    
  • sendfile:通过允许内核直接从磁盘向客户端发送文件,绕过用户空间,从而优化文件传输。为了性能,设置为 on

    http {
        sendfile        on;
        # ...
    }
    
  • tcp_nopushtcp_nodelay:这些指令调整 HTTP 响应的 TCP 行为。tcp_nopush 通常与 sendfile 一起使用以优化数据包发送,而 tcp_nodelay 有助于避免 keepalive 连接上的延迟。

    http {
        tcp_nopush     on;
        tcp_nodelay    on;
        # ...
    }
    

server

每个 server 块定义一个虚拟服务器,允许 Nginx 在同一台服务器上处理针对不同域名或 IP 地址的请求。

  • listen:指定服务器将监听传入连接的 IP 地址和/或端口。

    server {
        listen 80;
        listen [::]:80;
        server_name example.com www.example.com;
        # ...
    }
    
  • server_name:定义服务器的名称。Nginx 使用它来匹配传入请求的 Host 头。

    server {
        listen 80;
        server_name mydomain.org *.mydomain.org;
        # ...
    }
    
  • root:设置文档根目录。Nginx 通过将请求 URI 附加到此目录来构建文件路径。

    server {
        listen 80;
        server_name localhost;
        root /var/www/html;
        index index.html index.htm;
        # ...
    }
    
  • index:指定请求目录时要提供的默认文件。

    server {
        # ...
        index index.html index.htm default.html;
        # ...
    }
    
  • error_page:为特定的 HTTP 状态码定义自定义错误页面。

    server {
        # ...
        error_page 404 /404.html;
        location = /404.html {
            root /usr/share/nginx/html;
            internal;
        }
        # ...
    }
    

location

location 块用于匹配请求 URI,并决定 Nginx 如何处理它们。你可以在此处为应用程序的不同部分配置路由。

  • 匹配 URI:Location 可以匹配精确字符串、前缀或正则表达式。精确匹配使用 =,正则表达式使用 ~~*,普通前缀按 URI 前缀匹配。

    location /images/ {
        # 针对以 /images/ 开头的请求的指令
    }
    
    location = /favicon.ico {
        # 精确匹配 /favicon.ico
    }
    
    location ~ \.php$ {
        # 正则匹配以 .php 结尾的文件
    }
    
  • proxy_pass:将请求转发到上游服务器。注意尾部斜杠,因为它会改变 Nginx 重写匹配前缀的方式。

    location /api/ {
        proxy_pass http://backend-service:8080/;
        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;
    }
    
  • alias:将 location 映射到文件系统路径,而不附加完整的原始 URI。它通常用于存储在主文档根目录之外的静态资源。

    location /static/ {
        alias /var/www/app/assets/;
    }
    

    使用 alias 时,对于目录映射,请确保 location 和路径都包含尾部斜杠。alias 将匹配的 location 前缀替换为别名路径,而 root 则将 URI 附加到根路径。

  • try_files:按指定顺序检查文件是否存在,并提供找到的第一个文件,或者返回指定的代码/URI。

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

    这对于单页应用程序很常见。如果请求的文件或目录不存在,Nginx 将提供 index.html,以便客户端路由器可以处理该路径。

安全与性能指令

  • ssl_certificatessl_certificate_key:配置 HTTPS 所必需的。这些指令指向你的 SSL 证书和私钥文件。

    server {
        listen 443 ssl;
        server_name secure.example.com;
    
        ssl_certificate /etc/letsencrypt/live/secure.example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/secure.example.com/privkey.pem;
    
        # ... 其他 SSL 设置
    }
    
  • gzip:为选定的响应类型启用或禁用 gzip 压缩。它通常可以减少文本资源的传输大小,但应避免压缩已经压缩过的文件,例如大多数图片。

    http {
        gzip on;
        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
        # ...
    }
    
  • expires:控制静态资源的缓存头。对于带有指纹的文件,使用较长的缓存生命周期;对于在部署之间保持相同 URL 的文件,使用较短的生命周期。

    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 30d;
        add_header Cache-Control "public";
    }
    

常用 Nginx 命令

为了管理 Nginx 并应用配置更改,你会经常使用以下命令:

  • 测试配置:检查 Nginx 配置文件中是否存在语法错误。

    sudo nginx -t
    
  • 重载配置:优雅地重载 Nginx 配置,而不会断开活动连接。

    sudo systemctl reload nginx
    # 或
    sudo service nginx reload
    
  • 重启 Nginx:停止然后启动 Nginx 服务。

    sudo systemctl restart nginx
    # 或
    sudo service nginx restart
    
  • 检查状态:显示 Nginx 服务的当前状态。

    sudo systemctl status nginx
    # 或
    sudo service nginx status
    

一个最小的工作示例

此示例从磁盘提供单页应用,并将 API 请求代理到应用服务器:

server {
    listen 80;
    server_name example.com;

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

    location /api/ {
        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;
    }

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

每次重载前运行 sudo nginx -t。这一个习惯可以在语法错误导致停机之前捕获它们。

要点

大多数 Nginx 错误源于上下文和路径处理。将 HTTP 范围的设置放在 http 中,主机特定的规则放在 server 中,URI 路由放在 location 中,并在重载前使用 nginx -t 测试每个更改。