SSL for Ruby on Rails app

When pummeling around this problem I figured out there are not many step-by-step tutorials for dummies (like me). So after fixing all issues, I think it’s good practice to share the knowledge.

How to set up SSL for your rails application

Step 1: Obtain the SSL certificate. Various providers offer them. A certificate is, simply put, a bunch of text. It is divided into few parts. Usually two or four. The first one is the key. The second one is the actual certificate. It might be split into three separate files.

Step 2: Place those files on your server. I put them inside the Nginx directory (/etc/nginx/ssl/project_name/certificate.crt – for the certificate and /etc/nginx/ssl/project_name/certificate.key – for the key) Be sure, to concatenate your certificate the right way. If it’s not concatenated yet, take care of combining them together with, the right way – there is always a middle part, a prefix, and a suffix part. Putting middle part at the end will cause the file to malfunction.

Example of the certificate file

Step 3: Configure Nginx. My example is listed below. It shows how you can run both versions, http and https at the same time. Additionally, I included a redirect, so my client doesn’t need to buy certificates for each similar domain.

upstream puma_project_name {
  server unix:///home/deploy/apps/project_name/shared/tmp/sockets/project_name-puma.sock;
}

server {
  server_name project_name.ru;
  rewrite ^ https://project_name.ru$request_uri? permanent;
}


server {
  listen 80;
  server_name project_name.net;

  root /home/deploy/apps/project_name/current/public;
  access_log /home/deploy/apps/project_name/current/log/nginx.access.log;
  error_log /home/deploy/apps/project_name/current/log/nginx.error.log info;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @puma;
  location @puma {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;

    proxy_pass http://puma_project_name;
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 10M;
  keepalive_timeout 10;
}

server { 
  listen 443 ssl;
  server_name https_domain_project_name.ru;

  ssl_prefer_server_ciphers On;

  ssl_certificate /etc/nginx/ssl/project_name/certificate.crt; 
  ssl_certificate_key /etc/nginx/ssl/project_name/certificate.key; 
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;


  root /home/deploy/apps/project_name/current/public;
  access_log /home/deploy/apps/project_name/current/log/nginx.access.log;
  error_log /home/deploy/apps/project_name/current/log/nginx.error.log info;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

I’m almost sure that this is the most basic and ineffective approach, but it’s working quite well.

Published by

Anton

Hello! My name is Anton. I am a passionate project manager who loves digging deep into code. You can check my Github and CodeEval. Hopefully my thoughts on management can lead you to one or another good idea.