capistrano3-puma 6.0.0 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b0d265909a3107947404ed854ac684f27f5bbd65cc9aea7fd9efb39c1aa3b42f
4
- data.tar.gz: f4c31b71706468b2c090a8ef00a21e4df9766bf99e6dedc70f1d78f47dc49f06
3
+ metadata.gz: a0e3b56cceac3a829240f070437a0e232c5c79f38370989572024ab08af9038a
4
+ data.tar.gz: 67e21b9c665facae205f009b694d6a2652c0a9546c95a3db3739fac5c5a0159f
5
5
  SHA512:
6
- metadata.gz: 43cc928a86e88f01c25739b9f94716b00cbbe3233618a4f05a8c4079bc8a77529ec8de2631b3ceb561a246e807dec15ca4448f0b1e76f4fd497d78b172e3e6d5
7
- data.tar.gz: ef9e24fd09b905f096a8452ac9f84c78d385e4c1d75e20ec99c209cbcc9587dfffdb8942c9c17358f47ce7613f770d47bef81c8dd549d7abc46134d634c63590
6
+ metadata.gz: 3c216aed4f83378c3ecf0a2bb0cab5c7046eb1a2ad9bf280691ea4325e6d583dbf98640c14e7c8e793eb8ee9c3645d2c0da17b9205e20db3c48b330fa4ed80ed
7
+ data.tar.gz: 4b19a5a3c2513402c5987ec0e501e5dcb19d7fb47e80b3ad4eec037d1a4171c1ba9645c0bad51f8cc28f5c8f16f215084015f1e32861784fd13ccbe364a995a1
data/CHANGELOG.md CHANGED
@@ -1,7 +1,24 @@
1
1
  # Changelog
2
2
 
