Skip to content

Nginx 动静分离·虚拟主机·HTTPS·多前端

涵盖动静分离、虚拟主机、HTTPS 站点与同一实例部署多前端等场景。


一、动静分离

在 Nginx 中实现动静分离,是通过配置将动态请求(如需要后端服务器处理的 PHP、Java 等请求)和静态资源(如 HTML、CSS、JS、图片等)分开处理,从而提高服务器性能、减轻后端压力

原理

  • 转发动态请求:由 Nginx 转发到后端应用服务器(如 Tomcat、PHP-FPM、Node.js 等)处理,再将结果返回给客户端。
  • 处理静态资源:由 Nginx 直接处理并返回(Nginx 处理静态资源效率极高)。

实现动静分离

修改 nginx.conf 配置文件

shell
# vim /etc/nginx/nginx.conf

server {
    listen 80;
    server_name example.com;  # 域名或服务器 IP

    # 访问日志(可选)
    access_log /var/log/nginx/example_access.log;
    error_log /var/log/nginx/example_error.log;

    # 图片/字体 静态资源处理:匹配静态文件后缀
    location ~* \.(html|htm|css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
        root /usr/share/nginx/static;  # 静态资源根目录
        expires 1d;  # 缓存时间(1天),减少重复请求
        add_header Cache-Control "public, max-age=86400";  # HTTP 缓存头
        try_files $uri =404;  # 找不到文件返回 404
    }
    
    # html 静态资源处理:匹配 /page/
    location /page {
        root /usr/share/nginx/static; # 实际地址:/usr/share/nginx/static/page/
        index index.html index.htm; # 默认索引文件,直接访问 /usr/share/nginx/static/page 会默认访问当前目录下的 index.html
    }

    # 动态请求处理:转发到后端服务器(当以上都没有匹配时当后端服务处理,转发到后端服务)
    location / {
        # 后端应用服务器地址
        proxy_pass http://192.168.1.200: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;
    }
}

动静分离测试

shell
# 访问静态资源(nginx 直接返回)
http://example.com/images/logo.png # 实际访问地址:/usr/share/nginx/static/images/logo.png

# 访问动态路径(转发给后端服务处理)
http://example.com/user/login # 实际访问地址:http://192.168.1.200:8080/user/login

静态资源 CDN 加速

将静态资源部署到 CDN,Nginx 配置 location 直接指向 CDN 地址

防盗链配置

防止静态资源被其他网站盗用

shell
location ~* \.(jpg|png|gif)$ {
    valid_referers none blocked example.com *.example.com;
    if ($invalid_referer) {
        return 403;  # 非法引用返回 403
    }
}

二、多虚拟主机

在 Nginx 中配置多虚拟主机(Virtual Host)通常通过基于 域名、端口 或 IP 地址 的方式实现,其中最常用的是基于域名的虚拟主机。

基于 域名 的虚拟主机

shell
# 为 www.example1.com 创建配置文件:/etc/nginx/conf.d/example1.conf
server {
    listen 80;                   # 监听端口
    server_name www.example1.com example1.com;  # 绑定的域名(多个域名用空格分隔)

    root /var/www/example1.com/html;  # 网站根目录
    index index.html index.htm;       # 默认索引文件

    # 日志配置(可选)
    access_log /var/log/nginx/example1_access.log;
    error_log /var/log/nginx/example1_error.log;

    # location 块(处理请求的规则,可选)
    location / {
        try_files $uri $uri/ =404;  # 尝试访问文件,不存在则返回 404
    }
}

