promisepreston
12/16/2019 - 3:59 PM

Puma Systemd Setup

Puma Systemd Setup

  1. Install Puma if it is not already installed.

  2. Create a directory called puma under the config directory and add a file production.rb to it.

  3. Copy the contents in config/puma.rb into it , but simply change the RAILS_ENV from development to production. Please do not delete the file config/puma.rb as it defines the puma configuration for the development environment.

  4. Run the command which puma to print the absolute installation path of the puma server on your machine, which is usually /home/your-username/.rbenv/shims/puma path if you used rbenv version manager.

  5. Open the puma.service file located at /etc/systemd/system/puma.service by the running the command below:

    sudo nano /etc/systemd/system/puma.service

  6. Copy the Puma service configuration file below into it and save.

Puma Service Configuration

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

[Service]
# Foreground process (do not use --daemon in ExecStart or config.rb)
Type=simple

# Preferably configure a non-privileged user
User=deploy

# The path to the your application code root directory
WorkingDirectory=/home/deploy/my-app

# The command to start Puma
ExecStart=/home/deploy/.rbenv/shims/puma -C /home/deploy/my-app/config/puma.rb

# The command to stop Puma
ExecStop=/home/deploy/.rbenv/shims/puma -S /home/deploy/my-app/config.puma.rb

# Path to PID file so that systemd knows which is the master process
PIDFile=/home/deploy/my-app/tmp/pids/puma.pid

# Should systemd restart puma?
# Use "no" (the default) to ensure no interference when using
# stop/start/restart via `pumactl`.  The "on-failure" setting might
# work better for this purpose, but you must test it.
# Use "always" if only `systemctl` is used for start/stop/restart, and
# reconsider if you actually need the forking config.
Restart=always

[Install]
WantedBy=multi-user.target

Note:

  • For ExecStart: ExecStart=/your-puma-directory-path -C /your-app-puma-config-file-path
  • For ExecStop: ExecStop=/your-puma-directory-path -S /your-app-puma-config-file-path
  • There is no need to define ExecReload or ExecRestart, they work out of the box.

Nginx Config File for Puma

upstream railsserver {
server 127.0.0.1:3000;
}

server {
    listen 80;

    # replace 'localhost' with your fqdn if you want to use zammad from remote
    server_name localhost;

    root /home/deploy/oau-apply/public;

    client_max_body_size 50M;

    location ~ ^/(assets/|robots.txt|humans.txt|favicon.ico) {
        expires max;
    }

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header CLIENT_IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300;
        proxy_pass http://railsserver;

        gzip on;
        gzip_types text/plain text/xml text/css image/svg+xml application/javas$
        gzip_proxied any;
    }
}

After this run sudo systemctl enable puma to enable the puma service.

Commands for Managing Puma Service

  • Enable: Enable both socket and service so they start on boot. Alternatively, you could leave puma.service disabled and systemd will start it on first use (with startup lag on first request)

    sudo systemctl enable puma.service

  • Reload: Reload the puma service after installing or making changes to either the puma.socket or puma.service file.

    sudo systemctl daemon-reload

  • Start: Initial start up. The Requires directive ensures the socket is started before the service.

    sudo systemctl start puma.socket puma OR

    sudo systemctl start puma.socket puma.service

  • Status: Check status of both socket and service.

    sudo systemctl status puma.socket puma OR

    sudo systemctl status puma.socket puma.service

  • Restart: A "hot" restart, with systemd keeping puma.socket listening and providing to the new puma (master) instance.

    sudo systemctl restart puma OR

    sudo systemctl restart puma.service

    A normal restart, needed to handle changes to puma.socket, such as changing the Listen Stream ports.

    sudo systemctl restart puma.socket puma OR

    sudo systemctl restart puma.socket puma.service

    Note: sudo systemctl daemon-reload should be run first.

Here is a sample output from sudo systemctl status puma with puma.service and running:

● puma.service - Puma HTTP Server
   Loaded: loaded (/etc/systemd/system/puma.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2019-12-16 17:02:52 UTC; 3s ago
  Process: 10449 ExecStop=/home/deploy/.rbenv/shims/puma -S /home/deploy/my-app/config.
 Main PID: 10498 (ruby)
    Tasks: 30 (limit: 4703)
   CGroup: /system.slice/puma.service
           ├─10498 puma 3.12.1 (tcp://0.0.0.0:3000) [my-app]
           ├─10545 puma: cluster worker 0: 10498 [my-app]
           └─10549 puma: cluster worker 1: 10498 [my-app]

Dec 16 17:02:53 ip-172-31-19-238 puma[10498]: [10498] * Min threads: 5, max threads: 5
Dec 16 17:02:53 ip-172-31-19-238 puma[10498]: [10498] * Environment: production
Dec 16 17:02:53 ip-172-31-19-238 puma[10498]: [10498] * Process workers: 2
Dec 16 17:02:53 ip-172-31-19-238 puma[10498]: [10498] * Preloading application
Dec 16 17:02:54 ip-172-31-19-238 puma[10498]: [10498] * Listening on tcp://0.0.0.0:3000
Dec 16 17:02:54 ip-172-31-19-238 puma[10498]: [10498] ! WARNING: Detected 1 Thread(s) star
Dec 16 17:02:54 ip-172-31-19-238 puma[10498]: [10498] ! #<Thread:0x000055632d4e1570@/home/
Dec 16 17:02:54 ip-172-31-19-238 puma[10498]: [10498] Use Ctrl-C to stop
Dec 16 17:02:54 ip-172-31-19-238 puma[10498]: [10498] - Worker 0 (pid: 10545) booted, phas
Dec 16 17:02:54 ip-172-31-19-238 puma[10498]: [10498] - Worker 1 (pid: 10549) booted, phas

References

  1. Puma Systemd Service and Socket Configuration
  2. Managing Unicorn & Puma web servers with systemd
  3. Puma Service GitHub Gist
  4. Setting up Puma as Systemd service in Ubuntu 18