Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
## [Unreleased]

- Make systemd unit environment variables configurable via
`:solid_queue_service_unit_env_files` and `:solid_queue_service_unit_env_vars`
(inspired by `capistrano-sidekiq`). Both fall back to shared
`:service_unit_env_files` / `:service_unit_env_vars` when set.
- Make the executed command configurable via `:solid_queue_command`
(default: `"rake solid_queue:start"`) so SolidQueue >= 0.4 setups can use
`"bin/jobs"`.
- Fix: `[Install] WantedBy=` now switches to `multi-user.target` when running
in `:system` mode (previously always `default.target`, which prevented boot
activation of system units).
- Fix: in `:system` mode the service now runs as `:solid_queue_user`
(defaults to `:run_as` → `:user`) instead of implicitly running as root.
- **Breaking**: Capistrano's `default_env` is no longer rendered into the
systemd unit file. `MALLOC_ARENA_MAX=2` is no longer hardcoded either. Pass
what you need explicitly via the new configuration hooks. `RAILS_ENV` is
still set from the current stage.

## [0.1.2] - 2025-06-12

- Quiet task only runs on :solid_queue_role [#3](https://github.com/codeur/capistrano-solid_queue/pull/5) by [@bashcoder](https://github.com/bashcoder)
Expand Down
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,56 @@ through their Capistrano counterparts, ex: `bundle exec cap solid_queue:restart`
The plugin has registered a Capistrano `hook` to run `bundle exec cap solid_queue:restart` after deploy.
See [`#register_hooks`](lib/capistrano/solid_queue.rb)

## Configuration

The following variables can be set in your `deploy.rb` or stage files:

```ruby
set :solid_queue_role, :app
set :solid_queue_access_log, -> { File.join(shared_path, "log", "solid_queue.log") }
set :solid_queue_error_log, -> { File.join(shared_path, "log", "solid_queue.log") }
set :solid_queue_service_unit_name, -> { "#{fetch(:application)}_solid_queue_#{fetch(:stage)}" }
set :solid_queue_systemctl_user, :user # or :system

# What runs after `bundle exec` — override for SolidQueue >= 0.4:
set :solid_queue_command, "bin/jobs"

# Unix user for the service when running in :system mode
# (defaults to :run_as, then to Capistrano's :user)
set :solid_queue_user, "deploy"
```

### Environment variables

Two hooks let you inject arbitrary environment into the generated systemd unit
(inspired by [`capistrano-sidekiq`](https://github.com/seuros/capistrano-sidekiq)):

```ruby
# Referenced via `EnvironmentFile=` — one line per file
set :solid_queue_service_unit_env_files, %w[
/etc/environment
/home/deploy/apps/my_app/shared/.env
]

# Rendered as `Environment="KEY=VALUE"` — one line per entry
set :solid_queue_service_unit_env_vars, [
"RAILS_LOG_TO_STDOUT=1",
"DB_POOL=10",
"SOLID_QUEUE_IN_PUMA=false"
]
```

If your project already sets `:service_unit_env_files` / `:service_unit_env_vars`
(shared with other systemd-based capistrano plugins), they are picked up as
the default — you only need to override when SolidQueue should see a different
set of variables.

Only `RAILS_ENV=<stage>` is set implicitly (it is derived directly from the
Capistrano stage). Capistrano's `default_env` is **not** rendered into the unit
file — pass anything else you need (including tuning knobs like
`MALLOC_ARENA_MAX`) via `:solid_queue_service_unit_env_vars` or
`:solid_queue_service_unit_env_files`.

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
Expand Down
13 changes: 13 additions & 0 deletions lib/capistrano/solid_queue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@ def set_defaults
set_if_empty :solid_queue_error_log, -> { File.join(shared_path, "log", "solid_queue.log") }
set_if_empty :solid_queue_service_unit_name, -> { "#{fetch(:application)}_solid_queue_#{fetch(:stage)}" }
set_if_empty :solid_queue_systemd_conf_dir, -> { fetch_systemd_unit_path }

# Command executed by the systemd unit (concatenated after `bundle exec`).
# Override with e.g. "bin/jobs" for SolidQueue >= 0.4 setups.
set_if_empty :solid_queue_command, "rake solid_queue:start"

# Unix user the service runs as when using `:system` mode. Falls back to
# `:run_as` (shared with other systemd capistrano plugins) and finally
# the SSH `:user` capistrano connects with.
set_if_empty :solid_queue_user, -> { fetch(:run_as, fetch(:user)) }

# SolidQueue could have a stripped down or more complex version of the environment variables
set_if_empty :solid_queue_service_unit_env_files, -> { fetch(:service_unit_env_files, []) }
set_if_empty :solid_queue_service_unit_env_vars, -> { fetch(:service_unit_env_vars, []) }
end

def define_tasks
Expand Down
17 changes: 10 additions & 7 deletions lib/capistrano/templates/solid_queue.service.erb
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
[Unit]
Description=SolidQueue background job
Description=SolidQueue background job for <%= "#{fetch(:application)} (#{fetch(:stage)})" %>
After=syslog.target network.target

[Service]
Type=simple
Environment='RAILS_ENV=<%= fetch(:stage) %>'
<% fetch(:default_env).reject{ |k, _| k.to_s == 'path' }.each do |variable, value| -%>
Environment='<%= variable.to_s.upcase %>=<%= value.to_s %>'
<%= "User=#{fetch(:solid_queue_user)}" if fetch(:solid_queue_systemctl_user) == :system %>
Environment=RAILS_ENV=<%= fetch(:stage) %>
<% Array(fetch(:solid_queue_service_unit_env_files)).each do |file| -%>
EnvironmentFile=<%= file %>
<% end -%>
<% Array(fetch(:solid_queue_service_unit_env_vars)).each do |environment_variable| -%>
Environment="<%= environment_variable %>"
<% end -%>
WorkingDirectory=<%= current_path %>
ExecStart=<%= capture(:echo, SSHKit.config.command_map[:bundle]).strip %> exec rake solid_queue:start
ExecStart=<%= capture(:echo, SSHKit.config.command_map[:bundle]).strip %> exec <%= fetch(:solid_queue_command) %>
ExecReload=/bin/kill -TSTP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
Environment=MALLOC_ARENA_MAX=2

# if we crash, restart
RestartSec=1
Expand All @@ -24,4 +27,4 @@ Restart=on-failure
SyslogIdentifier=<%= fetch(:solid_queue_service_unit_name) %>

[Install]
WantedBy=default.target
WantedBy=<%= fetch(:solid_queue_systemctl_user) == :system ? "multi-user.target" : "default.target" %>