[NEW] Szukaj pracy anonimowo — sprawdź szczegóły
Close

Rails 8 with Solid Queue 1.1 deployed with Capistrano

While configuring my Ruby on Rails application, I ran into unexpected challenges setting up Solid Queue 1.1.3. With PostgreSQL as the database and Capistrano handling deployments (though I haven’t explored Kamal yet), I anticipated a straightforward setup—but version 1 introduced some complexities.

After researching blog posts, GitHub issues, and troubleshooting along the way, I’ve compiled this guide to help others overcome similar configuration hurdles more easily.


Server setup

I use the one Fotbo VPS (referral link) with Postgres manually preinstalled and configured Capistrano for deployment on Debian 12. To run Solid Queue, I set up systemd as was mentioned in the first good documentation I found from Rob Zolkos.

So, we need to define the systemd service in a file located in your deploy users home folder (in my case, the use name is deploy):

/home/deploy/.config/systemd/user/solid_queue.service

Insert the configurations (change the <my app> and /home/deploy/.rbenv/shims/ruby to your values):

[Unit]
Description=solid_queue for my app
After=syslog.target network.target

[Service]
Type=simple
Environment=RAILS_ENV=production
WorkingDirectory=/home/deploy/<my app>/current
ExecStart=/home/deploy/.rbenv/shims/ruby -- /home/deploy/<my app>/current/bin/jobs
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

Take a note to the ExecStart command, since the Solid Queue changed the way to start the service I used the binstub command, previously it was rake solid_queue:start 

Reload the daemon after adding the configurations so the new service is loaded:

$ systemctl --user daemon-reload

Start the service:

$ systemctl --user start solid_queue.service

Check the status:

$ systemctl --user status solid_queue.service
● solid_queue.service — solid_queue for my_app
     Loaded: loaded (/home/deploy/.config/systemd/user/solid_queue.service; enabled; preset: enabled)
     Active: active (running) since Sat 2025-02-22 10:23:51 UTC; 24h ago
...

Enable the service to start at boot:

$ systemctl --user enable solid_queue.service

Enable the service to keep running when the deploy user is logged out:

$ sudo loginctl enable-linger

This is all that you should do on the server.


Application setup

Solid Queue gem

I created the app using Rails 8, so the Solid Queue gem was already added to the Gemfile. But in case you are migrating from Rails 7, just follow the gem's documentation:

$ bundle add solid_queue
$ bin/rails solid_queue:install

This will configure Solid Queue as the production Active Job backend, create the configuration files config/queue.yml and config/recurring.yml, and create the db/queue_schema.rb. It'll also create a bin/jobs executable wrapper that you can use to start Solid Queue.
Once you've done that, you will then have to add the configuration for the queue database in config/database.yml

Solid Queue README
# config/database.yml

production:
  primary: &primary_production
    <<: *default
    database: app_production
    username: app
    password: <%= ENV["APP_DATABASE_PASSWORD"] %>
  queue:
    <<: *primary_production
    database: app_production_queue
    migrations_paths: db/queue_migrate

Check the config/environments/production.rb so it has these lines:

  config.active_job.queue_adapter = :solid_queue
  config.solid_queue.connects_to = { database: { writing: :queue } }

Then run db:prepare in production to ensure the database is created and the schema is loaded. In my case this command didn't create the database, so I created  it manually, but for some reason I received the  PG::UndefinedTable: ERROR:  relation "solid_queue_jobs" does not exist error when I tried to schedule the  job for later.

After the investigation, I found the Loading schema in production GitHub Issue where as temporal solution was this suggestion to loaded the schema in a rails console with:

ActiveRecord::Base.establish_connection(:queue)
load 'db/queue_schema.rb'

After that, my background job was successfully scheduled 🎉!


Capistrano setup

To get the solid_queue systemd service to restart during the deployment, I added these tasks to deploy.rb file:

# solid queue
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

after "deploy:starting", "solid_queue:quiet"
after "deploy:updated", "solid_queue:stop"
after "deploy:published", "solid_queue:start"
after "deploy:failed", "solid_queue:restart"

So when you run cap production deploy the solid_queue  service will be restarted automatically by Capistrano.


Mission Control — Jobs

This gem provides a Rails-based frontend to Active Job adapters. If you are familiar with Sidekiq Dashboard, this gem does the same for the Solid Queue jobs, in a separate route, it gives you the ability to check all the background jobs statistics, pause, restart failed, etc. 

The setup is simple:

$ bundle add mission_control-jobs
$ bin/rails mission_control:jobs:authentication:configure

In the prompt, you need to set the user name for the basic auth, these credentials will be saved in the Rails.application.credentials

mission_control:
  http_basic_auth_user: dev
  http_basic_auth_password: secret

Mount Mission Control Job's engine where you wish to have it accessible from your app, in your routes.rb file:

Rails.application.routes.draw do
  # ...
  mount MissionControl::Jobs::Engine, at: "/jobs"

Now you can open the /jobs path in your browser, enter the credentials you added, and you should see the Mission Control:

the Mission Control page
the Mission Control page

This is how it looks on my fresh set up.


Conclusion

Ruby on Rails is a powerful framework that enables fast development. However, you might encounter challenges due to changes in configurations and approaches across different open-source gems. Fortunately, the community is welcoming, and you can always find tips, suggestions, and assistance. If you haven't already, consider sharing your knowledge or joining the community. Here's a post on why Rails is excellent for solo development.


Avatar
Ruby on Rails Developer
Gru 10
Why Ruby on Rails is Ideal for Solo Developers
Discover the joys of Ruby on Rails! Explore its supportive community, rapid development, and career potential in this insightful blog post.
Sty 31
Model-View-Controller in Ruby on Rails
The article explains the roles of the Model, View, and Controller in a Ruby on Rails application.
Gru 30
Getting Started with Rails: The Basics Every Developer Should Know
In this article, I’ll guide you through the initial steps for setting up your development environment, installing the necessary tools, and starting your journey as a Ruby on Rails developer.

Ta strona używa plików cookie, aby zapewnić Ci lepsze wrażenia podczas przeglądania.

Dowiedz się więcej o tym, jak używamy plików cookie i jak zmienić preferencje dotyczące plików cookie w naszej Polityka plików cookie.

Zmień ustawienia
Zapisz Akceptuj wszystkie cookies