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
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
[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
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
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.