capistrano-pumaio 0.0.18 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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) %>