Introduction
To set up HTTPS for a Rails app that is served up by Nginx is quite easy, but there are a couple of little things that need to be configured. This writeup is intended to document these small yet crucial steps.
This document makes the following assumptions:
- SSL has been obtained and placed in the Nginx configuration folders.
- Most of the SSL flags in Nginx conf file have been set.
If that’s not true, google online to find out how to do that. But here are a couple of tricky things on both the Nginx and Rails configurations that need to be highlighted.
On the Nginx side…
Requesting a SSL certificate
You need to follow the instructions from this web page: https://calnetweb.berkeley.edu/calnet-technologists/calnet-incommon-sectigo-certificate-service
Installing the Certificate
Once your request is approved, IST will send you an email with all the certificate download link. The only file you need to worry about is the Certificate (w/ chain), PEM encoded.
After you have downloaded that file, follow the instructions on this web page: https://calnetweb.berkeley.edu/calnet-technologists/incommon-comodo-certificate-service/extended-incommon-ssl-certificate-example.
The most important instructions are here:
To examine the individual certificates provided (and to simplify the later creation of a new Root/Intermediate bundle file), open as a source file the test_training_berkeley_edu.cer certificate bundle file using your favorite text editor. Now save the text components corresponding to each certificate into three new files named cert1.cer (topmost certificate in the source file), cert2.cer (middle certificate in the source file), and cert3.cer (bottom certificate in the source file).
Note: cert2.cer – the middle section – should have two certificates
These are steps to get all the certificates ready (assuming that you are in a temporary working directory like ~/ssl/nginx/
:
cp test_training_berkeley_edu cert1.cer # keep top cert cp test_training_berkeley_edu cert2.cer # keep middle 2 certs cp test_training_berkeley_edu cert3.cer # keep bottom cert mv cert3.cer test_training_berkeley_edu_cert.cer mv test_training_berkeley_edu_cert.cer /etc/ssl/nginx/ cat cert2.cer cert1.cer > CA-bundle.cer mv CA-bundle.cer /etc/ssl/nginx/ mv test.training.berkeley.edu.key /etc/ssl/private/ sudo chmod 0400 /etc/ssl/private/test.training.berkeley.edu.key mv ssl_passwords.txt /etc/ssl/private/ sudo chmod 0400 /etc/ssl/private/ssl_passwords.txt
Once we have all the certificates and keys put in the right places, then we need to update the Nginx server configuration like this:
server { listen *:80; server_name test.training.berkeley.edu; return 301 https://$host$request_uri; } server { server_name test.training.berkeley.edu; listen *:443; ssl on; ssl_prefer_server_ciphers on; ssl_certificate /etc/ssl/nginx/test_training_berkeley_edu_cert.cer; ssl_certificate_key /etc/ssl/private/test.training.berkeley.edu.key; ssl_password_file /etc/ssl/private/ssl_passwords.txt; # send intermediate certificate during new sessions ssl_trusted_certificate /etc/ssl/nginx/CA-bundle.cer; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !kECDH !DSS !MD5 !RC4 !E XP !PSK !SRP !CAMELLIA !SEED'; ssl_dhparam /etc/ssl/nginx/dhparam2048.pem; ssl_stapling on; ssl_session_cache builtin:1000 shared:SSL:10m; .... the rest of the server configuration
Note: dhparam2048.pem may not exists, so you need to generate it like this:
openssl dhparam -out /etc/ssl/nginx/dhparam2048.pem 2048
Additional Configuration for Nginx
We need to set proxy_set_header X-Forwarded-Proto https;
in the @app
location in the Nginx configuration. This is what ggkbase_production.conf
looks like in that portion:
location @app { proxy_pass http://ggkbase_production_puma_server; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; # IF NOT SET, TOO MANY REDIRECT ERROR proxy_set_header Host $http_host; proxy_set_header X-Sendfile-Type X-Accel-Redirect; proxy_set_header X-Accel-Mapping /work/railsapps/ggkbase_production/=/__send_file_accel/; proxy_read_timeout 3000; proxy_redirect off; }
On the Rails side…
In the app/config/environments/production.rb
configuration file, set config.force_ssl = true
After that restart Nginx and Puma, and the site is all good to go with HTTPS.