如何通过Nginx为单个域名在同一服务器上配置多端口并启用SSL
如何通过Nginx为单个域名在同一服务器上配置多端口并启用SSL
嘿,针对你这个用Nginx给单个子域名在同一服务器上配置多端口还启用SSL的需求,结合你已经有的GoDaddy域名指向、DigitalOcean服务器、Let's Encrypt SSL这些前提,我来给你一步步理清楚怎么搞!
首先得明确:SSL证书是绑定域名的,和端口无关,所以同一个子域名的不同SSL端口可以共用同一份Let's Encrypt证书,这点不用纠结。
第一步:先配好80端口的基础配置
这一步主要是处理Let's Encrypt的自动续期挑战,同时把HTTP请求跳转到HTTPS。你可以新建一个80端口的server块:
server { listen 80; server_name <subdomain_name>; location /.well-known/acme-challenge/ { root /var/www/html/test; default_type text/plain; } # 把所有HTTP请求自动跳转到HTTPS(默认443端口,如果你想指定其他端口也可以改) location / { return 301 https://$host$request_uri; } }
第二步:配置多端口的SSL server块
你现在已经有一个443端口的配置了,要加其他端口的话,直接新增对应的server块就行,每个块监听不同的SSL端口,指向不同的后端服务。
比如你要加8443端口,配置如下:
server { listen 8443 http2 ssl; server_name <subdomain_name>; # 直接复用你现有的Let's Encrypt证书 ssl_certificate /etc/letsencrypt/live/<subdomain_name>/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/<subdomain_name>/privkey.pem; # 加一些SSL安全优化参数,提升安全性 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; # 日志分开存,方便排查问题 access_log /var/log/nginx/<subdomain_name>-8443.access.log; error_log /var/log/nginx/<subdomain_name>-8443.error.log; # 同样要加上挑战路径,防止续期时出问题 location /.well-known/acme-challenge/ { root /var/www/html/test; default_type text/plain; } location / { # 这些代理头和你原来的配置保持一致就行 proxy_set_header Host $host:$server_port; 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; # 这里改成你8443端口对应的后端服务地址,比如http://localhost:3001 proxy_pass http://localhost:3001; } }
而你原来的443端口配置,只需要把SSL证书的路径补上(你原来的配置里没写,这是关键!),调整下日志名区分开:
server { listen 443 http2 ssl; server_name <subdomain_name>; # 补上SSL证书路径,不然443端口的SSL会失效 ssl_certificate /etc/letsencrypt/live/<subdomain_name>/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/<subdomain_name>/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; # 日志单独存,方便排查443端口的问题 access_log /var/log/nginx/<subdomain_name>-443.access.log; error_log /var/log/nginx/<subdomain_name>-443.error.log; location /.well-known/acme-challenge/ { root /var/www/html/test; default_type text/plain; } location / { proxy_set_header Host $host:$server_port; 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; # 这里是你443端口对应的后端服务地址,比如http://localhost:3000 proxy_pass http://localhost:3000; } }
第三步:重要的后续检查
- 先检查Nginx配置有没有语法错误,执行
sudo nginx -t,如果显示ok,就重启Nginx:sudo systemctl restart nginx - 去DigitalOcean的防火墙或者服务器上的UFW,把你要用到的SSL端口(比如443、8443)还有80端口都开放,不然外部访问不了
- Let's Encrypt证书续期后,记得重启Nginx让新证书生效,你可以给certbot加个钩子,自动续期后重启Nginx,比如执行
sudo certbot renew --deploy-hook "sudo systemctl reload nginx"
如果你想让同一个server块监听多个SSL端口(比如443和8443都用同一个server块,然后根据路径转发到不同后端),也可以这么写:
server { listen 443 http2 ssl; listen 8443 http2 ssl; server_name <subdomain_name>; ssl_certificate /etc/letsencrypt/live/<subdomain_name>/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/<subdomain_name>/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; access_log /var/log/nginx/<subdomain_name>-multi-port.access.log; error_log /var/log/nginx/<subdomain_name>-multi-port.error.log; location /.well-known/acme-challenge/ { root /var/www/html/test; default_type text/plain; } # 443端口的请求转发到3000(也可以根据路径区分,这里只是示例) location /service1/ { proxy_set_header Host $host:$server_port; 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; proxy_pass http://localhost:3000/; } # 8443端口的请求转发到3001 location /service2/ { proxy_set_header Host $host:$server_port; 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; proxy_pass http://localhost:3001/; } }
不过这种方式是靠路径区分服务,不是靠端口,看你实际需求选就行。
备注:内容来源于stack exchange,提问作者Roger




