Nginx反向代理实战:单服务器多域名HTTPS配置指南

张开发
2026/4/16 13:47:29 15 分钟阅读

分享文章

Nginx反向代理实战:单服务器多域名HTTPS配置指南
1. 为什么需要单服务器多域名HTTPS配置最近帮朋友公司处理了个挺典型的场景他们开发了两个微信小程序用户量都不大但每个小程序都需要独立的HTTPS域名。按照常规做法每个域名配一台服务器成本直接翻倍。其实用Nginx反向代理完全可以在单台服务器上实现多域名HTTPS服务我实测下来每年能省下大几千的服务器费用。这里的技术核心在于两点一是SSL证书的多域名支持二是Nginx的SNIServer Name Indication技术。简单来说当客户端访问服务器时会先告诉服务器自己要访问哪个域名Nginx就能根据这个信息把请求准确转发到对应的后端服务。这就好比快递柜的取件码——不同快递域名请求对应不同的格子后端服务。常见的使用场景包括为多个微信小程序配置独立域名企业官网与管理系统共用服务器开发测试环境的多项目隔离个人博客与作品集站点合并部署2. 准备工作与环境配置2.1 服务器基础环境建议使用Ubuntu 20.04 LTS或CentOS 7系统我习惯用Ubuntu因为apt包管理更友好。先更新系统sudo apt update sudo apt upgrade -y必备的依赖包sudo apt install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev2.2 Nginx安装与验证官方源版本可能较旧建议添加Nginx官方源sudo apt install curl gnupg2 ca-certificates lsb-release echo deb http://nginx.org/packages/ubuntu lsb_release -cs nginx | sudo tee /etc/apt/sources.list.d/nginx.list curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add - sudo apt update sudo apt install nginx -y安装后检查版本nginx -v # 应该输出类似nginx version: nginx/1.25.3启动Nginx并设置开机自启sudo systemctl start nginx sudo systemctl enable nginx2.3 SSL证书准备推荐使用Lets Encrypt免费证书用certbot工具自动获取sudo apt install certbot python3-certbot-nginx -y假设我们有两个域名api1.yourdomain.comapi2.yourdomain.com分别获取证书注意替换真实域名sudo certbot certonly --nginx -d api1.yourdomain.com sudo certbot certonly --nginx -d api2.yourdomain.com证书通常存放在/etc/letsencrypt/live/api1.yourdomain.com//etc/letsencrypt/live/api2.yourdomain.com/每个目录包含fullchain.pem证书链privkey.pem私钥cert.pem证书chain.pem中间证书3. Nginx多域名配置实战3.1 基础配置结构Nginx的配置文件通常位于/etc/nginx/nginx.conf但最佳实践是为每个站点创建独立配置文件sudo mkdir /etc/nginx/sites-available sudo mkdir /etc/nginx/sites-enabled然后在nginx.conf的http块内添加include /etc/nginx/sites-enabled/*.conf;3.2 多域名HTTPS配置创建第一个域名的配置文件sudo nano /etc/nginx/sites-available/api1.conf写入以下内容注意替换证书路径和域名server { listen 443 ssl; server_name api1.yourdomain.com; ssl_certificate /etc/letsencrypt/live/api1.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api1.yourdomain.com/privkey.pem; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; location / { 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_pass http://127.0.0.1:8081; } }同理创建api2.confserver { listen 443 ssl; server_name api2.yourdomain.com; ssl_certificate /etc/letsencrypt/live/api2.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api2.yourdomain.com/privkey.pem; # 其他SSL配置与api1相同... location / { 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_pass http://127.0.0.1:8082; } }启用配置sudo ln -s /etc/nginx/sites-available/api1.conf /etc/nginx/sites-enabled/ sudo ln -s /etc/nginx/sites-available/api2.conf /etc/nginx/sites-enabled/3.3 HTTP重定向到HTTPS强制所有HTTP请求跳转到HTTPSsudo nano /etc/nginx/sites-available/redirect.conf内容server { listen 80; server_name api1.yourdomain.com api2.yourdomain.com; return 301 https://$host$request_uri; }启用并测试配置sudo ln -s /etc/nginx/sites-available/redirect.conf /etc/nginx/sites-enabled/ sudo nginx -t # 测试配置 sudo systemctl reload nginx4. SpringBoot后端服务配置4.1 多实例端口分配假设有两个SpringBoot项目小程序A后端运行在8081端口小程序B后端运行在8082端口application.yml配置示例# 项目A的配置 server: port: 8081 servlet: context-path: /api1 # 项目B的配置 server: port: 8082 servlet: context-path: /api24.2 解决常见跨域问题在SpringBoot中添加配置类Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOrigins(https://api1.yourdomain.com, https://api2.yourdomain.com) .allowedMethods(GET, POST, PUT, DELETE) .allowCredentials(true) .maxAge(3600); } }4.3 日志隔离配置为不同项目配置独立日志文件logging: file: name: logs/app1.log level: root: info com.yourpackage: debug5. 高级配置与优化技巧5.1 连接池优化在Nginx配置中调整反向代理参数location / { proxy_http_version 1.1; proxy_set_header Connection ; proxy_connect_timeout 60s; proxy_read_timeout 600s; proxy_send_timeout 600s; proxy_buffering off; # 其他配置... }5.2 负载均衡配置如果单个后端实例压力大可以扩展为多实例upstream backend1 { server 127.0.0.1:8081 weight5; server 192.168.1.100:8081; keepalive 32; } upstream backend2 { server 127.0.0.1:8082; server 192.168.1.101:8082 backup; } server { # ...其他配置 location / { proxy_pass http://backend1; } }5.3 证书自动续期Lets Encrypt证书有效期90天设置自动续期sudo crontab -e添加0 3 * * * /usr/bin/certbot renew --quiet --post-hook systemctl reload nginx6. 常见问题排查6.1 502 Bad Gateway错误可能原因及解决方案后端服务未启动检查sudo systemctl status your-service端口冲突sudo netstat -tulnp | grep 8081防火墙限制sudo ufw allow 8081/tcp6.2 SSL证书不生效检查步骤证书路径是否正确证书文件权限sudo chmod 644 /etc/letsencrypt/live/*/privkey.pem证书链是否完整openssl x509 -in fullchain.pem -text -noout6.3 微信小程序域名验证在微信公众平台配置服务器域名时需要确保HTTPS证书有效备案信息完整不包含非标准端口如需WebSocket需单独配置wss协议7. 安全加固措施7.1 防止恶意扫描在Nginx中添加基础防护server { # 禁止常见恶意User-Agent if ($http_user_agent ~* (nmap|nikto|wget|curl|python)) { return 403; } # 限制请求方法 if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 405; } }7.2 请求频率限制防止CC攻击limit_req_zone $binary_remote_addr zoneapi_limit:10m rate10r/s; server { location / { limit_req zoneapi_limit burst20 nodelay; # 其他配置... } }7.3 隐藏服务器信息修改nginx.confserver_tokens off; more_set_headers Server: Your-Custom-Name;8. 性能监控与日志分析8.1 实时监控配置安装ngxtop实时监控sudo pip install ngxtop ngxtop -l /var/log/nginx/access.log8.2 日志格式化在nginx.conf中定义日志格式log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for $request_time $upstream_response_time;8.3 错误日志分析常见错误日志定位connect() failed (111: Connection refused)后端服务未启动upstream timed out增加proxy_read_timeout值SSL_do_handshake() failed检查证书有效期和协议支持9. 实际部署案例最近部署的一个电商项目包含主站APIapi.shop.com → 8081端口管理后台APIadmin.shop.com → 8082端口移动端H5m.shop.com → 8083端口Nginx关键配置# 主站配置 server { listen 443 ssl; server_name api.shop.com; ssl_certificate /path/to/api.shop.com/fullchain.pem; ssl_certificate_key /path/to/api.shop.com/privkey.pem; location / { proxy_pass http://backend_cluster1; } } # 管理后台配置 server { listen 443 ssl; server_name admin.shop.com; ssl_certificate /path/to/admin.shop.com/fullchain.pem; ssl_certificate_key /path/to/admin.shop.com/privkey.pem; location / { # 添加IP白名单限制 allow 192.168.1.0/24; deny all; proxy_pass http://backend_cluster2; } }10. 维护与更新策略证书更新后我发现Nginx有时不会自动加载新证书后来在reload命令前增加了sleep#!/bin/bash certbot renew --quiet --post-hook sleep 10 systemctl reload nginx对于SpringBoot服务更新我习惯用脚本实现零停机部署#!/bin/bash # 构建新版本 mvn clean package -DskipTests # 停止旧实例保留一个实例运行 systemctl stop service1instance2.service # 部署新版本 cp target/app.jar /opt/service1/instance2/ # 启动新实例 systemctl start service1instance2.service # 等待健康检查 sleep 30 # 滚动更新另一个实例 systemctl stop service1instance1.service # ...重复上述步骤

更多文章