# 为 www.example2.com 创建配置文件:/etc/nginx/conf.d/example2.conf
server {
    listen 80;
    server_name www.example2.com example2.com;

    root /var/www/example2.com/html;
    index index.html index.htm;

    access_log /var/log/nginx/example2_access.log;
    error_log /var/log/nginx/example2_error.log;

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

基于 端口 的虚拟主机

shell
# 为 8080端口 创建配置文件:/etc/nginx/conf.d/site8080.conf
server {
    listen 8080;  # 监听 8080 端口
    server_name _;  # 通配符(不限制域名,默认服务器)

    root /var/www/site8080/html;
    index index.html;
}

# 为 8081端口 创建配置文件:/etc/nginx/conf.d/site8081.conf
server {
    listen 8081;  # 监听 8081 端口
    server_name _; # 通配符(不限制域名,默认服务器)

    root /var/www/site8081/html;
    index index.html;
}

基于 IP 的虚拟主机

shell
# 为 192.168.1.100 创建配置文件:/etc/nginx/conf.d/192.168.1.100.conf
server {
    listen 192.168.1.100:80;
    server_name _; # 通配符(不限制域名,默认服务器)

    root /var/www/ip100/html;
}

# 为 192.168.1.101 创建配置文件:/etc/nginx/conf.d/192.168.1.101.conf
server {
    listen 192.168.1.101:80;
    server_name _; # 通配符(不限制域名,默认服务器)

    root /var/www/ip101/html;
}

注意事项

  1. 任何配置变更后,需执行 nginx -t 测试配置语法是否正确,无误后再用 systemctl reload nginx 重启服务。
  2. 直接在 conf.d/ 目录下新建 域名.conf 文件,无需修改主配置,更便于管理

三、HTTPS 站点与域名

准备域名

shell
# 从阿里云服务器购买域名、备案、解析
1. 购买域名
点击控制台 --> 域名 --> 点击域名交易 --> 可进行后缀和价格限制 -->选中要购买的域名支付即可,比如:greenp.com 

2. 域名备案
点击备案 --> 按照流程进行域名备案(阿里审核 1 ~ 3 天)(管理局审核需要13 ~ 20天) 

3. 域名解析
点击控制台 --> 域名 --> 域名列表,选中指定域名 --> 点击解析,将域名解析到指定到服务器的外网 ip 地址

准备 SSL 证书文件

  1. 方案一:获取免费证书
shell
# 通过 CentOS 安装工具生成
通过  Certbot 生成免费的 SSL 证书,步骤如下:

1. 安装工具
yum install epel-release
yum install certbot python3-certbot-nginx

2. 生成 SSL 证书
使用 Certbot 自动生成证书并配置 Web 服务器,执行
sudo certbot --nginx -d example.com -d www.example.com
# -d 后面指定域名,可添加多个(如主域名和 www 子域名)。
# 执行后会提示输入邮箱(用于证书过期提醒),同意服务条款,选择是否开启 HTTPS 重定向(推荐选择,将 HTTP 请求自动转为 HTTPS)。

3. 验证证书
证书生成后,默认存储在 /etc/letsencrypt/live/your-domain/ 目录下,包含以下文件:
fullchain.pem # 完整证书链(包含服务器证书和中间证书)
privkey.pem # 私钥文件
# 通过浏览器访问 https://your-domain,若地址栏显示小锁图标,说明证书生效。

4. 自动续期
sudo systemctl list-timers | grep certbot # 检查续期配置
sudo certbot renew --dry-run # 手动测试续期(不会实际续期,仅验证流程)

5. 手动生成自签名证书(仅测试用)
如果仅用于本地测试(不用于生产环境),可手动生成自签名证书
# 生成私钥和证书(有效期 365 天)
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/ssl/private/selfsigned.key \
  -out /etc/ssl/certs/selfsigned.crt
# 执行时需填写一些信息(如国家、域名等,可随意填写),但自签名证书在浏览器中会提示 “不安全”,不适合公网使用
# 结果
证书文件(如 domain.crt fullchain.pem)
私钥文件(如 domain.key)

6. 将证书文件上传到服务器(建议路径:/etc/nginx/ssl/,需手动创建目录)
  1. 方案二:获取付费证书
shell
# 从阿里云购买 https 免费证书
从阿里云、腾讯云等服务商购买

1. 依赖当前域名,购买 https 免费证书
搜索里输入:搜索域名 --> 点击查看域名详情 --> 点击开启SSL证书 
--> 点击个人测试证书 -->创建证书,域名填写:www.greenp.com www.greenpray.com
--> 勾选快捷签发 --> 完善信息等待审核,签发证书(大概等待 10 分钟,有短信提示)

2. 下载购买的证书
点击下载 --> 可选择不同环境 nginx 或者 apache --> 点击帮助:可查看不同环境下的配置操作
点击下载 --> 下载 nginx 版本的 https 证书包

3. 解压下载的证书文件并全部上传到服务器的 /etc/nginx/ssl/ 目录下,比如:
www.greenp.com.key
www.greenp.com.pem

配置 HTTPS

shell
# 编辑配置文件
vim /etc/nginx/conf.d/domainSSL.conf

# 内容如下
server {
    # 监听 HTTPS 端口(默认 443)
    listen 443 ssl;
    # 支持 IPv6
    listen [::]:443 ssl;

    # 绑定域名(替换为你的域名)
    server_name example.com www.example.com;

    # SSL 证书路径(替换为实际路径)
    ssl_certificate /etc/nginx/ssl/fullchain.pem;    # 证书文件
    ssl_certificate_key /etc/nginx/ssl/domain.key;    # 私钥文件

    # SSL 协议与加密套件配置(安全性优化)
    ssl_protocols TLSv1.2 TLSv1.3;  # 禁用不安全的 SSLv3、TLSv1.0、TLSv1.1
    ssl_prefer_server_ciphers on;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_session_cache shared:SSL:10m;  # 缓存 SSL 会话信息,提升性能
    ssl_session_timeout 10m;           # 会话超时时间

    # 可选:HSTS 配置(强制浏览器使用 HTTPS)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # 网站根目录(替换为实际路径)
    root /var/www/example.com;
    index index.html index.htm;

    # 其他常规配置(如日志、静态资源缓存等)
    access_log /var/log/nginx/example_https_access.log;
    error_log /var/log/nginx/example_https_error.log;

    # 静态资源缓存配置(可选)
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 30d;
        add_header Cache-Control "public, max-age=2592000";
    }
}

