You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过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

火山引擎 最新活动