capistrano-pumaio 0.0.18 → 3.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.
@@ -0,0 +1,66 @@
1
+ require 'capistrano/helpers/base'
2
+ require 'capistrano/helpers/monit'
3
+ require 'capistrano/helpers/puma/monit'
4
+ require 'capistrano/dsl/base_paths'
5
+ include Capistrano::DSL::BasePaths
6
+ include Capistrano::Helpers::Base
7
+ include Capistrano::Helpers::Monit
8
+ include Capistrano::Helpers::Puma::Monit
9
+
10
+ namespace :puma do
11
+ namespace :monit do
12
+ desc 'MONIT: Setup Puma service'
13
+ task :setup do
14
+ on roles(:app) do |host|
15
+ info "MONIT: Uploading configuration for puma for #{fetch(:application)} on #{host}"
16
+ # Upload configuration
17
+ upload! template_to_s_io(fetch(:puma_monit_config_template)), available_configuration_with_path
18
+ end
19
+ end
20
+
21
+ desc 'MONIT: Enable services for Puma'
22
+ task :enable do
23
+ on roles(:app) do |host|
24
+ info "MONIT: Enabling service for puma for application #{fetch(:application)} on #{host}"
25
+ enable_monitor(available_configuration_file )
26
+ end
27
+ end
28
+
29
+ desc 'MONIT: Disable and Stop services for Puma'
30
+ task :disable do
31
+ on roles(:app) do |host|
32
+ info "MONIT: Disabling service for puma for application #{fetch(:application)} on #{host}"
33
+ disable_monitor(available_configuration_file)
34
+ end
35
+ end
36
+
37
+ %w(start stop restart monitor unmonitor).each do |cmd|
38
+ desc "MONIT: #{cmd.capitalize} puma"
39
+ task cmd.to_sym do
40
+ on roles(:app) do |host|
41
+ info "MONIT: #{cmd} #{fetch(:puma_monit_service_name)} on #{host}"
42
+ command_monit(cmd, fetch(:puma_monit_service_name))
43
+ end
44
+ end
45
+ end
46
+
47
+ desc 'MONIT: Purge Puma configuration'
48
+ task :purge do
49
+ on roles(:app) do |host|
50
+ info "MONIT: Purging config for #{fetch(:puma_monit_service_name)} on #{host}"
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ after 'monit:setup', 'puma:monit:setup'
57
+ # after 'puma:monit:setup', 'puma:monit:enable'
58
+ after 'puma:monit:enable', 'monit:reload'
59
+
60
+ before 'puma:monit:disable', 'puma:monit:unmonitor'
61
+ after 'puma:monit:disable', 'monit:reload'
62
+
63
+ # start service after update in case it has not been stopped
64
+ # This shouldn't be necessary, as monit should pick up a non-running service.
65
+ # Starting it here might trigger double starting if monit is triggered simultaniously.
66
+ # after "deploy:update", "puma:monit:start"
@@ -0,0 +1,119 @@
1
+ require 'capistrano/dsl/base_paths'
2
+ require 'capistrano/helpers/base'
3
+ require 'capistrano/helpers/puma/nginx'
4
+ include Capistrano::DSL::BasePaths
5
+ include Capistrano::Helpers::Base
6
+ include Capistrano::Helpers::Puma::Nginx
7
+
8
+ namespace :puma do
9
+ namespace :nginx do
10
+ desc 'Get the config needed to add to sudoers for nginx commands'
11
+ task :sudoers do
12
+ run_locally do
13
+ info '---------------ENTRIES FOR SUDOERS (Nginx)---------------------'
14
+ puts '#---------------ENTRIES FOR SUDOERS (Nginx)---------------------'
15
+ puts "#{fetch(:user)} ALL=NOPASSWD: /bin/mkdir -p #{fetch(:nginx_log_path)}"
16
+ puts "#{fetch(:user)} ALL=NOPASSWD: /bin/chown -R #{fetch(:user)}\\:root #{fetch(:nginx_log_path)}"
17
+ puts "#{fetch(:user)} ALL=NOPASSWD: /bin/chmod 6775 #{fetch(:nginx_log_path)}"
18
+ puts "#{fetch(:user)} ALL=NOPASSWD: /bin/chown #{fetch(:user)}\\:root #{fetch(:nginx_sites_enabled_path)}"
19
+ puts "#{fetch(:user)} ALL=NOPASSWD: /usr/sbin/service nginx *"
20
+ puts '#---------------------------------------------------------------'
21
+ info '---------------------------------------------------------------'
22
+ end
23
+ # info "#{fetch(:user)} ALL=NOPASSWD: /bin/chown deploy:root #{monit_monitrc_file}"
24
+ end
25
+
26
+ desc 'Generates and uploads nginx configuration for this app to the App server(s)'
27
+ # task :setup, :roles => :app , :except => { :no_release => true } do
28
+ task :setup do
29
+ # Will setup nginx on the application server, as single-host app/web server is used behind load balancer
30
+ # Nginx is used for talking over socket to puma instead of opening puma to the 'world'
31
+ on roles(:app) do |host|
32
+ info "NGINX: Setting up for puma for #{fetch(:application)} on #{host}"
33
+ upload! template_to_s_io(fetch(:nginx_config_template)), fetch(:nginx_remote_config)
34
+ if (fetch(:nginx_use_simple_auth)) || fetch(:nginx_ssl_use_simple_auth)
35
+ set :pw, ask('', '')
36
+ set :create_httpwd, ask('Create .httpasswd configuration file [Yn]', 'Y')
37
+ # if auth is enabled, upload htpasswd file
38
+ # Since passwords are stored in plaintext in the deployment file, you should use simple auth with care.
39
+ # It is generally better to implement a full authorization stack like oauth, use devise on rails,
40
+ # or other login/auth system
41
+ if fetch(:create_httpwd)
42
+ set :nginx_simple_auth_password, default_pw_generator if fetch(:nginx_simple_auth_password).nil?
43
+ upload! template_to_s_io(fetch(:nginx_htpasswd_template)), fetch(:nginx_remote_htpasswd)
44
+ else
45
+ set :nginx_use_simple_auth, false
46
+ set :nginx_ssl_use_simple_auth, false
47
+ end
48
+ end
49
+ # create log path
50
+ # /var/log/nginx must be writable by 'deploy' user, usually this can be acomplished by adding the deploy user to
51
+ # the www-data group
52
+ execute :sudo, :mkdir, "-p #{fetch(:nginx_log_path)}"
53
+ execute :sudo, :chown, "-R #{fetch(:user)}:root #{fetch(:nginx_log_path)}"
54
+ execute :sudo, :chmod, "6775 #{fetch(:nginx_log_path)}"
55
+ execute :mkdir, "-p #{fetch(:nginx_app_log_path)}"
56
+ end
57
+ end
58
+
59
+ desc 'Enable nginx site for the application'
60
+ task :enable do
61
+ on roles(:app) do |host|
62
+ if test("[ ! -h #{fetch(:nginx_sites_enabled_symlink)} ]")
63
+ info "NGINX: Enabling application #{fetch(:application)} on #{host}"
64
+ # Make sure deploy user can symlink site
65
+ execute :sudo, :chown, "#{fetch(:user)}:root #{fetch(:nginx_sites_enabled_path)}"
66
+ execute :ln, "-sf #{fetch(:nginx_remote_config)} #{fetch(:nginx_sites_enabled_symlink)}"
67
+ else
68
+ info "NGINX: Already enabled application #{fetch(:application)} on #{host}"
69
+ end
70
+ end
71
+ end
72
+
73
+ desc 'Disable nginx site for the application'
74
+ task :disable do
75
+ on roles(:app) do |host|
76
+ if test("[ -h #{fetch(:nginx_sites_enabled_symlink)} ]")
77
+ info "NGINX: Disabling application #{fetch(:application)} on #{host}"
78
+ # Make sure deploy user can unsymlink site
79
+ execute :sudo, :chown, "#{fetch(:user)}:root #{fetch(:nginx_sites_enabled_path)}"
80
+ execute :rm, "-f #{fetch(:nginx_sites_enabled_symlink)}"
81
+ else
82
+ info "NGINX: Already disabled application #{fetch(:application)} on #{host}"
83
+ end
84
+ end
85
+ end
86
+
87
+ desc 'Purge nginx site config for the application'
88
+ task :purge do
89
+ on roles(:app) do |host|
90
+ info "NGINX: Purging configuration for #{fetch(:application)} on #{host}"
91
+ execute :rm, "-f #{fetch(:nginx_sites_enabled_symlink)}" if test("[ -h #{fetch(:nginx_sites_enabled_symlink)} ]")
92
+ execute :rm, "-f #{fetch(:nginx_remote_htpasswd)}"
93
+ execute :rm, "-f #{fetch(:nginx_remote_config)}"
94
+ # must restart nginx to make sure site is disabled when config is purge
95
+ execute :sudo, :service, 'nginx restart'
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ namespace :nginx do
102
+ %w(start stop restart status).each do |nginx_cmd|
103
+ desc "Nginx/Puma: #{nginx_cmd.capitalize}"
104
+ task nginx_cmd.to_sym do
105
+ on roles(:app) do |host|
106
+ info "NGINX: Performing #{nginx_cmd} for #{fetch(:application)} on #{host}"
107
+ execute :sudo, :service, "nginx #{nginx_cmd}"
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ # after 'deploy:setup' do
114
+ # puma.nginx.setup if Capistrano::CLI.ui.agree("Create nginx configuration file? [Yn]")
115
+ # if Capistrano::CLI.ui.agree("Enable site in nginx? [Yn]")
116
+ # puma.nginx.enable
117
+ # nginx.restart # must restart after enable for nginx to pickup new site
118
+ # end
119
+ # end
@@ -0,0 +1,63 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext/string/filters'
3
+ require 'capistrano/helpers/puma/template_paths'
4
+ require 'capistrano/helpers/base'
5
+ include Capistrano::Helpers::Base
6
+
7
+ namespace :load do
8
+ task :defaults do
9
+ # Where your nginx lives. Usually /opt/nginx or /usr/local/nginx for source compiled.
10
+ set :nginx_sites_enabled_path, '/etc/nginx/sites-enabled'
11
+
12
+ # simple authorization in nginx recipe
13
+ # Remember NOT to share your deployment file in case you have sensitive passwords stored in it...
14
+ # This is added to make it easier to deploy staging sites with a simple htpasswd.
15
+
16
+ set :nginx_use_simple_auth, false
17
+ set :nginx_simple_auth_message, 'Restricted site'
18
+ set :nginx_simple_auth_user, 'user'
19
+ set :nginx_simple_auth_password, nil # if set to nil, it will automatically be generated
20
+ set :nginx_simple_auth_salt, (0...8).map { ('a'..'z').to_a[rand(26)] }.join
21
+
22
+ # Server names. Defaults to application name.
23
+ set :server_names, proc { app_env_underscore }
24
+
25
+ # Path to the nginx erb template to be parsed before uploading to remote
26
+ set :nginx_config_template, File.join(Capistrano::Helpers::Puma::TemplatePaths.template_base_path, 'nginx', 'application.conf.erb') # rubocop:disable Metrics/LineLength
27
+
28
+ # Path to where your remote config will reside (I use a directory sites inside conf)
29
+ set :nginx_remote_config, proc { shared_path.join('config', "nginx_#{app_env_underscore}.conf") }
30
+
31
+ # Path to local htpasswd template file
32
+ set :nginx_htpasswd_template, File.join(Capistrano::Helpers::Puma::TemplatePaths.template_base_path, 'nginx', 'htpasswd.erb')
33
+
34
+ # Path to remote htpasswd file
35
+ set :nginx_remote_htpasswd, proc { shared_path.join('config', '.htpasswd') }
36
+
37
+ set :nginx_sites_enabled_symlink, proc { File.join(fetch(:nginx_sites_enabled_path), app_env_underscore) }
38
+
39
+ set :nginx_uses_http, true
40
+ set :nginx_uses_ssl, false
41
+ set :nginx_port, 80
42
+
43
+ set :nginx_log_path, proc { File.join('/var', 'log', 'nginx') }
44
+
45
+ set :nginx_app_log_path, proc { File.join(fetch(:nginx_log_path), fetch(:application).squish.downcase.gsub(/[\s|-]/, '_')) }
46
+
47
+ set :nginx_client_max_body_size, '10M'
48
+
49
+ set :nginx_ssl_port, 443
50
+ set :nginx_ssl_use_simple_auth, false
51
+ set :nginx_ssl_client_max_body_size, '10M'
52
+ set :nginx_ssl_public_crt, File.join('/etc', 'certs', 'server.crt')
53
+ set :nginx_ssl_private_key, File.join('/etc', 'certs', 'server.key')
54
+
55
+ set :nginx_puma_server_url, proc { "unix:#{fetch(:puma_socket_file)}" }
56
+ set :nginx_puma_server_timeout, proc { 'fail_timeout=0' }
57
+
58
+ # Supply a block of text to add to the nginx config file before hitting puma server (rewrites etc)
59
+ set :nginx_extra_rules, nil
60
+ # Same as above but for ssl
61
+ set :nginx_extra_rules_ssl, nil
62
+ end
63
+ end
@@ -0,0 +1,179 @@
1
+ require 'capistrano/dsl/base_paths'
2
+ require 'capistrano/dsl/runit_paths'
3
+ require 'capistrano/helpers/base'
4
+ require 'capistrano/helpers/runit'
5
+
6
+ include Capistrano::DSL::BasePaths
7
+ include Capistrano::DSL::RunitPaths
8
+ include Capistrano::Helpers::Base
9
+ include Capistrano::Helpers::Runit
10
+
11
+ # require 'capistrano/runit'
12
+ namespace :puma do
13
+ desc 'Setup Puma configuration'
14
+ task :setup do
15
+ on roles(:app) do
16
+ execute :mkdir, "-p #{fetch(:sockets_path)}" if test("[ ! -d '#{fetch(:sockets_path)}' ]")
17
+ execute :mkdir, "-p '#{fetch(:puma_remote_config_folder)}'" if test("[ ! -d '#{fetch(:puma_remote_config_folder)}' ]")
18
+ upload! template_to_s_io(fetch(:puma_config_template)), fetch(:puma_config_file)
19
+ end
20
+ end
21
+
22
+ desc 'Flush Puma sockets, as they can end up \'hanging around\''
23
+ task :flush_sockets do
24
+ on roles(:app) do
25
+ execute :rm, "-f '#{fetch(:puma_socket_file)}'"
26
+ execute :rm, "-f '#{fetch(:puma_control_file)}'"
27
+ end
28
+ end
29
+
30
+ namespace :runit do
31
+ desc 'Setup Puma runit-service'
32
+ task :setup do
33
+ on roles(:app) do
34
+ # Create runit config
35
+ if test("[ ! -d '#{runit_service_path(fetch(:puma_runit_service_name))}' ]")
36
+ execute :mkdir, "-p '#{runit_service_path(fetch(:puma_runit_service_name))}'"
37
+ end
38
+
39
+ upload! template_to_s_io(fetch(:puma_runit_run_template)), runit_service_run_config_file(fetch(:puma_runit_service_name)) # rubocop:disable Metrics/LineLength
40
+ upload! template_to_s_io(fetch(:puma_runit_finish_template)), runit_service_finish_config_file(fetch(:puma_runit_service_name)) # rubocop:disable Metrics/LineLength
41
+
42
+ # must use quit script for stop as well, to ensure quit and stop performs equally
43
+ if test("[ ! -d '#{runit_service_control_path(fetch(:puma_runit_service_name))}' ]")
44
+ execute :mkdir, "-p '#{runit_service_control_path(fetch(:puma_runit_service_name))}'"
45
+ end
46
+ upload! template_to_s_io(fetch(:puma_runit_control_q_template)), runit_service_control_file(fetch(:puma_runit_service_name), 'q') # rubocop:disable Metrics/LineLength
47
+ upload! template_to_s_io(fetch(:puma_runit_control_q_template)), runit_service_control_file(fetch(:puma_runit_service_name), 's') # rubocop:disable Metrics/LineLength
48
+
49
+ # Log scripts for runit service
50
+ if test("[ ! -d '#{runit_service_log_path(fetch(:puma_runit_service_name))}' ]")
51
+ execute :mkdir, "-p '#{runit_service_log_path(fetch(:puma_runit_service_name))}'"
52
+ end
53
+
54
+ upload! template_to_s_io(fetch(:puma_runit_log_run_template)), runit_service_log_run_file(fetch(:puma_runit_service_name)) # rubocop:disable Metrics/LineLength
55
+
56
+ # Make scripts executable
57
+ runit_set_executable_files(fetch(:puma_runit_service_name))
58
+
59
+ # Create log paths for the service
60
+ if test("[ ! -d '#{runit_var_log_service_single_service_path(fetch(:puma_runit_service_name))}' ]")
61
+ execute :mkdir, "-p '#{runit_var_log_service_single_service_path(fetch(:puma_runit_service_name))}'"
62
+ end
63
+ end
64
+ end
65
+
66
+ desc 'Enable Puma runit-service'
67
+ task :enable do
68
+ on roles(:app) do
69
+ enable_service(fetch(:puma_runit_service_name))
70
+ end
71
+ end
72
+
73
+ desc 'Disable Puma runit-service'
74
+ task :disable do
75
+ on roles(:app) do
76
+ disable_service(fetch(:puma_runit_service_name))
77
+ end
78
+ end
79
+
80
+ desc 'Start Puma runit-service'
81
+ task :start do
82
+ on roles(:app) do
83
+ control_service(fetch(:puma_runit_service_name), 'start')
84
+ end
85
+ end
86
+
87
+ desc 'Start Puma runit-service only ONCE (no supervision...)'
88
+ task :once do
89
+ on roles(:app) do
90
+ control_service(fetch(:puma_runit_service_name), 'once')
91
+ end
92
+ end
93
+
94
+ desc 'Stop Puma runit-service'
95
+ # :on_error => :continue should be added when cap3 equivalent has been figured out
96
+ task :stop do
97
+ on roles(:app) do
98
+ # have to use force-stop on failed stop, since puma might not terminate properly depending on current
99
+ # 'slow' clients.
100
+ # will wait 30 seconds for puma to shut down, to allow it to serve any on-going requests
101
+ begin
102
+ control_service(fetch(:puma_runit_service_name), 'force-stop', '-w 30')
103
+ rescue
104
+ end
105
+ end
106
+ end
107
+
108
+ desc 'Quit the puma runit-service'
109
+ # :on_error => :continue should be added when cap3 equivalent has been figured out
110
+ task :quit do
111
+ on roles(:app) do
112
+ control_service(fetch(:puma_runit_service_name), 'quit')
113
+ end
114
+ end
115
+
116
+ desc 'Restart Puma runit-service'
117
+ task :restart do
118
+ on roles(:app) do
119
+ # It is not possible to see if a restart is in progress using the pumactl tool as of now.
120
+
121
+ started = false
122
+ restarting = false
123
+ within(current_path) do
124
+ a = capture(fetch(:puma_control), "-S #{fetch(:puma_state_file)} status)")
125
+ started = a.includes?('started')
126
+ restarting = a.includes?('restarting')
127
+ end
128
+
129
+ if (started == true) && (restarting == false)
130
+ info("\nRestarting puma")
131
+ # Send USR2 to puma in order to restart it....
132
+ control_service(fetch(:puma_runit_service_name), '2')
133
+ elsif restarting == false
134
+ info("\nStarting puma, (wasn't running before)")
135
+ control_service(fetch(:puma_runit_service_name), 'start')
136
+ end
137
+ # end
138
+ end
139
+ end
140
+
141
+ desc 'Phased Restart of Puma'
142
+ task :phased_restart do
143
+ on roles(:app) do
144
+ started = false
145
+ within(current_path) do
146
+ a = capture(fetch(:puma_control), "-S #{fetch(:puma_state_file)} status)")
147
+ started = a.includes?('started')
148
+ end
149
+
150
+ if started == true
151
+ # Send USR1 to puma in order to restart it....
152
+ info("\nPhased restart of puma")
153
+ control_service(fetch(:puma_runit_service_name), '1')
154
+ else
155
+ important("\nStarting puma, (wasn't running before)")
156
+ control_service(fetch(:puma_runit_service_name), 'start')
157
+ end
158
+ end
159
+ end
160
+
161
+ desc 'Purge Puma runit configuration'
162
+ # :on_error => :continue should be added when cap3 equivalent has been figured out
163
+ task :purge do
164
+ on roles(:app) do
165
+ disable_service(fetch(:puma_runit_service_name))
166
+ purge_service(fetch(:puma_runit_service_name))
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ after 'runit:setup', 'puma:runit:setup'
173
+
174
+ # enable service after update in case it has been disabled
175
+ # Service should probably be started as well?
176
+ after 'deploy:updated', 'puma:runit:enable'
177
+ before 'puma:runit:setup', 'puma:flush_sockets'
178
+ before 'puma:runit:setup', 'puma:setup'
179
+ before 'puma:runit:quit', 'puma:runit:stop'
@@ -1,16 +1,15 @@
1
1
  # Monit configuration for Puma
