Nginx+Passenger部署Rails应用SSL证书配置疑问确认
Hey there! Let's break down your questions one by one to get your SSL setup working smoothly for your Ruby on Rails app.
1. Is splitting into separate server blocks okay, or should I merge them?
Splitting your HTTP (port 80) and HTTPS (port 443) configurations into separate server blocks is totally acceptable—this is actually a common, clean approach that makes it easy to manage redirects and separate settings for each protocol. You don't have to merge them, though you could if you prefer (by adding both listen 80 and listen 443 ssl to a single block).
That said, your current HTTPS block has one tiny syntax error that will cause Nginx to fail on startup: the line ssl_stapling on is missing a trailing semicolon. Also, modern Nginx best practice prefers using listen 443 ssl; instead of the separate ssl on; directive (the old syntax still works, but the new one is more explicit).
2. Are there missing items in the current configuration?
Yes, there are a few key additions and tweaks to make your setup more secure and functional:
- HTTP-to-HTTPS redirect: Right now, your HTTP block still serves the app over unencrypted HTTP. You should redirect all port 80 traffic to HTTPS so users never access your site insecurely.
- SSL stapling trust chain:
ssl_stapling on(which enables OCSP stapling for faster, more private certificate validation) requires assl_trusted_certificatedirective pointing to your CA's bundle file (most SSL providers include this alongside your main certificate). Without it, stapling won't work properly. - Rails
force_sslsetting: In your Rails app'sconfig/environments/production.rb, addconfig.force_ssl = true. This ensures Rails generates all internal links as HTTPS and prevents mixed-content errors (where some resources load over HTTP while the page is HTTPS). - Diffie-Hellman parameter: Generate a DH parameter file with
openssl dhparam -out /etc/ssl/dhparam.pem 2048(this may take a minute), then addssl_dhparam /etc/ssl/dhparam.pem;to your HTTPS block. This strengthens the security of TLS handshakes. - Cover both www and non-www domains: Update your
server_nameto include bothwww.mysite.comandmysite.com, then either redirect one to the other (e.g., non-www to www) to avoid duplicate content and user confusion. - HSTS header: Add
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;to your HTTPS block. This tells browsers to only access your site via HTTPS for the next year, even if a user types inhttp://. - Deprecated protocols: Your
ssl_protocolsincludes TLSv1 and TLSv1.1, which are no longer secure. Remove them and stick with TLSv1.2 and TLSv1.3.
3. Can I replace server_name with the server's IP address?
You technically can, but it's not recommended unless you have an IP-specific SSL certificate. Here's why:
- If your certificate is issued to
www.mysite.com, users accessing your site via IP will get a browser warning saying the certificate doesn't match the address (since the certificate's subject is a domain, not an IP). - IP-based certificates exist, but they're less common and usually only necessary if you don't have a domain name.
- For most use cases, sticking with your domain name in
server_nameis better—users expect to use a domain, and it avoids trust-eroding certificate warnings.
Updated Configuration Examples
Here's how your corrected configs should look:
HTTP Block (Redirect to HTTPS)
server { listen 80; listen [::]:80 ipv6only=on; server_name www.mysite.com mysite.com; # Redirect all HTTP traffic to HTTPS return 301 https://$server_name$request_uri; }
HTTPS Block
server { listen 443 ssl; listen [::]:443 ssl ipv6only=on; server_name www.mysite.com mysite.com; passenger_enabled on; rails_env production; root /home/directory; # SSL Core Settings ssl_certificate /etc/ssl/my_certificate; ssl_certificate_key /etc/ssl/my_private_key; ssl_trusted_certificate /etc/ssl/my_certificate_bundle; # Path to your CA's bundle file ssl_dhparam /etc/ssl/dhparam.pem; # Secure Protocols & Ciphers ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_prefer_server_ciphers on; # Session & Stapling ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_stapling on; ssl_stapling_verify on; # Security Headers add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # Error Pages error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
内容的提问来源于stack exchange,提问作者Ahmed

