Skip to content
Advertisement

How to get Puma and Nginx to run in Rails production?

Fighting for months with this, another new career path blooming every week, it seems, I look down.

So, that said. Here’s the closest I’ve come. I had it working several times, but it’s so brittle as I’m more a developer than a devops (?) person.

I am running Ubuntu 20.04.

be puma -C config/puma.rb config.ru -e production 
  --pidfile /run/puma.pid 
  --control-url 'unix:///root/mysite/tmp/sockets/mysite-puma.sock' 
  --control-token 'app' 
  --state tmp/puma.state 
  -b 'tcp://mysite.com'

I can run pumactl as so: bundle exec pumactl -T 'app' -C 'unix:///root/mysite/tmp/sockets/mysite-puma.sock' -S tmp/puma.state [pumactl switch]

My nginx config.

/etc/nginx/nginx.conf

user www-data;
worker_processes auto;

pid /run/nginx.pid;

include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 1024;
    multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

        sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # SSL Settings
    ##

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;

    ##
    # Logging Settings
    ##

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    ##
    # Gzip Settings
    ##

    gzip off;

    gzip_vary off;
    #gzip_proxied any;
    #gzip_comp_level 6;
    #gzip_buffers 16 8k;
    #gzip_http_version 1.1;
    #gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/mysite.com;
}

/etc/nginx/sites-enabled/mysite.com

# This configuration uses Puma. If using another rack server, substitute appropriate values throughout.
upstream puma {
  server unix:///root/mysite/tmp/sockets/mysite.sock;
}

# We need to be listing for port 80 (HTTP traffic). 
# The force_ssl option will redirect to port 443 (HTTPS)
server {

  # Update this
  server_name mysite.com www.mysite.com;

  # Don't forget to update these, too.
  # For help with setting this part up, see:
  # http://localhost:4000/2018/09/18/deploying-ruby-on-rails-for-ubuntu-1804.html
  root        /root/mysite/public;
  access_log  /root/mysite/log/nginx.access.log;
  error_log   /root/mysite/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;
  }

}

  # This is the configuration for port 443 (HTTPS)
  server {

    listen [::]:443 ssl ipv6only=on; # managed by Certbot

    server_name mysite.com www.mysite.com;
    
    ssl_certificate       /etc/letsencrypt/live/mysite.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key   /etc/letsencrypt/live/mysite.com/privkey.pem;   # managed by Certbot
    include               /etc/letsencrypt/options-ssl-nginx.conf;          # managed by Certbot
    ssl_dhparam           /etc/letsencrypt/ssl-dhparams.pem;                # managed by Certbot

    # Don't forget to update these, too.
    # I like to update my log files to include 'ssl' in the name.
    # If there's ever any need to consult the logs, it's handy to have HTTP and HTTPS traffic separated.
    root        /root/mysite/public;
    access_log  /root/mysite/log/nginx.ssl.access.log;      # Updated file name
    error_log   /root/mysite/log/nginx.ssl.error.log info;  # Updated file name

    error_page 500 502 503 504 /500.html;
    client_max_body_size 10M;   
    
    location ^~ /assets/ {
      gzip_static off;
      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;

       # This is an important line to help fix some redirect issues.
       proxy_set_header X-Forwarded-Proto https; 
    
       proxy_set_header Host $http_host;
       proxy_redirect off;

       proxy_pass http://puma;
     }
  }

  # If you chose Certbot to redirect all traffic to HTTPS, this will be in your current config. 
  # Remove it or you'll run into redirection errors:
  server {
   if ($host = example.com) {
      return 301 https://www.example.com$request_uri;
   } # managed by Certbot
 
 
    listen [::]:80 default_server deferred;
    server_name example.com;
    return 404; # managed by Certbot
 
}

Advertisement

Answer

First thing first, in your /etc/nginx/sites-enabled/mysite.com

First step

change

upstream puma {
  server unix:///root/mysite/tmp/sockets/mysite.sock;
}

to

upstream puma {
  server 0.0.0.0:9838; # port number in which your puma server starts
}

After changing your /etc/nginx/sites-enabled/mysite.com It should look like the following.

upstream puma {
  server 0.0.0.0:9838;
}

server {
    server_name  mysite.com www.mysite.com;
    client_max_body_size 200m;
    gzip             on;
    gzip_comp_level  4;
    gzip_min_length  1000;
    gzip_proxied     expired no-cache no-store private auth;
    gzip_types       text/plain application/javascript application/json application/x-javascript text/xml text/css application/xml text/javascript;

    root /root/mysite/public;

    location / {
      try_files $uri/index.html $uri @app;
    }

    location  ~* ^/assets {
      root /root/mysite/public;
      expires 1y;
      add_header Cache-Control public;
      add_header Last-Modified "";
      add_header ETag "";
      break;
    }

    error_page 500 502 503 504 /500.html;

    location @app {
      proxy_pass http://puma;

      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Proto https;
      proxy_set_header Host $http_host;
      proxy_redirect off;
    }

    location ~ /.well-known {
      allow all;
    }


    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/mysite.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}


server {
    if ($host = mysite.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    if ($host = www.mysite.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    server_name  mysite.com www.mysite.com;
    listen 80;
    return 404; # managed by Certbot
}

Second step

Then run gem install foreman to install foreman library. To know more about foreman click here.

Third step

Create Procfile in your project root directory and paste the below content

web: RAILS_ENV=production bundle exec puma -e  production -p 9838 -d -S  ~/puma -C config/puma.rb

Final step

Run foreman start to start the puma server and there you go, you will be able to see your application running.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement