08.21.2019

Deploy rails app with puma, systemd and nginx

This article will show how to deploy rails app using puma and systemd as daemon with nginx

In other article I did show how to install ruby, you can follow to install ruby on your server

In this article I will deploy my rails app using ubuntu user named ubuntu

su ubuntu

cd

exec bash

git clone [url-to-your-remote]/myrailsapp

cd myrailsapp

bundle install

Edit database config to make sure your app can connect database

vim config/database.yml

In production part edit as below:

database: <%= ENV['DATABASE_NAME'] %>
username: <%= ENV['DATABASE_USERNAME'] %>
password: <%= ENV['DATABASE_PASSWORD'] %>

edit puma.rb file, paste below code at the end of puma.rb file

# Change to match your CPU core count
workers 2

# 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

 

Next, create puma share directory

mkdir shared

cd shared

mkdir sockets pids log

Export environment config

export DATABASE_NAME=database
export DATABASE_USERNAME=databaseusername
export DATABASE_PASSWORD="databasepassword"
export RAILS_ENV=production

Run test to make sure puma can run correctly

bundle exec puma -C config/puma.rb

Ctrl + C to stop server

auto export config each time you logout from current user

cd ~

vim .bashrc

Add these content at the end of file

export DATABASE_NAME=database
export DATABASE_USERNAME=databaseusername
export DATABASE_PASSWORD="databasepassword"
export RAILS_ENV=production

then run 

source .bashrc

* if you got command not found error, please remove a space after export keyword then insert a new space

cd ~/myrailsapp

bundle exec rails db:create

bundle exec rails db:migrate

bundle exec rails assets:precompile

# if your got error "There was an error while trying to load the gem 'uglifier'.". Please install nodejs

bundle exec rails secret

Copy secret key then paste into config/secret.yml

production:
  secret_key_base: [secret key]

Create systemd service

exit from current user

exit

now you are running as root permission

vim /etc/systemd/system/puma.service

then past below content, remember to change working directory to your rails app and database config

[Unit]
Description=myrailsapp-web
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/myrailsapp
Environment="RAILS_ENV=production"
Environment="DATABASE_NAME=databasename"
Environment="DATABASE_USERNAME=mysqlusername"
Environment="DATABASE_PASSWORD=mysqlpassword"
Environment="PORT=3000"
ExecStart=/home/ubuntu/.rbenv/shims/bundle exec puma -C config/puma.rb
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target

Save and exit

add source path to puma.conf

vim /etc/puma.conf

Add path to your source code

/home/ubuntu/myrailsapp

Save and exit

service puma start

Make sure you have puma.sock in shared/sockets

ls /home/ubuntu/myrailsapp/shared/sockets

Config nginx

vim /etc/nginx/site-available/myrailsapp

Paste below content, remember to correct unix path to your puma.sock, root directory and domain name

upstream app {
    # Path to Puma SOCK file, as defined previously
    server unix:///home/ubuntu/myrailsapp/shared/sockets/puma.sock fail_timeout=0;
}

server {
    listen 80;
    server_name myrailsapp.com;
    root /home/ubuntu/myrailsapp/public;

    try_files $uri/index.html $uri @app;

    location / {
       try_files $uri $uri @app;
    }

    location @app {
        proxy_pass http://app;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

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

create symbolic link to enable config file

cd /etc/nginx/site-enabled

ln -s /etc/nginx/site-available/myrailsapp 

nginx -t

service nginx restart

service puma restart

Now check your website on browser

Hope this help

Please leave a comment if you have any problem when deploy your rails app

 

Leave a comment