2
- # <% c = Capistrano::BaseHelper::get_capistrano_instance %>
3
- # <%= "#{c.fetch(:application)} running as #{c.fetch(:user)} in environment #{Capistrano::BaseHelper.environment}" %>
2
+ # <%= "#{fetch(:application)} running as #{fetch(:user)} in environment #{environment}" %>
4
3
  #
5
- # Service name: <%= c.fetch(:puma_monit_service_name) %>
4
+ # Service name: <%= fetch(:puma_monit_service_name) %>
6
5
  #
7
- check process <%= c.fetch(:puma_monit_service_name) %>
8
- with pidfile <%= c.fetch(:puma_pid_file) %>
9
- start program = "<%= c.fetch(:puma_monit_start_command) %>"
10
- stop program = "<%= c.fetch(:puma_monit_stop_command) %>"
11
- if mem is greater than <%= c.fetch(:puma_monit_memory_alert_threshold) %> then alert
12
- if mem is greater than <%= c.fetch(:puma_monit_memory_restart_threshold) %> then restart
13
- if cpu is greater than <%= c.fetch(:puma_monit_cpu_alert_threshold) %> then alert
14
- if cpu is greater than <%= c.fetch(:puma_monit_cpu_restart_threshold) %> then restart
6
+ check process <%= fetch(:puma_monit_service_name) %>
7
+ with pidfile <%= fetch(:puma_pid_file) %>
8
+ start program = "<%= fetch(:puma_monit_start_command) %>"
9
+ stop program = "<%= fetch(:puma_monit_stop_command) %>"
10
+ if mem is greater than <%= fetch(:puma_monit_memory_alert_threshold) %> then alert
11
+ if mem is greater than <%= fetch(:puma_monit_memory_restart_threshold) %> then restart
12
+ if cpu is greater than <%= fetch(:puma_monit_cpu_alert_threshold) %> then alert
13
+ if cpu is greater than <%= fetch(:puma_monit_cpu_restart_threshold) %> then restart
15
14
 
16
- group <%= c.fetch(:monit_application_group_name) %>
15
+ group <%= fetch(:monit_application_group_name) %>