3
- [Unreleased](https://github.com/seuros/capistrano-puma/compare/v5.2.0...master)
4
- - Removed support for support for monit and upstart. (will add them back if someone is willing to maintain them)
3
+ ## [6.2.0](https://github.com/seuros/capistrano-puma/tree/6.2.0) (2025-06-22)
4
+
5
+ [Full Changelog](https://github.com/seuros/capistrano-puma/compare/v6.1.0...6.2.0)
6
+ - Harmonized interface with capistrano-sidekiq for better ecosystem consistency
7
+ - Aligned configuration variable naming patterns
8
+ - Unified systemd command execution methods
9
+ - Standardized template search order across both gems
10
+ - Added documentation reference to example application
11
+
12
+ ## [6.1.0](https://github.com/seuros/capistrano-puma/tree/6.1.0) (2025-01-21)
13
+
14
+ [Full Changelog](https://github.com/seuros/capistrano-puma/compare/v6.0.0...6.1.0)
15
+ - Restored default value for `puma_bind` to fix socket activation (Issue #387)
16
+ - Added documentation for puma.rb symlink requirement in v6.0.0 (Issue #384)
17
+ - Made WatchdogSec configurable via `puma_systemd_watchdog_sec` (Issue #373)
18
+ - Improved documentation for first-time setup and troubleshooting (Issues #377, #376, #372)
19
+ - Added migration guide for upgrading from v5 to v6
20
+ - Added troubleshooting section for common issues
21
+ - Removed support for monit and upstart (will add them back if someone is willing to maintain them)
5
22
  - Sync configuration with capistrano-sidekiq
6
23
  - Support for notify systemd service. Add sd_notify gem to your Gemfile.
7
24
  - Add example application for easier testing.
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2013-2022 Abdelkader Boudih
3
+ Copyright (c) 2013-2025 Abdelkader Boudih
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,6 +1,17 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/capistrano3-puma.svg)](http://badge.fury.io/rb/capistrano3-puma)
2
2
  # Capistrano::Puma
3
3
 
4
+ Puma integration for Capistrano - providing systemd service management and zero-downtime deployments for Puma 5.1+.
5
+
6
+ ## Example Application
7
+
8
+ For a complete working example of this gem in action, see the [capistrano-example-app](https://github.com/seuros/capistrano-example-app) which demonstrates:
9
+ - Rails 8.0 deployment with Capistrano
10
+ - Puma 6.0 with systemd socket activation
11
+ - Zero-downtime deployments
12
+ - rbenv integration
13
+ - Nginx configuration examples
14
+
4
15
  ## Installation
5
16
 
6
17
  Add this line to your application's Gemfile:
@@ -15,6 +26,34 @@ And then execute:
15
26
 
16
27
  $ bundle
17
28
 
29
+ ## Upgrading from Version 5.x to 6.x
30
+
31
+ Version 6.0 includes several breaking changes:
32
+
33
+ ### Breaking Changes:
34
+ 1. **Manual Puma Configuration**: The gem no longer generates `puma.rb` automatically
35
+ - You must create your own `config/puma.rb` in your repository
36
+ - Add it to `linked_files` in your `deploy.rb`
37
+
38
+ 2. **Default puma_bind Removed**: You must explicitly set the bind address
39
+ ```ruby
40
+ set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.sock"
41
+ ```
42
+
43
+ 3. **Systemd Service Changes**: Services are now user-specific by default
44
+ - Services are created in `~/.config/systemd/user/`
45
+ - Run `cap production puma:install` again after upgrading
46
+
47
+ ### Migration Steps:
48
+ 1. Create your `config/puma.rb` if you don't have one
49
+ 2. Add to your `deploy.rb`:
50
+ ```ruby
51
+ append :linked_files, 'config/puma.rb'
52
+ set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.sock"
53
+ ```
54
+ 3. Run `cap production puma:install` to update the systemd service
55
+ 4. Deploy as normal
56
+
18
57
  ## Usage
19
58
  ```ruby
20
59
  # Capfile
@@ -43,17 +82,53 @@ To make it work with rvm, rbenv and chruby, install the plugin after correspondi
43
82
  ### Config
44
83
 
45
84
  Puma configuration is expected to be in `config/puma.rb` or `config/puma/#{fetch(:puma_env)}.rb` and checked in your repository.
46
- Uploading the configuration via capistrano was removed as it was causing problems with custom configurations.
47
85
 
48
- ### Deployment
86
+ Starting with version 6.0.0, you need to manage the puma configuration file yourself. Here are the steps:
49
87
 
50
- Before running `$ bundle exec cap {stage} deploy` for the first time, install Puma on the deployment server. For example, if stage=production:
51
- ```
88
+ 1. Create your puma configuration in `shared/config/puma.rb` on the server
89
+ 2. Add it to linked_files in your `deploy.rb`:
90
+ ```ruby
91
+ append :linked_files, 'config/puma.rb'
92
+ ```
93
+
94
+ This ensures the puma configuration persists across deployments. The systemd service will start puma with `puma -e <environment>` from your app's current directory.
95
+
96
+ ### First-Time Setup (IMPORTANT! 🎉)
97
+
98
+ **🙋 Hey there, human! Read this magical section and save yourself from confusion! 😊**
99
+
100
+ Before your first deployment, you MUST install the Puma systemd service on your server:
101
+
102
+ ```bash
103
+ # ✨ This only needs to be done once per server/stage - it's like a first date! 💝
52
104
  $ bundle exec cap production puma:install
53
105
  ```
54
106
 
55
- To uninstall,
107
+ This command will:
108
+ - 🏗️ Create the systemd service files for Puma
109
+ - 🚀 Enable the service to start on boot
110
+ - 🔐 Set up the proper user permissions
111
+
112
+ **🎭 Plot twist:** Without running this command first, your deployment will succeed but Puma won't start! (We know, it's sneaky like that 😅)
113
+
114
+ ### Deployment
115
+
116
+ After the initial setup, normal deployments will work as expected:
117
+ ```bash
118
+ $ bundle exec cap production deploy
119
+ ```
120
+
121
+ The deployment process will automatically restart Puma using the installed systemd service.
122
+
123
+ To manually control the Puma service:
124
+ ```bash
125
+ $ bundle exec cap production puma:start
126
+ $ bundle exec cap production puma:stop
127
+ $ bundle exec cap production puma:restart
56
128
  ```
129
+
130
+ To uninstall the systemd service:
131
+ ```bash
57
132
  $ bundle exec cap production puma:uninstall
58
133
  ```
59
134
 
@@ -100,6 +175,8 @@ Configurable options, shown here with defaults: Please note the configuration op
100
175
  ```ruby
101
176
  set :puma_user, fetch(:user)
102
177
  set :puma_role, :web
178
+ set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.sock"
179
+ set :puma_systemd_watchdog_sec, 10 # Set to 0 or false to disable watchdog
103
180
  set :puma_service_unit_env_files, []
104
181
  set :puma_service_unit_env_vars, []
105
182
  ```
@@ -109,6 +186,35 @@ __Notes:__ If you are setting values for variables that might be used by other p
109
186
  append :rbenv_map_bins, 'puma', 'pumactl'
110
187
  ```
111
188
 
189
+ ## Troubleshooting
190
+
191
+ ### Puma is not starting after deployment
192
+ - Ensure you ran `cap production puma:install` before your first deployment
193
+ - Check the service status: `cap production puma:status`
194
+ - Check logs: `sudo journalctl -u your_app_puma_production -n 100`
195
+
196
+ ### Nginx 502 Bad Gateway errors
197
+ This usually means nginx and puma have mismatched configurations:
198
+ - If nginx expects a unix socket but puma binds to a port (or vice versa)
199
+ - Ensure your `puma_bind` in deploy.rb matches your nginx upstream configuration
200
+ - Common configurations:
201
+ ```ruby
202
+ # Unix socket (default)
203
+ set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.sock"
204
+
205
+ # TCP port
206
+ set :puma_bind, "tcp://0.0.0.0:3000"
207
+ ```
208
+
209
+ ### Puma keeps restarting (systemd watchdog kills it)
210
+ - Your app may take longer than 10 seconds to boot
211
+ - Disable or increase WatchdogSec (requires version 6.0.0+):
212
+ ```ruby
213
+ set :puma_systemd_watchdog_sec, 30 # 30 seconds
214
+ # or
215
+ set :puma_systemd_watchdog_sec, 0 # Disable watchdog
216
+ ```
217
+
112
218
  # Nginx documentation
113
219
  Nginx documentation was moved to [nginx.md](docs/nginx.md)
114
220
 
@@ -14,6 +14,7 @@ module Capistrano
14
14
  set_if_empty :puma_systemctl_bin, -> { fetch(:systemctl_bin, '/bin/systemctl') }
15
15
  set_if_empty :puma_service_unit_name, -> { "#{fetch(:application)}_puma_#{fetch(:stage)}" }
16
16
  set_if_empty :puma_enable_socket_service, false
17
+ set_if_empty :puma_systemd_watchdog_sec, 10
17
18
 
18
19
  set_if_empty :puma_service_unit_env_files, -> { fetch(:service_unit_env_files, []) }
19
20
  set_if_empty :puma_service_unit_env_vars, -> { fetch(:service_unit_env_vars, []) }
@@ -25,10 +26,6 @@ module Capistrano
25
26
  set_if_empty :puma_service_templates_path, fetch(:service_templates_path, 'config/deploy/templates')
26
27
  end
27
28
 
28
- def expanded_bundle_command
29
- backend.capture(:echo, SSHKit.config.command_map[:bundle]).strip
30
- end
31
-
32
29
  def fetch_systemd_unit_path
33
30
  if fetch(:puma_systemctl_user) == :system
34
31
  "/etc/systemd/system/"
@@ -6,18 +6,18 @@ module Capistrano
6
6
  def puma_switch_user(role, &block)
7
7
  user = puma_user(role)
8
8
  if user == role.user
9
- block.call
9
+ yield
10
10
  else
11
- backend.as user do
12
- block.call
13
- end
11
+ backend.as(user, &block)
14
12
  end
15
13
  end
16
14
 
17
15
  def puma_user(role)
18
16
  properties = role.properties
17
+ return role.user unless properties
18
+
19
19
  properties.fetch(:puma_user) || # local property for puma only
20
- fetch(:puma_user) ||
20
+ fetch(:puma_user, nil) ||
21
21
  properties.fetch(:run_as) || # global property across multiple capistrano gems
22
22
  role.user
23
23
  end
@@ -53,11 +53,7 @@ module Capistrano
53
53
  File.expand_path("../templates/#{from}.rb.erb", __FILE__)
54
54
  ].detect { |path| File.file?(path) }
55
55
  erb = File.read(file)
56
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.6')
57
- StringIO.new(ERB.new(erb, nil, '-').result(binding))
58
- else
59
- StringIO.new(ERB.new(erb, trim_mode: '-').result(binding))
60
- end
56
+ StringIO.new(ERB.new(erb, trim_mode: '-').result(binding))
61
57
  end
62
58
 
63
59
  def template_puma(from, to, role)
@@ -102,6 +98,10 @@ module Capistrano
102
98
  PumaBind.new(m, etype.to_sym, address)
103
99
  end
104
100
  end
101
+
102
+ def expanded_bundle_command
103
+ backend.capture(:echo, SSHKit.config.command_map[:bundle]).strip
104
+ end
105
105
  end
106
106
 
107
107
  class Puma < Capistrano::Plugin
@@ -109,9 +109,10 @@ module Capistrano
109
109
 
110
110
  def set_defaults
111
111
  set_if_empty :puma_role, :web
112
- set_if_empty :puma_env, -> { fetch(:rack_env, fetch(:rails_env, fetch(:stage))) }
112
+ set_if_empty :puma_env, -> { fetch(:rack_env, fetch(:rails_env, fetch(:rake_env, fetch(:stage)))) }
113
+ set_if_empty :puma_bind, -> { "unix://#{File.join(shared_path, 'tmp', 'sockets', 'puma.sock')}" }
113
114
  set_if_empty :puma_access_log, -> { File.join(shared_path, 'log', "puma.log") }
114
- set_if_empty :puma_error_log, -> { File.join(shared_path, 'log', "puma.log") }
115
+ set_if_empty :puma_error_log, -> { File.join(shared_path, 'log', "puma_error.log") }
115
116
 
116
117
  # Chruby, Rbenv and RVM integration
117
118
  append :chruby_map_bins, 'puma', 'pumactl' if fetch(:chruby_map_bins)
@@ -16,10 +16,16 @@ After=syslog.target network.target
16
16
 
17
17
  [Service]
18
18
  Type=<%= service_unit_type %>
19
- WatchdogSec=10
19
+ <% if fetch(:puma_systemd_watchdog_sec) && fetch(:puma_systemd_watchdog_sec) > 0 %>
20
+ WatchdogSec=<%= fetch(:puma_systemd_watchdog_sec) %>
21
+ <% end %>
20
22
  <%="User=#{puma_user(@role)}" if fetch(:puma_systemctl_user) == :system %>
21
23
  WorkingDirectory=<%= current_path %>
24
+ <% if fetch(:puma_use_login_shell) %>
25
+ ExecStart=/bin/bash -lc '<%= expanded_bundle_command %> exec puma -e <%= fetch(:puma_env) %>'
26
+ <% else %>
22
27
  ExecStart=<%= expanded_bundle_command %> exec puma -e <%= fetch(:puma_env) %>
28
+ <% end %>
23
29
  ExecReload=/bin/kill -USR1 $MAINPID
24
30
  <%- Array(fetch(:puma_service_unit_env_files)).each do |file| %>
25
31
  <%="EnvironmentFile=#{file}" -%>
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano3-puma
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.0
4
+ version: 6.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-01 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: capistrano
@@ -98,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
98
  - !ruby/object:Gem::Version
99
99
  version: '0'
100
100
  requirements: []
101
- rubygems_version: 3.6.2
101
+ rubygems_version: 3.6.7
102
102
  specification_version: 4
103
103
  summary: Puma integration for Capistrano
104
104
  test_files: []