Skip to content

Instantly share code, notes, and snippets.

@brenoperucchi
Forked from davidteren/Rails, Puma & Nginx.md
Created February 14, 2023 03:36
Show Gist options
  • Save brenoperucchi/940b261708054293264e8dad062bc9dc to your computer and use it in GitHub Desktop.
Save brenoperucchi/940b261708054293264e8dad062bc9dc to your computer and use it in GitHub Desktop.
Example setup for Puma with Nginx in a Rails app

In the apps config/puma.rb file:

Change to match your CPU core count
# Check using this on the server => grep -c processor /proc/cpuinfo
workers 4

# Min and Max threads per worker
threads 1, 6
app_dir    = File.expand_path('../..', __FILE__)
shared_dir = "#{app_dir}/shared"

# Default to production
rails_env = ENV['RAILS_ENV'] || 'production'
environment rails_env

# Set up socket location
bind "unix://#{shared_dir}/sockets/puma.sock"

# Logging
stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true

# Set master PID and state locations
pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"
activate_control_app

on_worker_boot do
  require 'active_record'
  ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
  ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])
end

In the /etc/systemd/system/puma.service file

#Modify the path to the app directory and the user and group. 
[Unit]
Description=Puma HTTP Server
After=network.target
# Uncomment for socket activation (see below)
# Requires=puma.socket
[Service]
# Foreground process (do not use --daemon in ExecStart or config.rb)
Type=simple
# Preferably configure a non-privileged user
User=deploy
Group=deploy
# Specify the path to your puma application root
WorkingDirectory=/home/deploy/app-name
# Helpful for debugging socket activation, etc.
# Environment=PUMA_DEBUG=1
# EnvironmentFile=/home/deploy/app-name/.env
# The command to start Puma
# ExecStart=/sbin/puma -b tcp://0.0.0.0:9292 -b ssl://0.0.0.0:9293?key=key.pem&cert=cert.pem
# ExecStart=/usr/local/bin/bundle exec --keep-file-descriptors puma -e production
# ExecStart=/usr/local/bin/puma -C /home/deploy/app-name/config/puma.rb
ExecStart=/home/deploy/.rbenv/shims/bundle exec puma -e production -C ./config/puma.rb config.ru
PIDFile=/home/deploy/app-name/shared/tmp/pids/puma.pid
Restart=always
[Install]
WantedBy=multi-user.target

In the /etc/nginx/sites-enabled/defaultfile

upstream app {
  # Path to Puma SOCK file, as defined previously
  server unix:/home/deploy/app-name/shared/sockets/puma.sock fail_timeout=0;
}
server {
  listen 80;
  server_name localhost;
  root /home/deploy/app-name/public;
  try_files $uri/index.html $uri @app;
  location @app {
    proxy_pass http://app;
    proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;

    # The follow resulted in a 422 unprocessible entity being returned after a login.
    # Changing from \$http_host to $host fixed the issue.
    # proxy_set_header Host \$http_host;
    proxy_set_header Host $host;

    proxy_redirect off;
  }
  error_page 500 502 503 504 /500.html;
  client_max_body_size 4G;
  keepalive_timeout 10;
  
  # Other rules & directives....

}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment