HHH v4

Rails app on Ubuntu production server under RVM + puma service + NginX + letsencrypt cert

Edit
equivalent Web Development
Public
Rails
NginX
Puma
ruby
Ubuntu
Idea is to run Rails 7 (Rails 8) app under Ruby installed via RVM  (so it's easy to upgrade Ruby versions), where Puma is systemctl  service (so it can start on system reboot)  and NginX is infront of Puma while SSL certificates are for free auto updated with Let's encrypt

Prerequisites
  • Install RVM - Ubuntu steps
  • install NginX 
  • Install certbot (Let's encrypt ubuntu daemon that auto updates certs)
  • ssh to server and git clone repo 

Clone project to server


ssh to your server and git clone it. My example will be cloned in 
/root/myapp

Install Ruby via RVM + alias


rvm install 3.3.5
rvm alias create myapp123 ruby-3.3.5
rvm alias list                           # you should see myapp123 => ruby-3.3.5

RVM alias will be important when we create puma service. We will tel it to use RVM alias instead of hardcode version number therefore we don't need to update service file every time we update ruby

Make sure your project has ./.ruby-version file and in it desired version number (e.g: ruby-3.3.5 )  this is so that you can start rails console in proper env when debugging stuff

Puma as a systemctl service


Create file /etc/systemd/system/myapp_puma.service 

[Unit]
Description=Puma HTTP Server for MyApp
After=network.target

# Uncomment for socket activation (see below)
# Requires=puma.socket

[Service]
Type=notify

WatchdogSec=10

# Preferably configure a non-privileged user
# User=

WorkingDirectory=/root/myapp

# Explicitly define your ENV variables as they may be ignored
Environment=WEB_CONCURRENCY=1
Environment=RAILS_ENV=production
Environment=PORT=3009

# Helpful for debugging socket activation, etc.
# Environment=PUMA_DEBUG=1

ExecStart=/usr/share/rvm/wrappers/myapp123/bundle exec  ./bin/rails server

Restart=always

[Install]
WantedBy=multi-user.target


Now if you run

sudo service myapp_puma start

...you should be able to curl localhost:3000  (or whatever port you define in config/puma.rb)

Important debugging note: if something fails and you change the service file content you need to run
sudo systemctl daemon-reload
before you can try sudo service myapp_puma start again so that it reloads


In order for this to work after system reboot you need to register the service:

sudo systemctl enable myapp_puma

to restart:
sudo service myapp_puma restart
sudo service myapp_puma stop
sudo service myapp_puma start
sudo service myapp_puma status

NginX + ssl certificate


Given Nginx you've installed have configs in /etc/nginx/sites-enabled
And you want to run your website on domain myapp.com  and www.myapp.com  
Then create a file in /etc/nginx/sites-available/myapp with content:

upstream myapp678 {
  server 127.0.0.1:3009;  # ...or whatever port you use
}

server {
  server_name myapp.com www.myapp.com;
  client_max_body_size 32M; # Optional - change this to whatever you feel like the biggest file upload be to your server

  root /var/www/html;
  location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-NginX-Proxy true;
    proxy_pass http://myapp678;
  }
}

that's it. Now if you run $ sudo nginx -t you should not see any errors. However we still need to add ssl certs. This will be added by running $ sudo certbot   and following the steps in the CLI. It will insert lines directly to this file  and end result will look something like:

# DON'T COPY PASTE THIS - THIS IS EXAMPLE OF WHAT CERTBOT GENERATES!
upstream myapp678 {
  server 127.0.0.1:3009;  # ...or whatever port you use
}

server {
  server_name myapp123.com www.myapp123.com;
  client_max_body_size 32M; # Optional - change this to whatever you feel like the biggest file upload be to your server

  root /var/www/html;
  location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-NginX-Proxy true;
    proxy_pass http://myapp678;

      # DON'T COPY PASTE THIS - THIS IS EXAMPLE OF WHAT CERTBOT GENERATES!
      proxy_set_header X-Forwarded-Proto https;
      proxy_set_header X-Forwarded-Server $host;
      proxy_set_header Host $http_host;
      proxy_redirect off;

  }

  # DON'T COPY PASTE THIS - THIS IS EXAMPLE OF WHAT CERTBOT GENERATES!
  # START These lines are added by certbot
  #listen [::]:443 ssl http2 ipv6only=on; # managed by Certbot
  listen 443 http2 ssl; # managed by Certbot
  ssl_certificate /etc/letsencrypt/live/myapp123.com/fullchain.pem; # managed by Certbot
  ssl_certificate_key /etc/letsencrypt/live/myapp123.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
  # END certbot

}

now you can manage NginX with

sudo service nginx stop
sudo service nginx start
sudo service nginx status
sudo service nginx restart
sudo nginx -t

------------------------------------------------------

Archive


Old Puma service (before Rails 8):

  
[Unit]
Description=Puma HTTP Server for MyApp123
After=network.target

# Uncomment for socket activation (see below)
# Requires=puma.socket

[Service]
Type=notify

WatchdogSec=10

# Preferably configure a non-privileged user
# User=

WorkingDirectory=/home/ubuntu/myapp123

# Explicitly define your ENV variables as they may be ignored
Environment=WEB_CONCURRENCY=3
Environment=RAILS_ENV=production

# Helpful for debugging socket activation, etc.
# Environment=PUMA_DEBUG=1

# use absolute path ov RVM alias for ruby version we use
ExecStart=/usr/share/rvm/wrappers/myapp123/bundle exec puma -C ./config/puma.rb

Restart=always

[Install]
WantedBy=multi-user.target