单域名多端口配置NGINX SSL,实现不同端口差异化请求处理
Hey there! Let's work through your NGINX config issue step by step. First, we'll fix the existing config problems, then cover the multi-port setup you requested, plus a cleaner alternative that might work better for your use case.
First: Correct Your 8877 Port Server Blocks
Your current API server blocks have a couple of small issues (like missing ssl on the IPv6 listen directive for port 8877). Here's the corrected, working version that uses your existing SSL certificate (single-domain certs fully support multiple ports for the same domain):
# Redirect HTTP (80) to HTTPS (443) for the main website server { listen 80; listen [::]:80; server_name example.com; rewrite ^/(.*) https://example.com/$1 permanent; } # Redirect HTTP (8877) to HTTPS (8877) for the API server { listen 8877; listen [::]:8877; server_name example.com; rewrite ^/(.*) https://example.com:8877/$1 permanent; } # Main website on HTTPS (443) server { listen 443 ssl; listen [::]:443 ssl; root /var/www/example; index index.html; server_name example.com; ssl_certificate /root/example.com.crt; ssl_certificate_key /root/example.com.key; # Modernize SSL protocols (drop outdated, insecure versions) ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; location / { try_files $uri $uri/ =404; } } # API on HTTPS (8877) - reverse proxy to NodeJS server { listen 8877 ssl; listen [::]:8877 ssl; server_name example.com; ssl_certificate /root/example.com.crt; ssl_certificate_key /root/example.com.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; location / { proxy_pass http://localhost:1111; # Add essential proxy headers so your NodeJS app gets correct client info 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; } }
Key Notes for This Multi-Port Setup:
- Your existing SSL certificate works here because certs are tied to domains, not ports—
example.com:8877is still a valid use for your single-domain certificate. - We added full IPv6 support for all ports to cover both IPv4 and IPv6 traffic.
- Updated SSL protocols to remove TLSv1 and TLSv1.1, which are no longer considered secure.
- Added proxy headers for your NodeJS app—this ensures your backend can correctly detect the original client's IP address and request protocol.
- Critical Tip: Move your SSL certificates out of
/rootif possible. The NGINX process (usually running aswww-data) may not have read access to the/rootdirectory. A safer location is/etc/nginx/ssl/, with file permissions set to600(read/write only for root).
Better Alternative: Path-Based Routing (No Extra Port Needed)
If you don't strictly require a separate port for your API, using a path prefix (like /api/) is a cleaner, more secure approach. This way, you only use port 443 for both your website and API, reducing your attack surface and simplifying maintenance:
# Redirect all HTTP traffic to HTTPS server { listen 80; listen [::]:80; server_name example.com; return 301 https://$host$request_uri; } # Combined website + API on HTTPS (443) server { listen 443 ssl; listen [::]:443 ssl; root /var/www/example; index index.html; server_name example.com; ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; # Serve static website content for all non-API paths location / { try_files $uri $uri/ =404; } # Reverse proxy all /api/ requests to NodeJS location /api/ { proxy_pass http://localhost:1111/; # Trailing slash ensures path is passed correctly to your backend 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; } }
Why This Is a Better Approach:
- Fewer open ports means fewer potential security vulnerabilities.
- A single HTTPS server block makes your config easier to maintain and debug.
- Users don't need to remember a custom port for your API—they just use
https://example.com/api/.
Final Steps to Validate
After updating your config:
- Test for syntax errors with
sudo nginx -t. - Reload NGINX to apply changes:
sudo systemctl reload nginx. - Verify both your website and API work over HTTPS (use
curlor your browser to test endpoints).
内容的提问来源于stack exchange,提问作者Michiel