配置 HTTP 自动跳转 HTTPS(可选)

shell
# 方案一:重定向
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    # 永久重定向到 HTTPS
    return 301 https://$host$request_uri;
}

# 方案二:重写
server{
        listen 80;
        listen [::]:80;
        server_name example.com www.example.com;
        rewrite ^(.*)$ https://www.greenp.com permanent; # http重写成https
        root   html; #网页根目录(/usr/local/nginx/html/)
        index  index.html index.htm; 
}

防火墙开放 80 和 443 端口

shell
# 查看防火墙端口是否开启
firewall-cmd --list-ports

# 开启防火墙 80 和 443 端口
firewall-cmd --zone=public --add-port=80/tcp --permanent    # 开启 80 端口
firewall-cmd --zone=public --add-port=443/tcp --permanent   # 开启 443 端口
firewall-cmd --reload                                       # 更新防火墙规则
firewall-cmd --list-ports                                   # 查看端口是否开启成功

在阿里云控制台配置80和443安全组

shell
点击云服务器 ECS --> 点击购买的服务器实例 --> 点击安全组 --> 点击配置规则 --> 配置80和443安全组

注意

  1. 域名解析范围说明
shell
DNS 域名解析的 ip 是本地电脑的虚拟机 ip:在虚拟机所在客户端是可以访问的,但是在互联网上则不行,因为虚拟机不是对外的
DNS 域名解析的 ip WLAN wifi ip:在同一 wifi 下的电脑和手机都可访问,但是在互联网上则不行,因为 wifi 有范围限制
DNS 域名解析的 ip 是真实服务器的 ip:可以在互联网上自由访问,注意配置防火墙的出站端口,即:dns域名解析服务器的外网ip,通过域名可以生成https证书,再在服务器上通过nginx配置域名和https协议
  1. 本地解析和互联网解析
