capistrano-cookbook 0.2.1 → 5.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/README.md +36 -16
- data/capistrano-cookbook.gemspec +2 -1
- data/lib/capistrano/cookbook.rb +1 -1
- data/lib/capistrano/cookbook/helpers/setup_config_values.rb +23 -19
- data/lib/capistrano/cookbook/helpers/template.rb +3 -1
- data/lib/capistrano/cookbook/systemd.rb +1 -0
- data/lib/capistrano/cookbook/tasks/check_revision.cap +0 -2
- data/lib/capistrano/cookbook/tasks/nginx.cap +7 -5
- data/lib/capistrano/cookbook/tasks/run_tests.cap +1 -3
- data/lib/capistrano/cookbook/tasks/setup_config.cap +18 -6
- data/lib/capistrano/cookbook/tasks/systemd.cap +17 -0
- data/lib/capistrano/cookbook/version.rb +1 -1
- data/lib/generators/capistrano/reliably_deploying_rails/bootstrap_generator.rb +68 -0
- data/lib/generators/capistrano/reliably_deploying_rails/templates/Capfile.erb +46 -0
- data/lib/generators/capistrano/reliably_deploying_rails/templates/deploy.rb.erb +42 -0
- data/lib/generators/capistrano/reliably_deploying_rails/templates/nginx_conf.erb +105 -0
- data/lib/generators/capistrano/reliably_deploying_rails/templates/production.rb.erb +30 -0
- data/lib/generators/capistrano/reliably_deploying_rails/templates/puma.rb.erb +53 -0
- data/lib/generators/capistrano/reliably_deploying_rails/templates/puma.service.erb +29 -0
- data/lib/generators/capistrano/reliably_deploying_rails/templates/puma_monit.conf.erb +7 -0
- data/lib/generators/capistrano/reliably_deploying_rails/templates/sidekiq.service.capistrano.erb +30 -0
- data/lib/generators/capistrano/reliably_deploying_rails/templates/sidekiq_monit.erb +4 -0
- data/lib/generators/capistrano/reliably_deploying_rails/templates/staging.rb.erb +30 -0
- metadata +32 -14
- data/lib/capistrano/cookbook/restart.rb +0 -1
- data/lib/capistrano/cookbook/tasks/restart.cap +0 -13
- data/lib/capistrano/cookbook/templates/mongoid.example.yml.erb +0 -69
- data/lib/capistrano/cookbook/templates/monit.erb +0 -22
- data/lib/capistrano/cookbook/templates/nginx.conf.erb +0 -57
- data/lib/capistrano/cookbook/templates/secrets.yml.erb +0 -2
- data/lib/capistrano/cookbook/templates/unicorn.rb.erb +0 -41
- data/lib/capistrano/cookbook/templates/unicorn_init.sh.erb +0 -86
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6196d2ecf217984aa66e19657b8ebfd58b0202b70d5c33bbcdf7b3e5385ccddd
|
4
|
+
data.tar.gz: 84eaad2671892ed175d1cc8e605fb7f7a935a484a310d3ae8a29355acee50050
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11507790fa3e84d2897565a729714cbe766b97e1d33169bd796901ac26fefdf4fc01253df4508d5a9929cb6fafdbe5397e8214a10abdb4484685409d62515b09
|
7
|
+
data.tar.gz: 0e218729f6040493dc87f900e8af733c31fa913ee1ac916d7da0138c459efe6a23cd6163871a308c1b4efcdcc8f55d967c9e111223398ac0f01f782f49dbf47a
|
data/README.md
CHANGED
@@ -16,9 +16,44 @@ Or install it yourself as:
|
|
16
16
|
|
17
17
|
$ gem install capistrano-cookbook
|
18
18
|
|
19
|
+
## Versioning
|
20
|
+
|
21
|
+
This gem is primarily intended to provide a batteries included approach to getting Rails applications up and running. It is tested with the server configuration in <https://github.com/TalkingQuickly/rails-server-template>.
|
22
|
+
|
23
|
+
Major versions of the rails server template above and this gem stay in sync. So Version X.*.* of this gem should provide a working out of the box capistrano configuration when used with version X.*.* of the server template.
|
24
|
+
|
25
|
+
Major and minor versions of this gem, the server template and the book [Reliably Deploying Rails Applications](https://leanpub.com/deploying_rails_applications) also stay in sync. Updates to the book are free for life so on a new project, it's always advisable to make sure you have the latest version.
|
26
|
+
|
19
27
|
## Usage
|
20
28
|
|
21
|
-
###
|
29
|
+
### Boostrap
|
30
|
+
|
31
|
+
To generate a complete Capistrano configuration include the gem in your Gemfile and then use the following Rails Generator:
|
32
|
+
|
33
|
+
```
|
34
|
+
bundle exec rails g capistrano:reliably_deploying_rails:bootstrap --sidekiq --production_hostname='YOUR_PRODUCTION_DOMAIN' --production_server_address='YOUR_PRODUCTION_SERVER'
|
35
|
+
```
|
36
|
+
|
37
|
+
Replacing `YOUR_PRODUCTION_DOMAIN` with the domain name people will access the Rails app on and `YOUR_PRODUCTION_SERVER` with the address or ip that can be used to access the server via SSH, these may be the same thing but often will not be (e.g. if the domain has a CDN or Load Balancer between it and the server you're deploying to),
|
38
|
+
|
39
|
+
This will generate a complete Capistrano configuration.
|
40
|
+
|
41
|
+
You can then execute:
|
42
|
+
|
43
|
+
```
|
44
|
+
bundle exec cap production deploy:setup_config
|
45
|
+
bundle exec cap production database:create
|
46
|
+
```
|
47
|
+
|
48
|
+
To perform setup tasks and create a new empty database. Followed by:
|
49
|
+
|
50
|
+
```
|
51
|
+
bundle exec cap production deploy
|
52
|
+
```
|
53
|
+
|
54
|
+
To kick off you first deploy.
|
55
|
+
|
56
|
+
### Including Tasks Manually
|
22
57
|
|
23
58
|
To include all tasks from the gem, add the following to your `Capfile`:
|
24
59
|
|
@@ -35,7 +70,6 @@ require 'capistrano/cookbook/create_database'
|
|
35
70
|
require 'capistrano/cookbook/logs'
|
36
71
|
require 'capistrano/cookbook/monit'
|
37
72
|
require 'capistrano/cookbook/nginx'
|
38
|
-
require 'capistrano/cookbook/restart'
|
39
73
|
require 'capistrano/cookbook/run_tests'
|
40
74
|
require 'capistrano/cookbook/setup_config'
|
41
75
|
```
|
@@ -126,20 +160,6 @@ cap STAGE nginx:restart
|
|
126
160
|
cap STAGE nginx:remove_default_vhost
|
127
161
|
```
|
128
162
|
|
129
|
-
#### Restart
|
130
|
-
|
131
|
-
Provides Commands for interacting with the Unicorn app server via an `init.d` script.
|
132
|
-
|
133
|
-
Usage:
|
134
|
-
|
135
|
-
``` bash
|
136
|
-
cap STAGE deploy:start
|
137
|
-
cap STAGE deploy:stop
|
138
|
-
cap STAGE deploy:force-stop
|
139
|
-
cap STAGE deploy:restart
|
140
|
-
cap STAGE deploy:upgrade
|
141
|
-
```
|
142
|
-
|
143
163
|
#### Run Tests
|
144
164
|
|
145
165
|
Allows a test suite to be automatically run with `rspec`, if the tests pass the deploy will continue, if they fail, the deploy will halt and the test output will be displayed.
|
data/capistrano-cookbook.gemspec
CHANGED
@@ -17,7 +17,8 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.add_dependency 'capistrano', '~> 3.
|
20
|
+
spec.add_dependency 'capistrano', '~> 3.16'
|
21
|
+
spec.add_dependency 'capistrano3-puma', '~> 5.0.4'
|
21
22
|
|
22
23
|
spec.add_development_dependency "bundler", "~> 1.5"
|
23
24
|
spec.add_development_dependency "rake"
|
data/lib/capistrano/cookbook.rb
CHANGED
@@ -6,9 +6,9 @@ module Capistrano
|
|
6
6
|
require 'capistrano/cookbook/logs'
|
7
7
|
require 'capistrano/cookbook/monit'
|
8
8
|
require 'capistrano/cookbook/nginx'
|
9
|
-
require 'capistrano/cookbook/restart'
|
10
9
|
require 'capistrano/cookbook/run_tests'
|
11
10
|
require 'capistrano/cookbook/setup_config'
|
12
11
|
require 'capistrano/cookbook/create_database'
|
12
|
+
require 'capistrano/cookbook/systemd'
|
13
13
|
end
|
14
14
|
end
|
@@ -16,42 +16,46 @@ module Capistrano
|
|
16
16
|
private
|
17
17
|
|
18
18
|
def symlinks_defaults
|
19
|
-
[
|
20
|
-
{
|
21
|
-
source: "nginx.conf",
|
22
|
-
link: "/etc/nginx/sites-enabled/{{full_app_name}}"
|
23
|
-
},
|
24
|
-
{
|
25
|
-
source: "unicorn_init.sh",
|
26
|
-
link: "/etc/init.d/unicorn_{{full_app_name}}"
|
27
|
-
},
|
19
|
+
base = [
|
28
20
|
{
|
29
21
|
source: "log_rotation",
|
30
|
-
|
22
|
+
link: "/etc/logrotate.d/{{full_app_name}}"
|
23
|
+
}
|
24
|
+
]
|
25
|
+
return base unless sidekiq_enabled?
|
26
|
+
|
27
|
+
base + [
|
28
|
+
{
|
29
|
+
source: "sidekiq.service.capistrano",
|
30
|
+
link: "/etc/systemd/system/#{fetch(:sidekiq_service_unit_name)}.service"
|
31
31
|
},
|
32
32
|
{
|
33
|
-
source: "
|
34
|
-
link: "/etc/monit/conf.d
|
33
|
+
source: "sidekiq_monit",
|
34
|
+
link: "/etc/monit/conf.d/#{fetch(:full_app_name)}_sidekiq.conf"
|
35
35
|
}
|
36
36
|
]
|
37
37
|
end
|
38
38
|
|
39
39
|
def executable_config_files_defaults
|
40
40
|
%w(
|
41
|
-
unicorn_init.sh
|
42
41
|
)
|
43
42
|
end
|
44
43
|
|
45
44
|
def config_files_defaults
|
46
|
-
%w(
|
47
|
-
nginx.conf
|
45
|
+
base = %w(
|
48
46
|
database.example.yml
|
49
47
|
log_rotation
|
50
|
-
monit
|
51
|
-
unicorn.rb
|
52
|
-
unicorn_init.sh
|
53
|
-
secrets.yml
|
54
48
|
)
|
49
|
+
return base unless sidekiq_enabled?
|
50
|
+
|
51
|
+
base + %w(
|
52
|
+
sidekiq.service.capistrano
|
53
|
+
sidekiq_monit
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
def sidekiq_enabled?
|
58
|
+
defined?(Capistrano::Sidekiq) == 'constant' && Capistrano::Sidekiq.class == Class
|
55
59
|
end
|
56
60
|
end
|
57
61
|
end
|
@@ -24,10 +24,12 @@ def smart_template(from, to=nil)
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def template_file(name)
|
27
|
-
if File.exist?((file = "config/deploy/#{fetch(:
|
27
|
+
if File.exist?((file = "config/deploy/#{fetch(:stage)}/#{name}.erb"))
|
28
28
|
return file
|
29
29
|
elsif File.exist?((file = "config/deploy/shared/#{name}.erb"))
|
30
30
|
return file
|
31
|
+
elsif File.exist?((file = "config/deploy/templates/#{name}.erb"))
|
32
|
+
return file
|
31
33
|
elsif File.exist?(file = File.expand_path("../templates/#{name}.erb",File.dirname(__FILE__)))
|
32
34
|
return file
|
33
35
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
load File.expand_path("tasks/systemd.cap", File.dirname(__FILE__))
|
@@ -11,11 +11,13 @@ namespace :nginx do
|
|
11
11
|
desc "Remove default Nginx Virtual Host"
|
12
12
|
task "remove_default_vhost" do
|
13
13
|
on roles(:app) do
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
%w(/etc/nginx/sites-enabled/default /etc/nginx/sites-enabled/000-default).each do |default_filename|
|
15
|
+
if test("[ -f #{default_filename} ]")
|
16
|
+
sudo "rm #{default_filename}"
|
17
|
+
puts "Removed default Nginx Virtualhost: #{default_filename}"
|
18
|
+
else
|
19
|
+
puts "Default: #{default_filename} not found, not removed"
|
20
|
+
end
|
19
21
|
end
|
20
22
|
end
|
21
23
|
end
|
@@ -2,7 +2,7 @@ namespace :deploy do
|
|
2
2
|
desc "Runs test before deploying, can't deploy unless they pass"
|
3
3
|
task :run_tests do
|
4
4
|
test_log = "log/capistrano.test.log"
|
5
|
-
tests = fetch(:tests
|
5
|
+
tests = fetch(:tests)
|
6
6
|
tests.each do |test|
|
7
7
|
puts "--> Running tests: '#{test}', please wait ..."
|
8
8
|
unless system "bundle exec rspec #{test} > #{test_log} 2>&1"
|
@@ -16,5 +16,3 @@ namespace :deploy do
|
|
16
16
|
system "rm #{test_log}"
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
20
|
-
before 'deploy', 'deploy:run_tests'
|
@@ -9,6 +9,7 @@ require 'securerandom'
|
|
9
9
|
namespace :deploy do
|
10
10
|
task :setup_config do
|
11
11
|
conf = ::Capistrano::Cookbook::SetupConfigValues.new
|
12
|
+
|
12
13
|
on roles(:app) do
|
13
14
|
# make the config dir
|
14
15
|
execute :mkdir, "-p #{shared_path}/config"
|
@@ -28,18 +29,29 @@ namespace :deploy do
|
|
28
29
|
conf.symlinks.each do |symlink|
|
29
30
|
sudo "ln -nfs #{shared_path}/config/#{symlink[:source]} #{sub_strings(symlink[:link])}"
|
30
31
|
end
|
32
|
+
|
33
|
+
if File.exists?(File.join('config', 'master.key'))
|
34
|
+
upload! File.join('config', 'master.key'), File.join(shared_path, 'config', 'master.key')
|
35
|
+
end
|
31
36
|
end
|
32
37
|
end
|
33
38
|
end
|
34
39
|
|
35
|
-
|
36
|
-
# to conflict with our configs
|
40
|
+
|
41
|
+
# remove the default nginx configuration as it will tend to conflict with our configs
|
37
42
|
before 'deploy:setup_config', 'nginx:remove_default_vhost'
|
38
43
|
|
39
|
-
#
|
40
|
-
# setup_config
|
44
|
+
# After setup config has generated and setup initial files, run the Capistrano Puma
|
45
|
+
# tasks responsible for uploading config files. Note that `setup_config` creates overrides
|
46
|
+
# for these in `config/deploy/templates` so we're not using the default ones from the gem
|
47
|
+
after 'deploy:setup_config', 'puma:config'
|
48
|
+
after 'deploy:setup_config', 'puma:nginx_config'
|
49
|
+
after 'deploy:setup_config', 'puma:monit:config'
|
50
|
+
after 'deploy:setup_config', 'puma:systemd:config'
|
51
|
+
|
52
|
+
# reload nginx to it will pick up any modified vhosts from setup_config
|
41
53
|
after 'deploy:setup_config', 'nginx:reload'
|
42
54
|
|
43
|
-
# Restart monit so it will pick up any monit configurations
|
44
|
-
# we've added
|
55
|
+
# Restart monit so it will pick up any monit configurations we've added
|
45
56
|
after 'deploy:setup_config', 'monit:reload'
|
57
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
namespace :puma do
|
2
|
+
namespace :systemd do
|
3
|
+
desc 'Reload the puma service via systemd by sending USR1 (e.g. trigger a zero downtime deploy)'
|
4
|
+
task :reload do
|
5
|
+
on roles(fetch(:puma_role)) do
|
6
|
+
if fetch(:puma_systemctl_user) == :system
|
7
|
+
sudo "#{fetch(:puma_systemctl_bin)} reload-or-restart #{fetch(:puma_service_unit_name)}"
|
8
|
+
else
|
9
|
+
execute "#{fetch(:puma_systemctl_bin)}", "--user", "reload", fetch(:puma_service_unit_name)
|
10
|
+
execute :loginctl, "enable-linger", fetch(:puma_lingering_user) if fetch(:puma_enable_lingering)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
after 'deploy:finished', 'puma:systemd:reload'
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
module ReliablyDeployingRails
|
5
|
+
module Generators
|
6
|
+
class BootstrapGenerator < Rails::Generators::Base
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
8
|
+
desc "Bootstrap everything required to deploy with capistrano to a server configured with: https://github.com/TalkingQuickly/rails-server-template"
|
9
|
+
class_option :sidekiq, type: :boolean, default: false
|
10
|
+
class_option :production_hostname, type: :string, default: nil
|
11
|
+
class_option :production_server_address, type: :string, default: nil
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@production_hostname = options[:production_hostname] || 'YOUR_PRODUCTION_HOSTNAME'
|
15
|
+
@production_server_address = options[:production_server_address] || 'YOUR_PRODUCTION_SERVER_ADDRESS'
|
16
|
+
@generate_sidekiq = options[:sidekiq]
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_capfile
|
20
|
+
template "Capfile.erb", 'Capfile'
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_deployment_configuration
|
24
|
+
FileUtils.mkdir_p 'config/deploy'
|
25
|
+
template "deploy.rb.erb", 'config/deploy.rb'
|
26
|
+
template "production.rb.erb", 'config/deploy/production.rb'
|
27
|
+
template "staging.rb.erb", 'config/deploy/staging.rb'
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_local_config_templates
|
31
|
+
FileUtils.mkdir_p 'config/deploy/templates'
|
32
|
+
base_path = File.expand_path('../templates', __FILE__)
|
33
|
+
|
34
|
+
templates(@generate_sidekiq).each do |file|
|
35
|
+
unless File.file?(file)
|
36
|
+
copy_file(File.join(base_path, file), "config/deploy/templates/#{file}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def templates(generate_sidekiq)
|
44
|
+
return puma_templates unless generate_sidekiq
|
45
|
+
puma_templates + sidekiq_templates
|
46
|
+
end
|
47
|
+
|
48
|
+
def puma_templates
|
49
|
+
%w(
|
50
|
+
nginx_conf.erb
|
51
|
+
puma_monit.conf.erb
|
52
|
+
puma.rb.erb
|
53
|
+
puma.service.erb
|
54
|
+
sidekiq_monit.erb
|
55
|
+
sidekiq.service.capistrano.erb
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def sidekiq_templates
|
60
|
+
%w(
|
61
|
+
sidekiq_monit.erb
|
62
|
+
sidekiq.service.capistrano.erb
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Load DSL and set up stages
|
2
|
+
require "capistrano/setup"
|
3
|
+
|
4
|
+
# Include default deployment tasks
|
5
|
+
require "capistrano/deploy"
|
6
|
+
|
7
|
+
# Load the SCM plugin appropriate to your project:
|
8
|
+
#
|
9
|
+
# require "capistrano/scm/hg"
|
10
|
+
# install_plugin Capistrano::SCM::Hg
|
11
|
+
# or
|
12
|
+
# require "capistrano/scm/svn"
|
13
|
+
# install_plugin Capistrano::SCM::Svn
|
14
|
+
# or
|
15
|
+
require "capistrano/scm/git"
|
16
|
+
install_plugin Capistrano::SCM::Git
|
17
|
+
|
18
|
+
# Include tasks from other gems included in your Gemfile
|
19
|
+
#
|
20
|
+
# For documentation on these, see for example:
|
21
|
+
#
|
22
|
+
# https://github.com/capistrano/rbenv
|
23
|
+
# https://github.com/capistrano/bundler
|
24
|
+
# https://github.com/capistrano/rails
|
25
|
+
#
|
26
|
+
require "capistrano/rbenv"
|
27
|
+
require "capistrano/bundler"
|
28
|
+
require "capistrano/rails/assets"
|
29
|
+
require "capistrano/rails/migrations"
|
30
|
+
require 'capistrano/cookbook'
|
31
|
+
|
32
|
+
require 'capistrano/puma'
|
33
|
+
install_plugin Capistrano::Puma, load_hooks: false # Default puma tasks
|
34
|
+
install_plugin Capistrano::Puma::Nginx, load_hooks: false # if you want to upload a nginx site template
|
35
|
+
install_plugin Capistrano::Puma::Systemd, load_hooks: false # if you use SystemD
|
36
|
+
install_plugin Capistrano::Puma::Monit, load_hooks: false # if you need the monit tasks
|
37
|
+
|
38
|
+
<% if @generate_sidekiq %>
|
39
|
+
require 'capistrano/sidekiq'
|
40
|
+
install_plugin Capistrano::Sidekiq # Default sidekiq tasks
|
41
|
+
# Then select your service manager
|
42
|
+
install_plugin Capistrano::Sidekiq::Systemd
|
43
|
+
<% end %>
|
44
|
+
|
45
|
+
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
|
46
|
+
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# config valid for current version and patch releases of Capistrano
|
2
|
+
lock "~> 3.16.0"
|
3
|
+
|
4
|
+
set :application, '<%= Rails.application.class.module_parent_name.underscore %>'
|
5
|
+
set :deploy_user, 'deploy'
|
6
|
+
|
7
|
+
# setup repo details
|
8
|
+
set :repo_url, '<%= `git config --get remote.origin.url`.delete!("\n") %>'
|
9
|
+
|
10
|
+
# setup rbenv.
|
11
|
+
set :rbenv_type, :system
|
12
|
+
set :rbenv_ruby, '3.0.0'
|
13
|
+
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=#{fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec"
|
14
|
+
set :rbenv_map_bins, %w{rake gem bundle ruby rails}
|
15
|
+
|
16
|
+
<% if @generate_sidekiq %>
|
17
|
+
# Setup sidekiq, make sure we run sidekiq as our deployment user, otherwise
|
18
|
+
# it will default to root which a) is insecture and b) will lead to lots of
|
19
|
+
# strange permissions issues
|
20
|
+
set :sidekiq_service_unit_user, :system
|
21
|
+
set :sidekiq_user, fetch(:deploy_user)
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
# setup puma to operate in clustered mode, required for zero downtime deploys
|
25
|
+
set :puma_preload_app, false
|
26
|
+
set :puma_init_active_record, true
|
27
|
+
set :puma_workers, 3
|
28
|
+
|
29
|
+
# how many old releases do we want to keep, not much
|
30
|
+
set :keep_releases, 5
|
31
|
+
|
32
|
+
# Directories that should be linked to the shared folder
|
33
|
+
append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', '.bundle', 'public/system', 'public/uploads'
|
34
|
+
append :linked_files, 'config/database.yml', 'config/master.key'
|
35
|
+
|
36
|
+
# this:
|
37
|
+
# http://www.capistranorb.com/documentation/getting-started/flow/
|
38
|
+
# is worth reading for a quick overview of what tasks are called
|
39
|
+
# and when for `cap stage deploy`
|
40
|
+
|
41
|
+
namespace :deploy do
|
42
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
upstream puma_<%= fetch(:nginx_config_name) %> { <%
|
2
|
+
@backends = [fetch(:puma_bind)].flatten.map do |m|
|
3
|
+
etype, address = /(tcp|unix|ssl):\/{1,2}(.+)/.match(m).captures
|
4
|
+
if etype == 'unix'
|
5
|
+
"server #{etype}:#{address} #{fetch(:nginx_socket_flags)};"
|
6
|
+
else
|
7
|
+
"server #{address.gsub(/0\.0\.0\.0(.+)/, "127.0.0.1\\1")} #{fetch(:nginx_http_flags)};"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
%><% @backends.each do |server| %>
|
11
|
+
<%= server %><% end %>
|
12
|
+
}
|
13
|
+
<% if fetch(:nginx_use_ssl) -%>
|
14
|
+
server {
|
15
|
+
listen 80;
|
16
|
+
server_name <%= fetch(:nginx_server_name) %>;
|
17
|
+
return 301 https://$host$1$request_uri;
|
18
|
+
}
|
19
|
+
<% end -%>
|
20
|
+
|
21
|
+
server {
|
22
|
+
<% if fetch(:nginx_use_ssl) -%>
|
23
|
+
<% if fetch(:nginx_use_http2) -%>
|
24
|
+
listen 443 ssl http2;
|
25
|
+
<% else -%>
|
26
|
+
listen 443 ssl;
|
27
|
+
<% end -%>
|
28
|
+
<% if fetch(:nginx_ssl_certificate) -%>
|
29
|
+
ssl_certificate <%= fetch(:nginx_ssl_certificate) %>;
|
30
|
+
<% else -%>
|
31
|
+
ssl_certificate /etc/ssl/certs/<%= fetch(:nginx_config_name) %>.crt;
|
32
|
+
<% end -%>
|
33
|
+
<% if fetch(:nginx_ssl_certificate_key) -%>
|
34
|
+
ssl_certificate_key <%= fetch(:nginx_ssl_certificate_key) %>;
|
35
|
+
<% else -%>
|
36
|
+
ssl_certificate_key /etc/ssl/private/<%= fetch(:nginx_config_name) %>.key;
|
37
|
+
<% end -%>
|
38
|
+
<% else -%>
|
39
|
+
listen 80;
|
40
|
+
<% end -%>
|
41
|
+
server_name <%= fetch(:nginx_server_name) %>;
|
42
|
+
root <%= current_path %>/public;
|
43
|
+
try_files $uri/index.html $uri @puma_<%= fetch(:nginx_config_name) %>;
|
44
|
+
|
45
|
+
client_max_body_size 4G;
|
46
|
+
keepalive_timeout 10;
|
47
|
+
|
48
|
+
error_page 500 502 504 /500.html;
|
49
|
+
error_page 503 @503;
|
50
|
+
|
51
|
+
location @puma_<%= fetch(:nginx_config_name) %> {
|
52
|
+
proxy_http_version 1.1;
|
53
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
54
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
55
|
+
proxy_set_header Host $host;
|
56
|
+
proxy_redirect off;
|
57
|
+
proxy_set_header Upgrade $http_upgrade;
|
58
|
+
proxy_set_header Connection "Upgrade";
|
59
|
+
proxy_headers_hash_max_size 512;
|
60
|
+
proxy_headers_hash_bucket_size 128;
|
61
|
+
<% if fetch(:nginx_use_ssl) -%>
|
62
|
+
proxy_set_header X-Forwarded-Proto https;
|
63
|
+
<% else -%>
|
64
|
+
<% if fetch(:nginx_downstream_uses_ssl) -%>
|
65
|
+
proxy_set_header X-Forwarded-Proto https;
|
66
|
+
<% else -%>
|
67
|
+
proxy_set_header X-Forwarded-Proto http;
|
68
|
+
<% end -%>
|
69
|
+
<% end -%>
|
70
|
+
proxy_pass http://puma_<%= fetch(:nginx_config_name) %>;
|
71
|
+
# limit_req zone=one;
|
72
|
+
access_log <%= shared_path %>/log/nginx.access.log;
|
73
|
+
error_log <%= shared_path %>/log/nginx.error.log;
|
74
|
+
}
|
75
|
+
|
76
|
+
location ^~ /assets/ {
|
77
|
+
gzip_static on;
|
78
|
+
expires max;
|
79
|
+
add_header Cache-Control public;
|
80
|
+
}
|
81
|
+
|
82
|
+
location = /50x.html {
|
83
|
+
root html;
|
84
|
+
}
|
85
|
+
|
86
|
+
location = /404.html {
|
87
|
+
root html;
|
88
|
+
}
|
89
|
+
|
90
|
+
location @503 {
|
91
|
+
error_page 405 = /system/maintenance.html;
|
92
|
+
if (-f $document_root/system/maintenance.html) {
|
93
|
+
rewrite ^(.*)$ /system/maintenance.html break;
|
94
|
+
}
|
95
|
+
rewrite ^(.*)$ /503.html break;
|
96
|
+
}
|
97
|
+
|
98
|
+
if ($request_method !~ ^(GET|HEAD|PUT|PATCH|POST|DELETE|OPTIONS)$ ){
|
99
|
+
return 405;
|
100
|
+
}
|
101
|
+
|
102
|
+
if (-f $document_root/system/maintenance.html) {
|
103
|
+
return 503;
|
104
|
+
}
|
105
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
set :stage, :production
|
2
|
+
set :branch, "master"
|
3
|
+
|
4
|
+
# This is used in the Nginx VirtualHost to specify which domains
|
5
|
+
# the app should appear on. If you don't yet have DNS setup, you'll
|
6
|
+
# need to create entries in your local Hosts file for testing.
|
7
|
+
set :nginx_server_name, '<%= @production_hostname %>'
|
8
|
+
|
9
|
+
# used in case we're deploying multiple versions of the same
|
10
|
+
# app side by side. Also provides quick sanity checks when looking
|
11
|
+
# at filepaths
|
12
|
+
set :full_app_name, "#{fetch(:application)}_#{fetch(:stage)}"
|
13
|
+
|
14
|
+
<% if @generate_sidekiq %>
|
15
|
+
# Name sidekiq systemd service after the app and stage name so that
|
16
|
+
# multiple apps and stages can co-exist on the same machine if needed
|
17
|
+
set :sidekiq_service_unit_name, "#{fetch(:full_app_name)}_sidekiq"
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
server '<%= @production_server_address %>', user: 'deploy', roles: %w{web app db}, primary: true
|
21
|
+
|
22
|
+
set :deploy_to, "/home/#{fetch(:deploy_user)}/apps/#{fetch(:full_app_name)}"
|
23
|
+
|
24
|
+
# dont try and infer something as important as environment from
|
25
|
+
# stage name.
|
26
|
+
set :rails_env, :production
|
27
|
+
|
28
|
+
# whether we're using ssl or not, used for building nginx
|
29
|
+
# config file
|
30
|
+
set :enable_ssl, false
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env puma
|
2
|
+
|
3
|
+
directory '<%= current_path %>'
|
4
|
+
rackup "<%=fetch(:puma_rackup)%>"
|
5
|
+
environment '<%= fetch(:puma_env) %>'
|
6
|
+
<% if fetch(:puma_tag) %>
|
7
|
+
tag '<%= fetch(:puma_tag)%>'
|
8
|
+
<% end %>
|
9
|
+
pidfile "<%=fetch(:puma_pid)%>"
|
10
|
+
state_path "<%=fetch(:puma_state)%>"
|
11
|
+
|
12
|
+
|
13
|
+
threads <%=fetch(:puma_threads).join(',')%>
|
14
|
+
|
15
|
+
<%= puma_plugins %>
|
16
|
+
|
17
|
+
<%= puma_bind %>
|
18
|
+
<% if fetch(:puma_control_app) %>
|
19
|
+
activate_control_app "<%= fetch(:puma_default_control_app) %>"
|
20
|
+
<% end %>
|
21
|
+
workers <%= puma_workers %>
|
22
|
+
<% if fetch(:puma_worker_timeout) %>
|
23
|
+
worker_timeout <%= fetch(:puma_worker_timeout).to_i %>
|
24
|
+
<% end %>
|
25
|
+
|
26
|
+
<% if puma_daemonize? %>
|
27
|
+
daemonize
|
28
|
+
<% end %>
|
29
|
+
|
30
|
+
restart_command '<%= fetch(:puma_restart_command) %>'
|
31
|
+
|
32
|
+
<% if puma_preload_app? %>
|
33
|
+
preload_app!
|
34
|
+
<% else %>
|
35
|
+
prune_bundler
|
36
|
+
<% end %>
|
37
|
+
|
38
|
+
on_restart do
|
39
|
+
puts 'Refreshing Gemfile'
|
40
|
+
ENV["BUNDLE_GEMFILE"] = "<%= fetch(:bundle_gemfile, "#{current_path}/Gemfile") %>"
|
41
|
+
end
|
42
|
+
|
43
|
+
<% if puma_preload_app? and fetch(:puma_init_active_record) %>
|
44
|
+
before_fork do
|
45
|
+
ActiveRecord::Base.connection_pool.disconnect!
|
46
|
+
end
|
47
|
+
|
48
|
+
on_worker_boot do
|
49
|
+
ActiveSupport.on_load(:active_record) do
|
50
|
+
ActiveRecord::Base.establish_connection
|
51
|
+
end
|
52
|
+
end
|
53
|
+
<% end %>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
[Unit]
|
2
|
+
Description=Puma HTTP Server for <%= "#{fetch(:application)} (#{fetch(:stage)})" %>
|
3
|
+
After=network.target
|
4
|
+
|
5
|
+
[Service]
|
6
|
+
Type=simple
|
7
|
+
<%="User=#{puma_user(@role)}" if fetch(:puma_systemctl_user) == :system %>
|
8
|
+
WorkingDirectory=<%= current_path %>
|
9
|
+
ExecStart=/usr/local/rbenv/bin/rbenv exec bundle exec puma -C <%= fetch(:puma_conf) %>
|
10
|
+
ExecReload=/bin/kill -USR1 $MAINPID
|
11
|
+
ExecStop=/bin/kill -TSTP $MAINPID
|
12
|
+
StandardOutput=append:<%= fetch(:puma_access_log) %>
|
13
|
+
StandardError=append:<%= fetch(:puma_error_log) %>
|
14
|
+
<%="EnvironmentFile=#{fetch(:puma_service_unit_env_file)}" if fetch(:puma_service_unit_env_file) %>
|
15
|
+
|
16
|
+
<% fetch(:puma_service_unit_env_vars, []).each do |environment_variable| %>
|
17
|
+
<%="Environment=#{environment_variable}" %>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
Environment=RBENV_VERSION=<%= fetch(:rbenv_ruby) %>
|
21
|
+
Environment=RBENV_ROOT=/usr/local/rbenv
|
22
|
+
|
23
|
+
Restart=always
|
24
|
+
RestartSec=1
|
25
|
+
|
26
|
+
SyslogIdentifier=puma_<%= fetch(:application) %>_<%= fetch(:stage) %>
|
27
|
+
|
28
|
+
[Install]
|
29
|
+
WantedBy=<%=(fetch(:puma_systemctl_user) == :system) ? "multi-user.target" : "default.target"%>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Monit configuration for Puma
|
2
|
+
# Service name: <%= puma_monit_service_name %>
|
3
|
+
#
|
4
|
+
check process <%= puma_monit_service_name %>
|
5
|
+
with pidfile "<%= fetch(:puma_pid) %>"
|
6
|
+
start program = "/usr/bin/systemctl start <%= fetch(:puma_service_unit_name) %>"
|
7
|
+
stop program = "/usr/bin/systemctl stop <%= fetch(:puma_service_unit_name) %>"
|
data/lib/generators/capistrano/reliably_deploying_rails/templates/sidekiq.service.capistrano.erb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
<% # Adapted from: https://github.com/seuros/capistrano-sidekiq/blob/master/lib/generators/capistrano/sidekiq/systemd/templates/sidekiq.service.capistrano.erb %>
|
2
|
+
|
3
|
+
[Unit]
|
4
|
+
Description=sidekiq for <%= "#{fetch(:application)} (#{fetch(:stage)})" %>
|
5
|
+
After=syslog.target network.target
|
6
|
+
|
7
|
+
[Service]
|
8
|
+
Type=simple
|
9
|
+
WorkingDirectory=<%= File.join(fetch(:deploy_to), 'current') %>
|
10
|
+
ExecStart=/usr/local/rbenv/bin/rbenv exec bundle exec sidekiq -e <%= fetch(:sidekiq_env) %>
|
11
|
+
ExecReload=/bin/kill -TSTP $MAINPID
|
12
|
+
ExecStop=/bin/kill -TERM $MAINPID
|
13
|
+
<%="StandardOutput=append:#{fetch(:sidekiq_log)}" if fetch(:sidekiq_log) %>
|
14
|
+
<%="StandardError=append:#{fetch(:sidekiq_error_log)}" if fetch(:sidekiq_error_log) %>
|
15
|
+
<%="User=#{fetch(:sidekiq_user)}" if fetch(:sidekiq_user) %>
|
16
|
+
<%="EnvironmentFile=#{fetch(:sidekiq_service_unit_env_file)}" if fetch(:sidekiq_service_unit_env_file) %>
|
17
|
+
<% fetch(:sidekiq_service_unit_env_vars, []).each do |environment_variable| %>
|
18
|
+
<%="Environment=#{environment_variable}" %>
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
Environment=RBENV_VERSION=<%= fetch(:rbenv_ruby) %>
|
22
|
+
Environment=RBENV_ROOT=/usr/local/rbenv
|
23
|
+
|
24
|
+
RestartSec=1
|
25
|
+
Restart=on-failure
|
26
|
+
|
27
|
+
SyslogIdentifier=sidekiq_<%= fetch(:application) %>_<%= fetch(:stage) %>
|
28
|
+
|
29
|
+
[Install]
|
30
|
+
WantedBy=default.target
|
@@ -0,0 +1,4 @@
|
|
1
|
+
check process <%= fetch(:sidekiq_service_unit_name) %> matching "sidekiq.*<%= fetch(:full_app_name) %>"
|
2
|
+
start program = "/usr/bin/systemctl start <%= fetch(:sidekiq_service_unit_name) %>"
|
3
|
+
stop program = "/usr/bin/systemctl stop <%= fetch(:sidekiq_service_unit_name) %>"
|
4
|
+
group <%= fetch(:sidekiq_monit_group) || fetch(:full_app_name) %>-sidekiq
|
@@ -0,0 +1,30 @@
|
|
1
|
+
set :stage, :staging
|
2
|
+
set :branch, "develop"
|
3
|
+
|
4
|
+
# This is used in the Nginx VirtualHost to specify which domains
|
5
|
+
# the app should appear on. If you don't yet have DNS setup, you'll
|
6
|
+
# need to create entries in your local Hosts file for testing.
|
7
|
+
set :nginx_server_name, "REPLACE_WITH_YOUR_STAGING_HOSTNAME"
|
8
|
+
|
9
|
+
# used in case we're deploying multiple versions of the same
|
10
|
+
# app side by side. Also provides quick sanity checks when looking
|
11
|
+
# at filepaths
|
12
|
+
set :full_app_name, "#{fetch(:application)}_#{fetch(:stage)}"
|
13
|
+
|
14
|
+
<% if @generate_sidekiq %>
|
15
|
+
# Name sidekiq systemd service after the app and stage name so that
|
16
|
+
# multiple apps and stages can co-exist on the same machine if needed
|
17
|
+
set :sidekiq_service_unit_name, "#{fetch(:full_app_name)}_sidekiq"
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
server 'YOUR_STAGING_SERVER_IP', user: 'deploy', roles: %w{web app db}, primary: true
|
21
|
+
|
22
|
+
set :deploy_to, "/home/#{fetch(:deploy_user)}/apps/#{fetch(:full_app_name)}"
|
23
|
+
|
24
|
+
# dont try and infer something as important as environment from
|
25
|
+
# stage name.
|
26
|
+
set :rails_env, :production
|
27
|
+
|
28
|
+
# whether we're using ssl or not, used for building nginx
|
29
|
+
# config file
|
30
|
+
set :enable_ssl, false
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano-cookbook
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 5.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Dixon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capistrano
|
@@ -16,14 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '3.
|
19
|
+
version: '3.16'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '3.
|
26
|
+
version: '3.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: capistrano3-puma
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 5.0.4
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 5.0.4
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -77,29 +91,34 @@ files:
|
|
77
91
|
- lib/capistrano/cookbook/logs.rb
|
78
92
|
- lib/capistrano/cookbook/monit.rb
|
79
93
|
- lib/capistrano/cookbook/nginx.rb
|
80
|
-
- lib/capistrano/cookbook/restart.rb
|
81
94
|
- lib/capistrano/cookbook/run_tests.rb
|
82
95
|
- lib/capistrano/cookbook/setup_config.rb
|
96
|
+
- lib/capistrano/cookbook/systemd.rb
|
83
97
|
- lib/capistrano/cookbook/tasks/check_revision.cap
|
84
98
|
- lib/capistrano/cookbook/tasks/compile_assets_locally.cap
|
85
99
|
- lib/capistrano/cookbook/tasks/create_database.cap
|
86
100
|
- lib/capistrano/cookbook/tasks/logs.cap
|
87
101
|
- lib/capistrano/cookbook/tasks/monit.cap
|
88
102
|
- lib/capistrano/cookbook/tasks/nginx.cap
|
89
|
-
- lib/capistrano/cookbook/tasks/restart.cap
|
90
103
|
- lib/capistrano/cookbook/tasks/run_tests.cap
|
91
104
|
- lib/capistrano/cookbook/tasks/setup_config.cap
|
105
|
+
- lib/capistrano/cookbook/tasks/systemd.cap
|
92
106
|
- lib/capistrano/cookbook/templates/database.example.yml.erb
|
93
107
|
- lib/capistrano/cookbook/templates/log_rotation.erb
|
94
|
-
- lib/capistrano/cookbook/templates/mongoid.example.yml.erb
|
95
|
-
- lib/capistrano/cookbook/templates/monit.erb
|
96
|
-
- lib/capistrano/cookbook/templates/nginx.conf.erb
|
97
|
-
- lib/capistrano/cookbook/templates/secrets.yml.erb
|
98
108
|
- lib/capistrano/cookbook/templates/sidekiq.yml.erb
|
99
109
|
- lib/capistrano/cookbook/templates/sidekiq_init.sh.erb
|
100
|
-
- lib/capistrano/cookbook/templates/unicorn.rb.erb
|
101
|
-
- lib/capistrano/cookbook/templates/unicorn_init.sh.erb
|
102
110
|
- lib/capistrano/cookbook/version.rb
|
111
|
+
- lib/generators/capistrano/reliably_deploying_rails/bootstrap_generator.rb
|
112
|
+
- lib/generators/capistrano/reliably_deploying_rails/templates/Capfile.erb
|
113
|
+
- lib/generators/capistrano/reliably_deploying_rails/templates/deploy.rb.erb
|
114
|
+
- lib/generators/capistrano/reliably_deploying_rails/templates/nginx_conf.erb
|
115
|
+
- lib/generators/capistrano/reliably_deploying_rails/templates/production.rb.erb
|
116
|
+
- lib/generators/capistrano/reliably_deploying_rails/templates/puma.rb.erb
|
117
|
+
- lib/generators/capistrano/reliably_deploying_rails/templates/puma.service.erb
|
118
|
+
- lib/generators/capistrano/reliably_deploying_rails/templates/puma_monit.conf.erb
|
119
|
+
- lib/generators/capistrano/reliably_deploying_rails/templates/sidekiq.service.capistrano.erb
|
120
|
+
- lib/generators/capistrano/reliably_deploying_rails/templates/sidekiq_monit.erb
|
121
|
+
- lib/generators/capistrano/reliably_deploying_rails/templates/staging.rb.erb
|
103
122
|
homepage: https://github.com/TalkingQuickly/capistrano-cookbook
|
104
123
|
licenses:
|
105
124
|
- MIT
|
@@ -119,8 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
138
|
- !ruby/object:Gem::Version
|
120
139
|
version: '0'
|
121
140
|
requirements: []
|
122
|
-
|
123
|
-
rubygems_version: 2.2.2
|
141
|
+
rubygems_version: 3.1.4
|
124
142
|
signing_key:
|
125
143
|
specification_version: 4
|
126
144
|
summary: Selection of Capistrano 3 tasks to reduce boilerplate required when deploying
|
@@ -1 +0,0 @@
|
|
1
|
-
load File.expand_path("tasks/restart.cap", File.dirname(__FILE__))
|
@@ -1,13 +0,0 @@
|
|
1
|
-
namespace :deploy do
|
2
|
-
desc 'Commands for unicorn application'
|
3
|
-
%w(start stop force-stop restart upgrade reopen-logs).each do |command|
|
4
|
-
task command.to_sym do
|
5
|
-
on roles(:app), in: :sequence, wait: 5 do
|
6
|
-
sudo "/etc/init.d/unicorn_#{fetch(:full_app_name)} #{command}"
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
# Automatically restart after a deploy
|
13
|
-
after 'deploy', 'deploy:restart'
|
@@ -1,69 +0,0 @@
|
|
1
|
-
<%= fetch(:rails_env) %>:
|
2
|
-
# Configure available database sessions. (required)
|
3
|
-
sessions:
|
4
|
-
# Defines the default session. (required)
|
5
|
-
default:
|
6
|
-
# Defines the name of the default database that Mongoid can connect to.
|
7
|
-
# (required).
|
8
|
-
database: <%= "#{fetch(:application)}_#{fetch(:rails_env)}" %>
|
9
|
-
# Provides the hosts the default session can connect to. Must be an array
|
10
|
-
# of host:port pairs. (required)
|
11
|
-
hosts:
|
12
|
-
- localhost
|
13
|
-
options:
|
14
|
-
# Change whether the session persists in safe mode by default.
|
15
|
-
# (default: false)
|
16
|
-
safe: true
|
17
|
-
|
18
|
-
# Change the default consistency model to :eventual or :strong.
|
19
|
-
# :eventual will send reads to secondaries, :strong sends everything
|
20
|
-
# to master. (default: :eventual)
|
21
|
-
# consistency: :eventual
|
22
|
-
|
23
|
-
# How many times Moped should attempt to retry an operation after
|
24
|
-
# failure. (default: 30)
|
25
|
-
# max_retries: 30
|
26
|
-
|
27
|
-
# The time in seconds that Moped should wait before retrying an
|
28
|
-
# operation on failure. (default: 1)
|
29
|
-
# retry_interval: 1
|
30
|
-
# Configure Mongoid specific options. (optional)
|
31
|
-
options:
|
32
|
-
# Configuration for whether or not to allow access to fields that do
|
33
|
-
# not have a field definition on the model. (default: true)
|
34
|
-
# allow_dynamic_fields: true
|
35
|
-
|
36
|
-
# Enable the identity map, needed for eager loading. (default: false)
|
37
|
-
identity_map_enabled: true
|
38
|
-
|
39
|
-
# Includes the root model name in json serialization. (default: false)
|
40
|
-
# include_root_in_json: false
|
41
|
-
|
42
|
-
# Include the _type field in serializaion. (default: false)
|
43
|
-
# include_type_for_serialization: false
|
44
|
-
|
45
|
-
# Preload all models in development, needed when models use
|
46
|
-
# inheritance. (default: false)
|
47
|
-
# preload_models: false
|
48
|
-
|
49
|
-
# Protect id and type from mass assignment. (default: true)
|
50
|
-
# protect_sensitive_fields: true
|
51
|
-
|
52
|
-
# Raise an error when performing a #find and the document is not found.
|
53
|
-
# (default: true)
|
54
|
-
# raise_not_found_error: true
|
55
|
-
|
56
|
-
# Raise an error when defining a scope with the same name as an
|
57
|
-
# existing method. (default: false)
|
58
|
-
# scope_overwrite_exception: false
|
59
|
-
|
60
|
-
# Skip the database version check, used when connecting to a db without
|
61
|
-
# admin access. (default: false)
|
62
|
-
# skip_version_check: false
|
63
|
-
|
64
|
-
# User Active Support's time zone in conversions. (default: true)
|
65
|
-
|
66
|
-
# Ensure all times are UTC in the app side. (default: false)
|
67
|
-
use_utc: true
|
68
|
-
|
69
|
-
|
@@ -1,22 +0,0 @@
|
|
1
|
-
<% application = fetch(:application) %>
|
2
|
-
set mail-format { subject: <%= "#{fetch(:full_app_name)} - #{fetch(:rails_env)}" %> $SERVICE $EVENT at $DATE }
|
3
|
-
|
4
|
-
check process unicorn_<%=application%>
|
5
|
-
with pidfile <%= current_path %>/tmp/pids/unicorn.pid
|
6
|
-
start program = "/etc/init.d/unicorn_<%= application %>_<%= fetch(:rails_env)%> start"
|
7
|
-
stop program = "/etc/init.d/unicorn_<%= application %>_<%= fetch(:rails_env)%> stop"
|
8
|
-
if mem is greater than 300.0 MB for 1 cycles then restart # eating up memory?
|
9
|
-
if cpu is greater than 50% for 2 cycles then alert # send an email to admin
|
10
|
-
if cpu is greater than 80% for 30 cycles then restart # hung process?
|
11
|
-
group unicorn
|
12
|
-
|
13
|
-
<% (0..(fetch(:unicorn_worker_count) -1)).each do |worker| %>
|
14
|
-
check process unicorn_<%= application %>_worker_<%= (5000 + worker).to_s %>
|
15
|
-
with pidfile <%= current_path %>/tmp/pids/unicorn.<%= (5000 + worker).to_s %>.pid
|
16
|
-
start program = "/bin/true"
|
17
|
-
stop program = "/etc/init.d/unicorn_<%= application %>_<%= fetch(:rails_env)%> kill_worker <%= (5000 + worker).to_s %>"
|
18
|
-
if mem is greater than 350.0 MB for 1 cycles then restart
|
19
|
-
if cpu is greater than 80% for 30 cycles then restart
|
20
|
-
|
21
|
-
group unicorn_workers
|
22
|
-
<% end %>
|
@@ -1,57 +0,0 @@
|
|
1
|
-
upstream unicorn_<%= fetch(:full_app_name) %> {
|
2
|
-
server unix:/tmp/unicorn.<%= fetch(:full_app_name) %>.sock fail_timeout=0;
|
3
|
-
}
|
4
|
-
|
5
|
-
server {
|
6
|
-
listen 80;
|
7
|
-
root <%= fetch(:deploy_to) %>/current/public;
|
8
|
-
server_name <%= fetch(:server_name) %>;
|
9
|
-
|
10
|
-
location ^~ /assets/ {
|
11
|
-
gzip_static on;
|
12
|
-
expires max;
|
13
|
-
add_header Cache-Control public;
|
14
|
-
}
|
15
|
-
|
16
|
-
try_files $uri/index.html $uri @unicorn;
|
17
|
-
location @unicorn {
|
18
|
-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
19
|
-
proxy_set_header Host $http_host;
|
20
|
-
proxy_redirect off;
|
21
|
-
proxy_pass http://unicorn_<%= fetch(:full_app_name) %>;
|
22
|
-
}
|
23
|
-
|
24
|
-
error_page 500 502 503 504 /500.html;
|
25
|
-
client_max_body_size 4G;
|
26
|
-
keepalive_timeout 10;
|
27
|
-
}
|
28
|
-
|
29
|
-
<% if fetch(:enable_ssl) %>
|
30
|
-
server {
|
31
|
-
listen 443 default deferred;
|
32
|
-
root <%= fetch(:deploy_to) %>/current/public;
|
33
|
-
server_name <%= fetch(:server_name) %>;
|
34
|
-
|
35
|
-
location ^~ /assets/ {
|
36
|
-
gzip_static on;
|
37
|
-
expires max;
|
38
|
-
add_header Cache-Control public;
|
39
|
-
}
|
40
|
-
|
41
|
-
try_files $uri/index.html $uri @unicorn;
|
42
|
-
location @unicorn {
|
43
|
-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
44
|
-
proxy_set_header X-Forwarded-Proto https;
|
45
|
-
proxy_set_header Host $http_host;
|
46
|
-
proxy_redirect off;
|
47
|
-
proxy_pass http://unicorn_<%= fetch(:full_app_name) %>;
|
48
|
-
}
|
49
|
-
|
50
|
-
error_page 500 502 503 504 /500.html;
|
51
|
-
client_max_body_size 4G;
|
52
|
-
keepalive_timeout 10;
|
53
|
-
ssl on;
|
54
|
-
ssl_certificate <%= fetch(:deploy_to) %>/shared/ssl_cert.crt;
|
55
|
-
ssl_certificate_key <%= fetch(:deploy_to) %>/shared/ssl_private_key.key;
|
56
|
-
}
|
57
|
-
<% end %>
|
@@ -1,41 +0,0 @@
|
|
1
|
-
root = "<%= current_path %>"
|
2
|
-
working_directory root
|
3
|
-
pid "#{root}/tmp/pids/unicorn.pid"
|
4
|
-
stderr_path "#{root}/log/unicorn.log"
|
5
|
-
stdout_path "#{root}/log/unicorn.log"
|
6
|
-
|
7
|
-
listen "/tmp/unicorn.<%= fetch(:full_app_name) %>.sock"
|
8
|
-
worker_processes <%= fetch(:unicorn_worker_count) %>
|
9
|
-
timeout 40
|
10
|
-
preload_app true
|
11
|
-
|
12
|
-
# Force unicorn to look at the Gemfile in the current_path
|
13
|
-
# otherwise once we've first started a master process, it
|
14
|
-
# will always point to the first one it started.
|
15
|
-
before_exec do |server|
|
16
|
-
ENV['BUNDLE_GEMFILE'] = "<%= current_path %>/Gemfile"
|
17
|
-
end
|
18
|
-
|
19
|
-
before_fork do |server, worker|
|
20
|
-
defined?(ActiveRecord::Base) and
|
21
|
-
ActiveRecord::Base.connection.disconnect!
|
22
|
-
# Quit the old unicorn process
|
23
|
-
old_pid = "#{server.config[:pid]}.oldbin"
|
24
|
-
if File.exists?(old_pid) && server.pid != old_pid
|
25
|
-
puts "We've got an old pid and server pid is not the old pid"
|
26
|
-
begin
|
27
|
-
Process.kill("QUIT", File.read(old_pid).to_i)
|
28
|
-
puts "killing master process (good thing tm)"
|
29
|
-
rescue Errno::ENOENT, Errno::ESRCH
|
30
|
-
puts "unicorn master already killed"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
after_fork do |server, worker|
|
36
|
-
port = 5000 + worker.nr
|
37
|
-
child_pid = server.config[:pid].sub('.pid', ".#{port}.pid")
|
38
|
-
system("echo #{Process.pid} > #{child_pid}")
|
39
|
-
defined?(ActiveRecord::Base) and
|
40
|
-
ActiveRecord::Base.establish_connection
|
41
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
#!/bin/sh
|
2
|
-
set -e
|
3
|
-
|
4
|
-
# Feel free to change any of the following variables for your app:
|
5
|
-
TIMEOUT=${TIMEOUT-60}
|
6
|
-
APP_ROOT=<%= current_path %>
|
7
|
-
PID_DIR=$APP_ROOT/tmp/pids
|
8
|
-
PID=$PID_DIR/unicorn.pid
|
9
|
-
CMD="cd $APP_ROOT; bundle exec unicorn -D -c <%= "#{shared_path}/config/unicorn.rb" %> -E <%= fetch(:rails_env) %>"
|
10
|
-
AS_USER=deploy
|
11
|
-
set -u
|
12
|
-
|
13
|
-
OLD_PIN="$PID.oldbin"
|
14
|
-
|
15
|
-
sig () {
|
16
|
-
test -s "$PID" && kill -$1 `cat $PID`
|
17
|
-
}
|
18
|
-
|
19
|
-
oldsig () {
|
20
|
-
test -s $OLD_PIN && kill -$1 `cat $OLD_PIN`
|
21
|
-
}
|
22
|
-
|
23
|
-
workersig () {
|
24
|
-
workerpid="$APP_ROOT/tmp/pids/unicorn.$2.pid"
|
25
|
-
|
26
|
-
test -s "$workerpid" && kill -$1 `cat $workerpid`
|
27
|
-
}
|
28
|
-
|
29
|
-
run () {
|
30
|
-
if [ "$(id -un)" = "$AS_USER" ]; then
|
31
|
-
eval $1
|
32
|
-
else
|
33
|
-
su -c "$1" - $AS_USER
|
34
|
-
fi
|
35
|
-
}
|
36
|
-
|
37
|
-
case "$1" in
|
38
|
-
start)
|
39
|
-
sig 0 && echo >&2 "Already running" && exit 0
|
40
|
-
run "$CMD"
|
41
|
-
;;
|
42
|
-
stop)
|
43
|
-
sig QUIT && exit 0
|
44
|
-
echo >&2 "Not running"
|
45
|
-
;;
|
46
|
-
force-stop)
|
47
|
-
sig TERM && exit 0
|
48
|
-
echo >&2 "Not running"
|
49
|
-
;;
|
50
|
-
kill_worker)
|
51
|
-
workersig QUIT $2 && exit 0
|
52
|
-
echo >&2 "Worker not running"
|
53
|
-
;;
|
54
|
-
restart|reload)
|
55
|
-
sig USR2 && echo reloaded OK && exit 0
|
56
|
-
echo >&2 "Couldn't reload, starting '$CMD' instead"
|
57
|
-
run "$CMD"
|
58
|
-
;;
|
59
|
-
upgrade)
|
60
|
-
if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
|
61
|
-
then
|
62
|
-
n=$TIMEOUT
|
63
|
-
while test -s $OLD_PIN && test $n -ge 0
|
64
|
-
do
|
65
|
-
printf '.' && sleep 1 && n=$(( $n - 1 ))
|
66
|
-
done
|
67
|
-
echo
|
68
|
-
|
69
|
-
if test $n -lt 0 && test -s $OLD_PIN
|
70
|
-
then
|
71
|
-
echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds"
|
72
|
-
exit 1
|
73
|
-
fi
|
74
|
-
exit 0
|
75
|
-
fi
|
76
|
-
echo >&2 "Couldn't upgrade, starting '$CMD' instead"
|
77
|
-
run "$CMD"
|
78
|
-
;;
|
79
|
-
reopen-logs)
|
80
|
-
sig USR1
|
81
|
-
;;
|
82
|
-
*)
|
83
|
-
echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
|
84
|
-
exit 1
|
85
|
-
;;
|
86
|
-
esac
|