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;
}注意事项
- 任何配置变更后,需执行 nginx -t 测试配置语法是否正确,无误后再用 systemctl reload nginx 重启服务。
- 直接在 conf.d/ 目录下新建 域名.conf 文件,无需修改主配置,更便于管理
三、HTTPS 站点与域名
准备域名
shell
# 从阿里云服务器购买域名、备案、解析
1. 购买域名
点击控制台 --> 域名 --> 点击域名交易 --> 可进行后缀和价格限制 -->选中要购买的域名支付即可,比如:greenp.com
2. 域名备案
点击备案 --> 按照流程进行域名备案(阿里审核 1 ~ 3 天)(管理局审核需要13 ~ 20天)
3. 域名解析
点击控制台 --> 域名 --> 域名列表,选中指定域名 --> 点击解析,将域名解析到指定到服务器的外网 ip 地址准备 SSL 证书文件
- 方案一:获取免费证书
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/,需手动创建目录)- 方案二:获取付费证书
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安全组注意
- 域名解析范围说明
shell
DNS 域名解析的 ip 是本地电脑的虚拟机 ip:在虚拟机所在客户端是可以访问的,但是在互联网上则不行,因为虚拟机不是对外的
DNS 域名解析的 ip 是 WLAN 即 wifi 的 ip:在同一 wifi 下的电脑和手机都可访问,但是在互联网上则不行,因为 wifi 有范围限制
DNS 域名解析的 ip 是真实服务器的 ip:可以在互联网上自由访问,注意配置防火墙的出站端口,即:dns域名解析服务器的外网ip,通过域名可以生成https证书,再在服务器上通过nginx配置域名和https协议- 本地解析和互联网解析
shell
我们可以在本地电脑的hosts文件中配置自定义域名,也可以通过本机电脑生成https证书,但是只是局限在本地电脑上实用
在阿里云购买域名,配置完域名解析ip,再购买免费的https证书指定到购买的域名,这样既可以在本地电脑也可在互联网上使用- 客户端浏览器测试时注意,如果之前配置失败并用浏览器测试过,之后重新配置并在浏览器上测试发现无效且找不到问题的原因,可以尝试清理浏览器缓存试一下
- certbot 生成 SSL 证书文件,证书有效期为 90 天,建议配置自动续期(如使用 certbot renew)
- 私钥文件(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 引入,方便管理。