This website is served by a combination of Nginx and Puma on a Ubuntu host (all on a virtual private server in the cloud somewhere). It took some time to get all of these components talking to each other in the way that I wanted. System administration has always been a hobby of mine ever since taking up programming, however I am in no way an expert. This is as much for others as it is for my self. Without a doubt it will be useful in my future as I build and maintain servers, and in the mean time it may also help someone else struggling with a similar setup.
This assumes Puma is serving a Ruby on Rails application. I am also using Capistrano for deployment, which determines the folder structures used in the configuration files.
Here is the Puma configuration script living at /var/www/my-app/shared/puma.rb
.
environment "production"
bind "unix:///var/www/my-app/shared/tmp/sockets/puma.sock"
pidfile "/var/www/my-app/shared/tmp/pids/puma.pid"
state_path "/var/www/my-app/shared/tmp/pids/puma.state"
directory "/var/www/my-app/current"
rackup "/var/www/my-app/current/config.ru"
stdout_redirect "/var/www/my-app/shared/log/puma_access.log", "/var/www/my-app/shared/log/puma_error.log", true
workers 0
threads 0,16
activate_control_app "unix:///var/www/my-app/shared/tmp/sockets/pumactl.sock"
prune_bundler
Definitely be sure to tweak all the settings as needed. Also note that the typical daemonize true
line is not present in this configuration. This is key to make managing Puma with Systemd simpler.
Next is the Systemd configuration file for the Puma application server in /etc/systemd/system/puma.service
.
[Unit]
Description=Puma application server
After=network.target
[Service]
Type=simple
User=deploy
Group=deploy
WorkingDirectory=/var/www/my-app/current
Environment=RAILS_ENV=production
ExecStart=/home/my-user/.rbenv/shims/bundle exec puma -C /var/www/my-app/shared/puma.rb --pidfile /var/www/my-app/shared/tmp/pids/puma.pid -e production
ExecStop=/home/my-user/.rbenv/shims/bundle exec pumactl -S /var/www/my-app/shared/tmp/pids/puma.state stop
ExecReload=/home/my-user/.rbenv/shims/bundle exec pumactl -S /var/www/my-app/shared/tmp/pids/puma.state phased-restart
Restart=always
KillMode=process
[Install]
WantedBy=multi-user.target
If daemonize true
is included in the Puma configuration, then the Systemd configuration would need to include something like PIDFile=/var/www/my-app/shared/tmp/pids/puma.pid
(a value set at the top of the Puma configuration file).
With these two files in place, the typical Systemd commands all behave as expected status
, start
, stop
, restart
, etc. Assuming everything else (Nginx, database, etc.) is setup properly, Puma should boot back up and be serving the application if the host machine ever needs to be restarted.