Nginx 基础 Web 服务配置
Web 服务是 Nginx 最基础也是最重要的功能之一。无论是托管静态网站、提供 API 服务,还是作为反向代理,都离不开基础 Web 服务配置。
介绍 Nginx 基础 Web 服务配置,涵盖静态资源托管(root 与 alias 区别、缓存优化)、多虚拟主机配置(基于域名、端口、IP)、URL 匹配规则(优先级、正则)、默认及错误页面设置、基础安全配置(访问控制、请求限制)以及常见面试题。内容旨在帮助开发者掌握 Nginx 在 Web 服务中的核心应用与性能优化技巧。

Web 服务是 Nginx 最基础也是最重要的功能之一。无论是托管静态网站、提供 API 服务,还是作为反向代理,都离不开基础 Web 服务配置。
静态资源托管是 Nginx 的核心功能之一,包括 HTML、CSS、JavaScript、图片、视频等各种静态文件的提供。
server {
listen 80;
server_name example.com;
# 基础静态资源托管
location / {
root /var/www/html;
index index.html index.htm;
}
}
这是初学者最容易混淆的概念,以下是区别示例:
# root 指令 - 将请求路径附加到根目录后面
server {
listen 80;
server_name example.com;
location /static/ {
root /var/www;
# 请求 /static/images/logo.png
# 实际访问 /var/www/static/images/logo.png
}
}
# alias 指令 - 将 location 路径替换为指定目录
server {
listen 80;
server_name example.com;
location /static/ {
alias /var/www/images/;
# 请求 /static/images/logo.png
# 实际访问 /var/www/images/images/logo.png
# 如果想访问 /var/www/images/logo.png,应该这样配置:
# alias /var/www/images;
}
location /css/ {
alias /var/www/stylesheets/;
# 请求 /css/main.css
# 实际访问 /var/www/stylesheets/main.css
}
}
server {
listen 80;
server_name example.com;
root /var/www/html;
# HTML 页面配置
location ~* \.html$ {
expires 1h;
add_header Cache-Control "public, must-revalidate";
}
# CSS/JS 文件长期缓存
location ~* \.(css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# 图片文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|svg)$ {
expires 30d;
add_header Cache-Control "public";
}
# 字体文件配置
location ~* \.(woff|woff2|ttf|eot)$ {
expires 1y;
add_header Access-Control-Allow-Origin *;
add_header Cache-Control "public";
}
# 防止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
server {
listen 80;
server_name example.com;
root /var/www/html;
# 启用 sendfile,提高文件传输效率
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# 文件缓冲区优化
location / {
# 客户端请求体缓冲区
client_body_buffer_size 128k;
# 代理缓冲区配置
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
# 文件缓存配置
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}
}
虚拟主机(Virtual Host)允许一台物理服务器托管多个网站,通过域名或端口区分不同的网站。这是现代 Web 服务的基础架构。
# 虚拟主机 1 - 主站
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;
error_log /var/log/nginx/example.com.error.log;
location / {
try_files $uri $uri/ =404;
}
}
# 虚拟主机 2 - 博客
server {
listen 80;
server_name blog.example.com;
root /var/www/blog.example.com;
index index.php index.html;
access_log /var/log/nginx/blog.example.com.access.log;
error_log /var/log/nginx/blog.example.com.error.log;
# PHP 处理
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
# 虚拟主机 3 - API 服务
server {
listen 80;
server_name api.example.com;
root /var/www/api.example.com;
# API 专用日志格式
log_format api_json escape=json '{' '"time": "$time_iso8601",' '"remote_addr": "$remote_addr",' '"method": "$request_method",' '"url": "$uri",' '"status": "$status",' '"response_time": "$request_time"' '}';
access_log /var/log/nginx/api.example.com.access.log api_json;
# API 特定配置
location / {
proxy_pass http://api_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
# 端口 1 - 开发环境
server {
listen 8080;
server_name localhost;
root /var/www/dev;
index index.html;
}
# 端口 2 - 测试环境
server {
listen 8081;
server_name localhost;
root /var/www/test;
index index.html;
}
# 端口 3 - 预发布环境
server {
listen 8082;
server_name localhost;
root /var/www/staging;
index index.html;
}
# 服务器有多个 IP 地址的情况
server {
listen 192.168.1.100:80;
server_name example1.com;
root /var/www/site1;
}
server {
listen 192.168.1.101:80;
server_name example2.com;
root /var/www/site2;
}
# HTTP 到 HTTPS 重定向
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
# www 到非 www 重定向
server {
listen 80;
server_name www.example.com;
return 301 http://example.com$request_uri;
}
# 非 www 到 www 重定向
server {
listen 80;
server_name example.com;
return 301 http://www.example.com$request_uri;
}
# 多域名统一重定向
server {
listen 80;
server_name oldsite.com old.example.com;
return 301 http://newsite.com$request_uri;
}
Nginx 的 URL 匹配遵循严格的优先级规则,理解这些规则对于正确配置至关重要:
server {
listen 80;
server_name example.com;
root /var/www/html;
# 1. 精确匹配 (=) - 优先级最高
location = /login {
# 只匹配 /login
return 200 "This is login page";
}
# 2. 最长前缀匹配 (^~) - 阻止正则匹配
location ^~ /images/ {
# 匹配 /images/ 开头的所有路径
# 不会继续匹配下面的正则表达式
root /var/www/images;
}
# 3. 正则匹配 (~ 和 ~*) - 按配置顺序
location ~* \.(jpg|jpeg|png|gif)$ {
# 匹配图片文件,不区分大小写
expires 30d;
}
# 4. 普通前缀匹配 - 最长匹配原则
location /admin/ {
# 匹配 /admin/ 开头的路径
root /var/www/admin;
}
# 5. 通用匹配
location / {
# 匹配所有其他路径
index index.html;
}
}
server {
listen 80;
server_name example.com;
root /var/www/html;
# API 版本控制
location ^~ /api/v1/ {
proxy_pass http://api_v1_backend/;
}
location ^~ /api/v2/ {
proxy_pass http://api_v2_backend/;
}
# 静态资源
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# 管理后台
location /admin {
# 需要身份验证
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
root /var/www/admin;
}
# 上传文件限制
location /upload {
# 限制文件大小
client_max_body_size 10M;
# 限制上传类型
location ~* \.(php|pl|py|jsp|asp|sh|cgi)$ {
deny all;
}
}
# 默认页面
location / {
try_files $uri $uri/ /index.html;
}
}
server {
listen 80;
server_name example.com;
root /var/www/html;
# 多条件匹配
location ~* "^/download/(.+)\\(pdf|doc|docx|xls|xlsx)$" {
# 匹配下载链接,设置下载头
add_header Content-Disposition "attachment; filename=$1.$2";
expires 1h;
}
# 版本号处理
location ~* "^/assets/([a-fA-F0-9]{8})/(.*)$" {
# 处理带版本号的静态资源
alias /var/www/assets/$2;
expires 1y;
add_header Cache-Control "public, immutable";
}
# 移动端适配
location / {
set $mobile_rewrite do_not_perform;
if ($http_user_agent ~* "(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino") {
set $mobile_rewrite perform;
}
if ($mobile_rewrite = perform) {
rewrite ^(.+)$ /mobile$1 last;
}
try_files $uri $uri/ /index.html;
}
}
server {
listen 80;
server_name example.com;
root /var/www/html;
# 多个默认页面,按优先级排列
index index.html index.htm index.php welcome.html;
# SPA 应用的 fallback 配置
location / {
try_files $uri $uri/ @fallback;
}
# SPA fallback 规则
location @fallback {
rewrite ^.*$ /index.html last;
}
# 目录列表
location /files/ {
autoindex on;
autoindex_exact_size off; # 显示文件大小(KB,MB,GB)
autoindex_localtime on; # 显示本地时间
}
}
server {
listen 80;
server_name example.com;
root /var/www/html;
# 自定义错误页面
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
# 错误页面的具体处理
location = /404.html {
root /var/www/error_pages;
internal; # 只能内部重定向访问
}
location = /50x.html {
root /var/www/error_pages;
internal;
}
# API 错误返回 JSON 格式
location ^~ /api/ {
error_page 404 = @api_404;
error_page 500 502 503 504 = @api_50x;
}
location @api_404 {
add_header Content-Type application/json;
return 200 '{"error": "Resource not found", "code": 404}';
}
location @api_50x {
add_header Content-Type application/json;
return 200 '{"error": "Internal server error", "code": 500}';
}
}
server {
listen 80;
server_name example.com;
root /var/www/html;
# 自定义访问日志格式
log_format detailed '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' 'rt=$request_time uct="$upstream_connect_time" ' 'uht="$upstream_header_time" urt="$upstream_response_time" ' 'cache="$upstream_cache_status"';
# 访问日志
access_log /var/log/nginx/example.access.log detailed;
# 错误日志
error_log /var/log/nginx/example.error.log warn;
# 不记录静态资源访问日志
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
access_log off;
expires 1y;
}
# 记录 API 访问日志
location ^~ /api/ {
access_log /var/log/nginx/api.access.log detailed;
# API 处理逻辑
}
}
server {
listen 80;
server_name example.com;
root /var/www/html;
# 隐藏 Nginx 版本号
server_tokens off;
# 安全头配置
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
# 防止访问敏感文件
location ~* \.(htaccess|htpasswd|ini|log|sh|sql|conf)$ {
deny all;
return 404;
}
# 限制请求方法
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 405;
}
}
server {
listen 80;
server_name example.com;
root /var/www/html;
# 基础认证
location /admin/ {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
# 认证后的页面
location ~* \.(php|pl|py|jsp|asp)$ {
# 防止执行危险脚本
deny all;
}
}
# IP 白名单
location /private/ {
allow 192.168.1.0/24;
allow 10.0.0.1;
deny all; # 白名单区域内容
}
}
# 在 http 块中定义限制区域
http {
# 限制每 IP 的连接数
limit_conn_zone $binary_remote_addr zone=per_ip:10m;
# 限制请求频率(每秒 10 个请求)
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
server {
listen 80;
server_name example.com;
root /var/www/html;
# 应用连接限制
limit_conn per_ip 10;
# 应用请求频率限制
limit_req zone=general burst=20 nodelay;
# 特定路径的限制
location /login {
limit_req zone=general burst=5 nodelay; # 登录页面限制更严格
}
}
}
| 配置项 | 用途 | 推荐值 | 说明 |
|---|---|---|---|
| sendfile | 零拷贝传输 | on | 提高文件传输效率 |
| tcp_nopush | TCP 优化 | on | 优化数据包发送 |
| expires | 缓存时间 | 1h/1d/1y | 根据文件类型设置 |
| gzip | 压缩传输 | on | 减少传输数据量 |
| 类型 | 配置方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 基于域名 | server_name | 简单易懂 | 需要 DNS 配置 | 多网站 |
| 基于端口 | listen port | 不需 DNS | 用户体验差 | 测试环境 |
| 基于 IP | listen ip | 隔离性强 | 需要多 IP | 高安全性 |
| 优先级 | 修饰符 | 匹配类型 | 性能 | 说明 |
|---|---|---|---|---|
| 1 | = | 精确匹配 | 最快 | 优先级最高 |
| 2 | ^~ | 最长前缀 | 快 | 阻止正则匹配 |
| 3 | ~ | 正则匹配 | 中等 | 区分大小写 |
| 4 | ~* | 正则匹配 | 中等 | 不区分大小写 |
| 5 | (none) | 普通前缀 | 快 | 最长匹配原则 |

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online