shell
我们可以在本地电脑的hosts文件中配置自定义域名,也可以通过本机电脑生成https证书,但是只是局限在本地电脑上实用
在阿里云购买域名,配置完域名解析ip,再购买免费的https证书指定到购买的域名,这样既可以在本地电脑也可在互联网上使用
  1. 客户端浏览器测试时注意,如果之前配置失败并用浏览器测试过,之后重新配置并在浏览器上测试发现无效且找不到问题的原因,可以尝试清理浏览器缓存试一下
  2. certbot 生成 SSL 证书文件,证书有效期为 90 天,建议配置自动续期(如使用 certbot renew)
  3. 私钥文件(domain.key)需严格权限控制(如 chmod 600 /etc/nginx/ssl/domain.key),避免泄露。

四、同机多前端部署

可以参考多虚拟主机,在这基础上还有

基于路径前缀区分(同域名,不同目录)

shell
# https://your-domain.com/admin/ 指向管理后台
# https://your-domain.com/app/ 指向用户端应用

server {
    listen 80;
    server_name your-domain.com;

    # 管理后台
    location /admin/ {
        alias /var/www/admin/dist/;  # 注意:alias 末尾的斜杠
        try_files $uri $uri/ /admin/index.html;
        
        # 如果前端路由是 History 模式,需添加:
        # try_files $uri $uri/ /admin/index.html?$args;
    }

    # 用户端应用
    location /app/ {
        root /var/www/app/;           # root 会将 /app 拼接在路径后
        try_files $uri $uri/ /app/index.html;
    }

    # 默认首页
    location / {
        root /var/www/landing-page/;
        index index.html;
    }
}

# 注意:
1. 这里刻意强调了 root alias 的区别。二者功能一样。但是 root 需要把 location 后的路径拼在拼接在 root 值的后面,alias 不会
 root /var/www/app/:访问 /app/index.html 时,实际读取 /var/www/app/app/index.html
 alias /var/www/admin/dist/:访问 /admin/index.html 时,实际读取 /var/www/admin/dist/index.html
2. 此法需要同步修改前端项目的静态资源基础路径 baseUrl,通常在项目的主配置文件中配置
开发环境访问 /
生成环境访问 /admin/
这样前端静态资源文件前缀会统一加上 /admin/,可正确访问到静态资源,否则 404

混合部署(部分静态 + 部分代理)

如果部分前端应用需要通过 Node.js 等后端服务运行,可使用 proxy_pass 转发。比如使用 next 实现服务端渲染

nginx

shell
server {
    listen 80;
    server_name your-domain.com;

    # 静态前端 1
    location / {
        root /var/www/main-site/;
        try_files $uri $uri/ /index.html;
    }

    # 静态前端 2
    location /blog/ {
        alias /var/www/blog/;
        try_files $uri $uri/ /blog/index.html;
    }

    # 代理到本地 Next.js 服务(运行在 3000 端口)
    location /dashboard/ {
        proxy_pass http://127.0.0.1:3000/;  # 注意末尾的斜杠,会去除 /dashboard 前缀
        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;
    }
}

关键说明

  • 单页应用使用 History 模式时,需要在 location 中配置 try_files 回退到 index.html,否则刷新子路径会 404。
shell
location /your-app/ {
    alias /path/to/dist/;
    try_files $uri $uri/ /your-app/index.html;
}
  • 建议为静态资源(js、css、图片)设置强缓存,html 入口文件使用协商缓存(必须明文配置,否则不同版本的 nginx 可能默认配置不同)
shell
server {
    listen 80;
    server_name example.com;
    
    # 静态资源强缓存(带 hash 的文件)
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        
        root /path/to/dist;
        try_files $uri =404;
    }
    
    # HTML 文件不缓存(确保入口文件总是最新)
    location ~* \.html$ {
        etag on;
        expires -1;
        add_header Cache-Control "no-cache, must-revalidate";
        
        root /path/to/dist;
        try_files $uri /index.html;
    }
}
  • 配置文件组织
shell
当站点增多时,建议将每个 server location 拆分为独立文件,放在 /etc/nginx/conf.d/ /etc/nginx/sites-enabled/ 下,主配置中使用 include 引入,方便管理。