Puma and Sidekiq with Systemd and Capistrano


This post - part of my experience based of migrating apps from Heroku to Digital Ocean droplet.

Today let’s setup our Puma and Sidekiq services to run/restart after reboot and redeploy.

First of all - let’s add rules for restart commands without asking password for deploy user.

$ sudo vi /etc/sudoers

%deploy ALL=NOPASSWD:/bin/systemctl restart sidekiq
%deploy ALL=NOPASSWD:/bin/systemctl restart puma

Let’s create puma.service file:

$ sudo vi /etc/systemd/system/puma.service 

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

[Service]
Type=simple
User=deploy
Environment=RAILS_ENV=production
EnvironmentFile=/etc/environment
WorkingDirectory=/home/deploy/apps/app/current/
ExecStart=/home/deploy/.rbenv/bin/rbenv exec bundle exec puma -C /home/deploy/apps/app/shared/puma.rb
ExecStop=/home/deploy/.rbenv/bin/rbenv exec bundle exec pumactl -F /home/deploy/apps/app/shared/puma.rb stop
ExecReload=/home/deploy/.rbenv/bin/rbenv exec bundle exec pumactl -F /home/deploy/apps/app/shared/puma.rb phased-restart
Restart=always
KillMode=process

[Install]
WantedBy=multi-user.target

And sidekiq.service:

$ sudo vi /etc/systemd/system/sidekiq.service

[Unit]
Description=Sidekiq2
After=multi-user.target

[Service]
Environment=RAILS_ENV=production
EnvironmentFile=/etc/environment
WorkingDirectory=/home/deploy/apps/app/current/
ExecStart=/home/deploy/.rbenv/bin/rbenv exec bundle exec sidekiq -e production -L /home/deploy/logs/sidekiq.log -C /home/deploy/apps/app/current/config/sidekiq.yml
User=deploy
Group=deploy
UMask=0002
RestartSec=1
Restart=on-failure

[Install]
WantedBy=multi-user.target

Sample deploy.rb fragment for Capistrano:

namespace :deploy do
  desc "Restart Puma"
  task :restart_puma do
    on roles(:app), in: :sequence, wait: 5 do
      execute :sudo, :systemctl, :restart, :puma
    end
  end

  desc "Restart sidekiq"
  task :restart_sidekiq do
    on roles(:app), in: :sequence, wait: 5 do
      execute :sudo, :systemctl, :restart, :sidekiq
    end
  end

  after  :finishing,    :restart_puma
  after  :finishing,    :restart_sidekiq
end