Using linger with Ruby on Rails

Overview

Running Puma with Ruby on Rails through Linger lets your app run as a persistent process, with your services restarting automatically if the app crashes or the server reboots.

Prerequisites

This article assumes you have completed the following steps:

How do I configure Ruby on Rails?

The following steps configure your Ruby on Rails app with Puma, and Linger.

How do I install Ruby and Rails?

Ruby: View the Ruby Version Manager (RVM) article to install a new version of Ruby on your Managed VPS.

Rails: View steps #1-7.3 in this guide to configure Rails. The guide uses the Rails app name of blog, but you can name it anything you like.

How do I install Puma?

View the following guides for steps on installing Puma:

Edit the puma.rb file

Navigate into the following directory:

[server]$ cd /home/username/example.com/blog/config

Edit the puma.rb file to change the default port # to the port you chose when creating the Proxy Server in the panel. This example uses port 8003:

port ENV.fetch("PORT") {8003}

Start the Puma web server

Navigate into the following directory:

[server]$ cd /home/username/example.com/blog/

Run the following command:

[server]$ bin/rails server

To stop the server, press CTRL + C.

Troubleshooting an error

If you get a blocked host error about your app domain, you'll need to add a line to the development.rb file. Navigate into the following directory:

[server]$ cd /home/username/example.com/blog/config/environments/

Edit the development.rb file. Under the config.enable_reloading = true line, add the following:

config.hosts << /example\.com/

Restart your Managed VPS and relaunch Puma. The error should now be resolved.

How do I install Linger?

To install linger under your user, log in to your server via SSH and run the following command:

[server]$ loginctl enable-linger

This command will not respond with any output.

How do I configure Puma for Systemd user units?

This step configures Puma for Systemd user units. View the official guide for further details.

  1. Create a file named puma.service in the .config/systemd/user directory:

    [server]$ nano ~/.config/systemd/user/puma.service
  2. Add the following code to this file:

    [Unit]
    Description=Puma instance to serve application
    After=network.target
    
    [Service]
    WorkingDirectory=/path/to/your/app
    ExecStart=/path/to/your/app/bin/puma -C config/puma.rb -e production
    ExecReload=/bin/kill -s HUP $MAINPID
    KillMode=mixed
    TimeoutStopSec=5
    PrivateTmp=true
    Restart=on-failure
    
    [Install]
    WantedBy=default.target
  3. Edit the highlighted lines above as follows:

    • WorkingDirectory: The path to your website application.

    • ExecStart: The path to your puma installation.

    If you are using a custom environment for your Ruby/Puma setup, be sure to define your environment directory paths in the [Service] section of your Linger Systemd service file.

    [Unit]
    Description=Puma server to serve application
    After=network.target
    
    [Service]
    WorkingDirectory=/path/to/your/app
    ExecStart=/path/to/your/app/bin/puma  -C config/puma.rb -e production
    ExecReload=/bin/kill -s HUP $MAINPID
    Environment=GEM_PATH=/path/to/your/.rvm/gem-VERSION@global
    Environment=GEM_HOME=/path/to/your/.rvm/gems/ruby-VERSION
    Environment=PATH=/path/to/your/.rvm/gems/ruby-VERSION/bin:/path/to/your/.rvm/gem-VERSION@global/bin:/path/to/your..rvm/rubies/ruby-VERSION/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/APP:/usr/local/APP:/snap/bin:/path/to/your/.rvm/bin
    KillMode=mixed
    TimeoutStopSec=5
    PrivateTmp=true
    Restart=on-failure
    PIDFile=/tmp/puma.pid
    
    [Install]
    WantedBy=default.target
  4. Enable the user unit for puma:

    [server]$ systemctl --user enable puma
  5. Start the unit with puma:

    [server]$ systemctl --user start puma
  6. Confirm it is running:

    [server]$ systemctl --user status puma

Your app's services will now automatically restart when the server reboots or if the application crashes.

See also

Still not finding what you're looking for?