capistrano3-puma 3.1.1 → 8.0.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 +5 -5
- data/CHANGELOG.md +345 -48
- data/LICENSE.txt +1 -1
- data/README.md +149 -75
- data/lib/capistrano/puma/nginx.rb +2 -0
- data/lib/capistrano/puma/systemd.rb +61 -0
- data/lib/capistrano/puma.rb +67 -62
- data/lib/capistrano/tasks/nginx.rake +8 -0
- data/lib/capistrano/tasks/systemd.rake +139 -0
- data/lib/capistrano/templates/nginx_conf.erb +17 -9
- data/lib/capistrano/templates/puma.service.erb +60 -0
- data/lib/capistrano/templates/puma.socket.erb +22 -0
- data/lib/generators/capistrano/nginx_puma/config_generator.rb +0 -1
- metadata +19 -32
- data/.gitignore +0 -18
- data/CONTRIBUTORS.md +0 -47
- data/Gemfile +0 -4
- data/Rakefile +0 -1
- data/capistrano3-puma.gemspec +0 -28
- data/lib/capistrano/puma/jungle.rb +0 -22
- data/lib/capistrano/puma/monit.rb +0 -34
- data/lib/capistrano/puma/version.rb +0 -3
- data/lib/capistrano/puma/workers.rb +0 -9
- data/lib/capistrano/tasks/jungle.rake +0 -65
- data/lib/capistrano/tasks/monit.rake +0 -61
- data/lib/capistrano/tasks/puma.rake +0 -100
- data/lib/capistrano/tasks/workers.rake +0 -43
- data/lib/capistrano/templates/puma-deb.erb +0 -421
- data/lib/capistrano/templates/puma-rpm.erb +0 -328
- data/lib/capistrano/templates/puma.rb.erb +0 -52
- data/lib/capistrano/templates/puma_monit.conf.erb +0 -7
- data/lib/capistrano/templates/run-puma.erb +0 -20
data/README.md
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
[](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,92 +26,147 @@ 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
|
|
21
60
|
|
|
22
61
|
require 'capistrano/puma'
|
|
23
62
|
install_plugin Capistrano::Puma # Default puma tasks
|
|
24
|
-
install_plugin Capistrano::Puma::
|
|
25
|
-
install_plugin Capistrano::Puma::Jungle # if you need the jungle tasks
|
|
26
|
-
install_plugin Capistrano::Puma::Monit # if you need the monit tasks
|
|
27
|
-
install_plugin Capistrano::Puma::Nginx # if you want to upload a nginx site template
|
|
63
|
+
install_plugin Capistrano::Puma::Systemd
|
|
28
64
|
```
|
|
29
65
|
|
|
30
66
|
To prevent loading the hooks of the plugin, add false to the load_hooks param.
|
|
31
67
|
```ruby
|
|
32
68
|
# Capfile
|
|
33
69
|
|
|
34
|
-
require 'capistrano/puma'
|
|
35
70
|
install_plugin Capistrano::Puma, load_hooks: false # Default puma tasks without hooks
|
|
36
|
-
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
To make it work with rvm, rbenv and chruby, install the plugin after corresponding library inclusion.
|
|
74
|
+
```ruby
|
|
75
|
+
# Capfile
|
|
76
|
+
|
|
77
|
+
require 'capistrano/rbenv'
|
|
78
|
+
require 'capistrano/puma'
|
|
79
|
+
install_plugin Capistrano::Puma
|
|
37
80
|
```
|
|
38
81
|
|
|
39
82
|
### Config
|
|
40
83
|
|
|
41
|
-
|
|
84
|
+
Puma configuration is expected to be in `config/puma.rb` or `config/puma/#{fetch(:puma_env)}.rb` and checked in your repository.
|
|
42
85
|
|
|
43
|
-
|
|
44
|
-
```ruby
|
|
45
|
-
cap production puma:config
|
|
46
|
-
```
|
|
47
|
-
By default the file located in `shared/puma.config`
|
|
86
|
+
Starting with version 6.0.0, you need to manage the puma configuration file yourself. Here are the steps:
|
|
48
87
|
|
|
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
|
+
```
|
|
49
93
|
|
|
50
|
-
|
|
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.
|
|
51
95
|
|
|
52
|
-
|
|
96
|
+
### First-Time Setup (IMPORTANT! 🎉)
|
|
53
97
|
|
|
54
|
-
|
|
98
|
+
**🙋 Hey there, human! Read this magical section and save yourself from confusion! 😊**
|
|
55
99
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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! 💝
|
|
104
|
+
$ bundle exec cap production puma:install
|
|
59
105
|
```
|
|
60
106
|
|
|
61
|
-
|
|
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
|
|
62
119
|
```
|
|
63
|
-
|
|
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
|
|
64
128
|
```
|
|
65
129
|
|
|
66
|
-
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
set :nginx_sites_enabled_path, "/etc/nginx/sites-enabled"
|
|
130
|
+
To uninstall the systemd service:
|
|
131
|
+
```bash
|
|
132
|
+
$ bundle exec cap production puma:uninstall
|
|
70
133
|
```
|
|
71
134
|
|
|
72
|
-
|
|
73
|
-
```ruby
|
|
74
|
-
set :puma_nginx, :foo
|
|
135
|
+
### Full Task List
|
|
75
136
|
```
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
137
|
+
$ cap -T puma
|
|
138
|
+
cap puma:disable # Disable Puma systemd service
|
|
139
|
+
cap puma:enable # Enable Puma systemd service
|
|
140
|
+
cap puma:install # Install Puma systemd service
|
|
141
|
+
cap puma:reload # Reload Puma service via systemd
|
|
142
|
+
cap puma:restart # Restart Puma service via systemd
|
|
143
|
+
cap puma:restart_socket # Restart Puma socket via systemd
|
|
144
|
+
cap puma:smart_restart # Restarts or reloads Puma service via systemd
|
|
145
|
+
cap puma:start # Start Puma service via systemd
|
|
146
|
+
cap puma:status # Get Puma service status via systemd
|
|
147
|
+
cap puma:stop # Stop Puma service via systemd
|
|
148
|
+
cap puma:stop_socket # Stop Puma socket via systemd
|
|
149
|
+
cap puma:uninstall # Uninstall Puma systemd service
|
|
79
150
|
```
|
|
151
|
+
## Example
|
|
80
152
|
|
|
81
|
-
|
|
153
|
+
A sample application is provided to show how to use this gem at https://github.com/seuros/capistrano-example-app
|
|
82
154
|
|
|
83
|
-
|
|
84
|
-
```ruby
|
|
85
|
-
set :puma_jungle_conf, '/etc/puma.conf'
|
|
86
|
-
set :puma_run_path, '/usr/local/bin/run-puma'
|
|
87
|
-
```
|
|
155
|
+
### Systemd Socket Activation
|
|
88
156
|
|
|
89
|
-
|
|
157
|
+
Systemd socket activation starts your app upon first request if it is not already running
|
|
90
158
|
|
|
91
|
-
Multi-bind can be set with an array in the puma_bind variable
|
|
92
159
|
```ruby
|
|
93
|
-
|
|
160
|
+
set :puma_enable_socket_service, true
|
|
94
161
|
```
|
|
95
|
-
* Listening on tcp://0.0.0.0:9220
|
|
96
|
-
* Listening on unix:///tmp/puma.sock
|
|
97
162
|
|
|
98
|
-
|
|
163
|
+
For more information on socket activation have a look at the `systemd.socket` [man page](https://man7.org/linux/man-pages/man5/systemd.socket.5.html).
|
|
99
164
|
|
|
100
|
-
|
|
101
|
-
```ruby
|
|
102
|
-
set :puma_init_active_record, true
|
|
165
|
+
To restart the listening socket using Systemd run
|
|
103
166
|
```
|
|
167
|
+
cap puma:systemd:restart_socket
|
|
168
|
+
```
|
|
169
|
+
This would also restart the puma instance as the puma service depends on the socket service being active
|
|
104
170
|
|
|
105
171
|
### Other configs
|
|
106
172
|
|
|
@@ -108,36 +174,12 @@ Configurable options, shown here with defaults: Please note the configuration op
|
|
|
108
174
|
|
|
109
175
|
```ruby
|
|
110
176
|
set :puma_user, fetch(:user)
|
|
111
|
-
set :
|
|
112
|
-
set :
|
|
113
|
-
set :
|
|
114
|
-
set :
|
|
115
|
-
set :
|
|
116
|
-
set :
|
|
117
|
-
set :puma_conf, "#{shared_path}/puma.rb"
|
|
118
|
-
set :puma_access_log, "#{shared_path}/log/puma_access.log"
|
|
119
|
-
set :puma_error_log, "#{shared_path}/log/puma_error.log"
|
|
120
|
-
set :puma_role, :app
|
|
121
|
-
set :puma_env, fetch(:rack_env, fetch(:rails_env, 'production'))
|
|
122
|
-
set :puma_threads, [0, 16]
|
|
123
|
-
set :puma_workers, 0
|
|
124
|
-
set :puma_worker_timeout, nil
|
|
125
|
-
set :puma_init_active_record, false
|
|
126
|
-
set :puma_preload_app, false
|
|
127
|
-
set :puma_daemonize, false
|
|
128
|
-
set :puma_plugins, [] #accept array of plugins
|
|
129
|
-
set :puma_tag, fetch(:application)
|
|
130
|
-
|
|
131
|
-
set :nginx_config_name, "#{fetch(:application)}_#{fetch(:stage)}"
|
|
132
|
-
set :nginx_flags, 'fail_timeout=0'
|
|
133
|
-
set :nginx_http_flags, fetch(:nginx_flags)
|
|
134
|
-
set :nginx_server_name, "localhost #{fetch(:application)}.local"
|
|
135
|
-
set :nginx_sites_available_path, '/etc/nginx/sites-available'
|
|
136
|
-
set :nginx_sites_enabled_path, '/etc/nginx/sites-enabled'
|
|
137
|
-
set :nginx_socket_flags, fetch(:nginx_flags)
|
|
138
|
-
set :nginx_ssl_certificate, "/etc/ssl/certs/{fetch(:nginx_config_name)}.crt"
|
|
139
|
-
set :nginx_ssl_certificate_key, "/etc/ssl/private/{fetch(:nginx_config_name)}.key"
|
|
140
|
-
set :nginx_use_ssl, false
|
|
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
|
|
180
|
+
set :puma_service_unit_env_files, []
|
|
181
|
+
set :puma_service_unit_env_vars, []
|
|
182
|
+
set :puma_service_unit_props, [] # Set extral puma service properties, such as ["MemoryMax=2G","TimeoutAbortSec=30"]
|
|
141
183
|
```
|
|
142
184
|
|
|
143
185
|
__Notes:__ If you are setting values for variables that might be used by other plugins, use `append` instead of `set`. For example:
|
|
@@ -145,6 +187,38 @@ __Notes:__ If you are setting values for variables that might be used by other p
|
|
|
145
187
|
append :rbenv_map_bins, 'puma', 'pumactl'
|
|
146
188
|
```
|
|
147
189
|
|
|
190
|
+
## Troubleshooting
|
|
191
|
+
|
|
192
|
+
### Puma is not starting after deployment
|
|
193
|
+
- Ensure you ran `cap production puma:install` before your first deployment
|
|
194
|
+
- Check the service status: `cap production puma:status`
|
|
195
|
+
- Check logs: `sudo journalctl -u your_app_puma_production -n 100`
|
|
196
|
+
|
|
197
|
+
### Nginx 502 Bad Gateway errors
|
|
198
|
+
This usually means nginx and puma have mismatched configurations:
|
|
199
|
+
- If nginx expects a unix socket but puma binds to a port (or vice versa)
|
|
200
|
+
- Ensure your `puma_bind` in deploy.rb matches your nginx upstream configuration
|
|
201
|
+
- Common configurations:
|
|
202
|
+
```ruby
|
|
203
|
+
# Unix socket (default)
|
|
204
|
+
set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.sock"
|
|
205
|
+
|
|
206
|
+
# TCP port
|
|
207
|
+
set :puma_bind, "tcp://0.0.0.0:3000"
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Puma keeps restarting (systemd watchdog kills it)
|
|
211
|
+
- Your app may take longer than 10 seconds to boot
|
|
212
|
+
- Disable or increase WatchdogSec (requires version 6.0.0+):
|
|
213
|
+
```ruby
|
|
214
|
+
set :puma_systemd_watchdog_sec, 30 # 30 seconds
|
|
215
|
+
# or
|
|
216
|
+
set :puma_systemd_watchdog_sec, 0 # Disable watchdog
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
# Nginx documentation
|
|
220
|
+
Nginx documentation was moved to [nginx.md](docs/nginx.md)
|
|
221
|
+
|
|
148
222
|
## Contributing
|
|
149
223
|
|
|
150
224
|
1. Fork it
|
|
@@ -11,6 +11,8 @@ module Capistrano
|
|
|
11
11
|
set_if_empty :nginx_http_flags, fetch(:nginx_flags)
|
|
12
12
|
set_if_empty :nginx_socket_flags, fetch(:nginx_flags)
|
|
13
13
|
set_if_empty :nginx_use_ssl, false
|
|
14
|
+
set_if_empty :nginx_use_http2, true
|
|
15
|
+
set_if_empty :nginx_downstream_uses_ssl, false
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
def define_tasks
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Capistrano
|
|
2
|
+
class Puma::Systemd < Capistrano::Plugin
|
|
3
|
+
include PumaCommon
|
|
4
|
+
|
|
5
|
+
def register_hooks
|
|
6
|
+
after 'deploy:published', 'puma:smart_restart'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def define_tasks
|
|
10
|
+
eval_rakefile File.expand_path('../../tasks/systemd.rake', __FILE__)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def set_defaults
|
|
14
|
+
set_if_empty :puma_systemctl_bin, -> { fetch(:systemctl_bin, '/bin/systemctl') }
|
|
15
|
+
set_if_empty :puma_service_unit_name, -> { "#{fetch(:application)}_puma_#{fetch(:stage)}" }
|
|
16
|
+
set_if_empty :puma_enable_socket_service, false
|
|
17
|
+
set_if_empty :puma_systemd_watchdog_sec, 10
|
|
18
|
+
|
|
19
|
+
set_if_empty :puma_service_unit_env_files, -> { fetch(:service_unit_env_files, []) }
|
|
20
|
+
set_if_empty :puma_service_unit_env_vars, -> { fetch(:service_unit_env_vars, []) }
|
|
21
|
+
set_if_empty :puma_service_unit_props, -> { fetch(:service_unit_props, []) }
|
|
22
|
+
|
|
23
|
+
set_if_empty :puma_systemctl_user, -> { fetch(:systemctl_user, :user) }
|
|
24
|
+
set_if_empty :puma_enable_lingering, -> { fetch(:puma_systemctl_user) != :system }
|
|
25
|
+
set_if_empty :puma_lingering_user, -> { fetch(:lingering_user, fetch(:user)) }
|
|
26
|
+
|
|
27
|
+
set_if_empty :puma_service_templates_path, fetch(:service_templates_path, 'config/deploy/templates')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def fetch_systemd_unit_path
|
|
31
|
+
if fetch(:puma_systemctl_user) == :system
|
|
32
|
+
"/etc/systemd/system/"
|
|
33
|
+
else
|
|
34
|
+
home_dir = backend.capture :pwd
|
|
35
|
+
File.join(home_dir, ".config", "systemd", "user")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def systemd_command(*args)
|
|
40
|
+
command = [fetch(:puma_systemctl_bin)]
|
|
41
|
+
|
|
42
|
+
unless fetch(:puma_systemctl_user) == :system
|
|
43
|
+
command << "--user"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
command + args
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def sudo_if_needed(*command)
|
|
50
|
+
if fetch(:puma_systemctl_user) == :system
|
|
51
|
+
backend.sudo command.map(&:to_s).join(" ")
|
|
52
|
+
else
|
|
53
|
+
backend.execute(*command)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def execute_systemd(*args)
|
|
58
|
+
sudo_if_needed(*systemd_command(*args))
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
data/lib/capistrano/puma.rb
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
require 'capistrano/bundler'
|
|
2
|
-
require
|
|
2
|
+
require 'capistrano/plugin'
|
|
3
3
|
|
|
4
4
|
module Capistrano
|
|
5
5
|
module PumaCommon
|
|
6
6
|
def puma_switch_user(role, &block)
|
|
7
7
|
user = puma_user(role)
|
|
8
8
|
if user == role.user
|
|
9
|
-
|
|
9
|
+
yield
|
|
10
10
|
else
|
|
11
|
-
backend.as
|
|
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
|
|
@@ -28,8 +28,14 @@ module Capistrano
|
|
|
28
28
|
end.join("\n")
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
def service_unit_type
|
|
32
|
+
## Jruby don't support notify
|
|
33
|
+
return "simple" if RUBY_ENGINE == "jruby"
|
|
34
|
+
## Puma 6.1+ has built-in sd_notify support
|
|
35
|
+
fetch(:puma_service_unit_type, "notify")
|
|
36
|
+
end
|
|
31
37
|
|
|
32
|
-
def
|
|
38
|
+
def compiled_template_puma(from, role)
|
|
33
39
|
@role = role
|
|
34
40
|
file = [
|
|
35
41
|
"lib/capistrano/templates/#{from}-#{role.hostname}-#{fetch(:stage)}.rb",
|
|
@@ -45,77 +51,76 @@ module Capistrano
|
|
|
45
51
|
File.expand_path("../templates/#{from}.rb.erb", __FILE__)
|
|
46
52
|
].detect { |path| File.file?(path) }
|
|
47
53
|
erb = File.read(file)
|
|
48
|
-
|
|
54
|
+
StringIO.new(ERB.new(erb, trim_mode: '-').result(binding))
|
|
49
55
|
end
|
|
50
|
-
end
|
|
51
56
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def define_tasks
|
|
56
|
-
eval_rakefile File.expand_path('../tasks/puma.rake', __FILE__)
|
|
57
|
+
def template_puma(from, to, role)
|
|
58
|
+
backend.upload! compiled_template_puma(from, role), to
|
|
57
59
|
end
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
# requests and "max" the maximum.
|
|
64
|
-
set_if_empty :puma_threads, [0, 16]
|
|
65
|
-
set_if_empty :puma_workers, 0
|
|
66
|
-
set_if_empty :puma_rackup, -> { File.join(current_path, 'config.ru') }
|
|
67
|
-
set_if_empty :puma_state, -> { File.join(shared_path, 'tmp', 'pids', 'puma.state') }
|
|
68
|
-
set_if_empty :puma_pid, -> { File.join(shared_path, 'tmp', 'pids', 'puma.pid') }
|
|
69
|
-
set_if_empty :puma_bind, -> { File.join("unix://#{shared_path}", 'tmp', 'sockets', 'puma.sock') }
|
|
70
|
-
set_if_empty :puma_control_app, false
|
|
71
|
-
set_if_empty :puma_default_control_app, -> { File.join("unix://#{shared_path}", 'tmp', 'sockets', 'pumactl.sock') }
|
|
72
|
-
set_if_empty :puma_conf, -> { File.join(shared_path, 'puma.rb') }
|
|
73
|
-
set_if_empty :puma_access_log, -> { File.join(shared_path, 'log', 'puma_access.log') }
|
|
74
|
-
set_if_empty :puma_error_log, -> { File.join(shared_path, 'log', 'puma_error.log') }
|
|
75
|
-
set_if_empty :puma_init_active_record, false
|
|
76
|
-
set_if_empty :puma_preload_app, false
|
|
77
|
-
set_if_empty :puma_daemonize, false
|
|
78
|
-
set_if_empty :puma_tag, ''
|
|
61
|
+
PumaBind = Struct.new(:full_address, :kind, :address) do
|
|
62
|
+
def unix?
|
|
63
|
+
kind == :unix
|
|
64
|
+
end
|
|
79
65
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
append :rvm_map_bins, 'puma', 'pumactl'
|
|
66
|
+
def ssl?
|
|
67
|
+
kind == :ssl
|
|
68
|
+
end
|
|
84
69
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
70
|
+
def tcp
|
|
71
|
+
kind == :tcp || ssl?
|
|
72
|
+
end
|
|
88
73
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
74
|
+
def local
|
|
75
|
+
if unix?
|
|
76
|
+
self
|
|
77
|
+
else
|
|
78
|
+
PumaBind.new(
|
|
79
|
+
localize_address(full_address),
|
|
80
|
+
kind,
|
|
81
|
+
localize_address(address)
|
|
82
|
+
)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
93
85
|
|
|
94
|
-
|
|
95
|
-
fetch(:puma_workers, 0)
|
|
96
|
-
end
|
|
86
|
+
private
|
|
97
87
|
|
|
98
|
-
|
|
99
|
-
|
|
88
|
+
def localize_address(address)
|
|
89
|
+
address.gsub(/0\.0\.0\.0(.+)/, "127.0.0.1\\1")
|
|
90
|
+
end
|
|
100
91
|
end
|
|
101
92
|
|
|
102
|
-
def
|
|
103
|
-
fetch(:
|
|
93
|
+
def puma_binds
|
|
94
|
+
Array(fetch(:puma_bind)).map do |m|
|
|
95
|
+
etype, address = /(tcp|unix|ssl):\/{1,2}(.+)/.match(m).captures
|
|
96
|
+
PumaBind.new(m, etype.to_sym, address)
|
|
97
|
+
end
|
|
104
98
|
end
|
|
105
99
|
|
|
106
|
-
def
|
|
107
|
-
|
|
108
|
-
"plugin '#{bind}'"
|
|
109
|
-
end.join("\n")
|
|
100
|
+
def expanded_bundle_command
|
|
101
|
+
backend.capture(:echo, SSHKit.config.command_map[:bundle]).strip
|
|
110
102
|
end
|
|
103
|
+
end
|
|
111
104
|
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
class Puma < Capistrano::Plugin
|
|
106
|
+
include PumaCommon
|
|
107
|
+
|
|
108
|
+
def set_defaults
|
|
109
|
+
set_if_empty :puma_role, :web
|
|
110
|
+
set_if_empty :puma_env, -> { fetch(:rack_env, fetch(:rails_env, fetch(:rake_env, fetch(:stage)))) }
|
|
111
|
+
set_if_empty :puma_bind, -> { "unix://#{File.join(shared_path, 'tmp', 'sockets', 'puma.sock')}" }
|
|
112
|
+
set_if_empty :puma_access_log, -> { File.join(shared_path, 'log', "puma.log") }
|
|
113
|
+
set_if_empty :puma_error_log, -> { File.join(shared_path, 'log', "puma_error.log") }
|
|
114
|
+
|
|
115
|
+
# Chruby, Rbenv and RVM integration
|
|
116
|
+
append :chruby_map_bins, 'puma', 'pumactl' if fetch(:chruby_map_bins)
|
|
117
|
+
append :rbenv_map_bins, 'puma', 'pumactl' if fetch(:rbenv_map_bins)
|
|
118
|
+
append :rvm_map_bins, 'puma', 'pumactl' if fetch(:rvm_map_bins)
|
|
119
|
+
|
|
120
|
+
# Bundler integration
|
|
121
|
+
append :bundle_bins, 'puma', 'pumactl'
|
|
114
122
|
end
|
|
115
123
|
end
|
|
116
124
|
end
|
|
117
125
|
|
|
118
|
-
require 'capistrano/puma/
|
|
119
|
-
require 'capistrano/puma/monit'
|
|
120
|
-
require 'capistrano/puma/jungle'
|
|
121
|
-
require 'capistrano/puma/nginx'
|
|
126
|
+
require 'capistrano/puma/systemd'
|
|
@@ -11,4 +11,12 @@ namespace :puma do
|
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
|
+
|
|
15
|
+
desc 'Generate nginx configuration locally'
|
|
16
|
+
task :generate_nginx_config_locally do
|
|
17
|
+
fake_role = Struct.new(:hostname)
|
|
18
|
+
run_locally do
|
|
19
|
+
File.write('nginx.conf', git_plugin.compiled_template_puma("nginx_conf", fake_role.new("example.com")).string)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
14
22
|
end
|