Rob Zolkos
February 21, 2024
(How I) Deploy Solid Queue with Capistrano
I manage a small number of Rails apps that haven’t yet migrated to Kamal for deployment but I wanted to migrate to solid_queue asap to reduce the service burden of running redis.
These applications are deployed with Capistrano on Ubuntu LTS servers and the solid_queue is managed by linux’s systemd. There isn’t much information out there on how to deploy solid_queue with Capistrano so hopefully this helps those of you that still use this popular way of deploying Rails applications.
The systemd service is defined in a file located in your deploy users home folder
/home/<deploy user>/.config/systemd/user/solid_queue.service
It looks like this (you may want to update Ruby versions and paths and such)
[Unit]
Description=solid_queue for app
After=syslog.target network.target
[Service]
Type=simple
Environment=RAILS_ENV=production
WorkingDirectory=/home/<deploy user>/apps/<app name>/current
ExecStart=/usr/local/bin/chruby-exec ruby-3.3.0 -- bundler exec rake solid_queue:start
ExecReload=/bin/kill -TSTP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
Environment=MALLOC_ARENA_MAX=2
RestartSec=1
Restart=on-failure
SyslogIdentifier=solid_queue
[Install]
WantedBy=default.target
Once you have this file in place you need to enable it, start it and ensure that it runs even when your deploy user is logged out.
Reload the daemon so the new service is loaded
systemctl --user daemon-reload
Start the service
systemctl --user start solid_queue.service
Enable the service to start at boot
systemctl --user enable solid_queue.service
Enable the service to keep running when deploy user is logged out
sudo loginctl enable-linger
That should be the systemd part done. Next up is getting Capistrano configured to stop and start the solid_queue service during a deployment.
Here is the config I use in my deploy.rb file to get solid_queue systemd service to restart.
set :solid_queue_systemd_unit_name, "solid_queue.service"
namespace :solid_queue do
desc "Quiet solid_queue (start graceful termination)"
task :quiet do
on roles(:app) do
execute :systemctl, "--user", "kill", "-s", "SIGTERM", fetch(:solid_queue_systemd_unit_name), raise_on_non_zero_exit: false
end
end
desc "Stop solid_queue (force immediate termination)"
task :stop do
on roles(:app) do
execute :systemctl, "--user", "kill", "-s", "SIGQUIT", fetch(:solid_queue_systemd_unit_name), raise_on_non_zero_exit: false
end
end
desc "Start solid_queue"
task :start do
on roles(:app) do
execute :systemctl, "--user", "start", fetch(:solid_queue_systemd_unit_name)
end
end
desc "Restart solid_queue"
task :restart do
on roles(:app) do
execute :systemctl, "--user", "restart", fetch(:solid_queue_systemd_unit_name)
end
end
end
# SolidQueue hooks
after "deploy:starting", "solid_queue:quiet"
after "deploy:updated", "solid_queue:stop"
after "deploy:published", "solid_queue:start"
after "deploy:failed", "solid_queue:restart"
That is all I needed to do. No extra gems. It all works smoothly, you will see the solid_queue workers shutdown and then start again after the app is deployed.
Let me know if you see anything that can be improved.