capistrano-unicorn-nginx 0.0.1
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 +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.md +19 -0
- data/README.md +189 -0
- data/Rakefile +1 -0
- data/capistrano-unicorn-nginx.gemspec +32 -0
- data/lib/capistrano-unicorn-nginx.rb +0 -0
- data/lib/capistrano/tasks/nginx.rake +68 -0
- data/lib/capistrano/tasks/unicorn.rake +56 -0
- data/lib/capistrano/unicorn_nginx.rb +2 -0
- data/lib/capistrano/unicorn_nginx/helpers.rb +27 -0
- data/lib/capistrano/unicorn_nginx/version.rb +5 -0
- data/lib/generators/capistrano/unicorn_nginx/USAGE.md +9 -0
- data/lib/generators/capistrano/unicorn_nginx/config_generator.rb +20 -0
- data/lib/generators/capistrano/unicorn_nginx/templates/nginx_conf.erb +78 -0
- data/lib/generators/capistrano/unicorn_nginx/templates/unicorn.rb.erb +48 -0
- data/lib/generators/capistrano/unicorn_nginx/templates/unicorn_init.erb +87 -0
- metadata +107 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 334f1a9b32d324cb61abc30de2f70652e7e5d01c
|
4
|
+
data.tar.gz: 491c76d4ccd11448b9603a55c699284bd25e48e9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a5ead97ec48101db2a2a10143ed0c2b4a39094ae47b051f37eb007a8b580735aa4b05626b4f7b6e92f29ff26b3b1f6701481031433b2980bb16879723389b72d
|
7
|
+
data.tar.gz: 26249b36ecb21b3c990d0f8aa40c02044d6bff1813f88babc066c722285cf85439dada54793248239d9cea3a1966969e58f59752dc7f37e2703d2a980b3a0773
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2014 Bruno Sutic
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the "Software"),
|
5
|
+
to deal in the Software without restriction, including without limitation
|
6
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
7
|
+
and/or sell copies of the Software, and to permit persons to whom the
|
8
|
+
Software is furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included
|
11
|
+
in all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
14
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
15
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
16
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
17
|
+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
18
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
19
|
+
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
# Capistrano-Nginx-Unicorn
|
2
|
+
|
3
|
+
Capistrano tasks for configuration and management nginx+unicorn combo for zero downtime deployments of Rails applications.
|
4
|
+
|
5
|
+
Provides capistrano tasks to:
|
6
|
+
|
7
|
+
* easily add application to nginx and reload it's configuration
|
8
|
+
* create unicorn init script for application, so it will be automatically started when OS restarts
|
9
|
+
* start/stop unicorn (also can be done using `sudo service unicorn_<your_app> start/stop`)
|
10
|
+
* reload unicorn using `USR2` signal to load new application version with zero downtime
|
11
|
+
* creates logrotate record to rotate application logs
|
12
|
+
|
13
|
+
Provides several capistrano variables for easy customization.
|
14
|
+
Also, for full customization, all configs can be copied to the application using generators.
|
15
|
+
|
16
|
+
## Installation
|
17
|
+
|
18
|
+
Add this line to your application's Gemfile:
|
19
|
+
|
20
|
+
gem 'capistrano-nginx-unicorn', require: false, group: :development
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
$ bundle
|
25
|
+
|
26
|
+
Or install it yourself as:
|
27
|
+
|
28
|
+
$ gem install capistrano-nginx-unicorn
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
Add this line to your `deploy.rb`
|
33
|
+
|
34
|
+
require 'capistrano-nginx-unicorn'
|
35
|
+
|
36
|
+
Note, that following capistrano variables should be defined:
|
37
|
+
|
38
|
+
application
|
39
|
+
current_path
|
40
|
+
shared_path
|
41
|
+
user
|
42
|
+
|
43
|
+
You can check that new tasks are available (`cap -T`):
|
44
|
+
|
45
|
+
for nginx:
|
46
|
+
|
47
|
+
# add and enable application to nginx
|
48
|
+
cap nginx:setup
|
49
|
+
|
50
|
+
# reload nginx configuration
|
51
|
+
cap nginx:reload
|
52
|
+
|
53
|
+
and for unicorn:
|
54
|
+
|
55
|
+
# create unicorn configuration and init script
|
56
|
+
cap unicorn:setup
|
57
|
+
|
58
|
+
# start unicorn
|
59
|
+
cap unicorn:start
|
60
|
+
|
61
|
+
# stop unicorn
|
62
|
+
cap unicorn:stop
|
63
|
+
|
64
|
+
# reload unicorn with no downtime
|
65
|
+
# old workers will process new request until new master is fully loaded
|
66
|
+
# then old workers will be automatically killed and new workers will start processing requests
|
67
|
+
cap unicorn:restart
|
68
|
+
|
69
|
+
and shared:
|
70
|
+
|
71
|
+
# create logrotate record to rotate application logs
|
72
|
+
cap logrotate
|
73
|
+
|
74
|
+
There is no need to execute any of these tasks manually.
|
75
|
+
They will be called automatically on different deploy stages:
|
76
|
+
|
77
|
+
* `nginx:setup`, `nginx:reload`, `unicorn:setup` and `logrotate` are hooked to `deploy:setup`
|
78
|
+
* `unicorn:restart` is hooked to `deploy:restart`
|
79
|
+
|
80
|
+
This means that if you run `cap deploy:setup`,
|
81
|
+
nginx and unicorn will be automatically configured.
|
82
|
+
And after each deploy, unicorn will be automatically reloaded.
|
83
|
+
|
84
|
+
However, if you changed variables or customized templates,
|
85
|
+
you can run any of these tasks to update configuration.
|
86
|
+
|
87
|
+
## Customization
|
88
|
+
|
89
|
+
### Using variables
|
90
|
+
|
91
|
+
You can customize nginx and unicorn configs using capistrano variables:
|
92
|
+
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
# path to customized templates (see below for details)
|
96
|
+
# default value: "config/deploy/templates"
|
97
|
+
set :templates_path, "config/deploy/templates"
|
98
|
+
|
99
|
+
# server name for nginx, default value: no (will be prompted if not set)
|
100
|
+
# set this to your site name as it is visible from outside
|
101
|
+
# this will allow 1 nginx to serve several sites with different `server_name`
|
102
|
+
set :nginx_server_name, "example.com"
|
103
|
+
|
104
|
+
# path, where unicorn pid file will be stored
|
105
|
+
# default value: `"#{current_path}/tmp/pids/unicorn.pid"`
|
106
|
+
set :unicorn_pid, "#{current_path}/tmp/pids/unicorn.pid"
|
107
|
+
|
108
|
+
# path, where nginx pid file will be stored (used in logrotate recipe)
|
109
|
+
# default value: `"/run/nginx.pid"`
|
110
|
+
set :nginx_pid, "/run/nginx.pid"
|
111
|
+
|
112
|
+
# path, where unicorn config file will be stored
|
113
|
+
# default value: `"#{shared_path}/config/unicorn.rb"`
|
114
|
+
set :unicorn_config, "#{shared_path}/config/unicorn.rb"
|
115
|
+
|
116
|
+
# path, where unicorn log file will be stored
|
117
|
+
# default value: `"#{shared_path}/config/unicorn.rb"`
|
118
|
+
set :unicorn_log, "#{shared_path}/config/unicorn.rb"
|
119
|
+
|
120
|
+
# user name to run unicorn
|
121
|
+
# default value: `user` (user varibale defined in your `deploy.rb`)
|
122
|
+
set :unicorn_user, "user"
|
123
|
+
|
124
|
+
# number of unicorn workers
|
125
|
+
# default value: no (will be prompted if not set)
|
126
|
+
set :unicorn_workers, 4
|
127
|
+
|
128
|
+
# if set, nginx will be configured to 443 port and port 80 will be auto rewritten to 443
|
129
|
+
# also, on `nginx:setup`, paths to ssl certificate and key will be configured
|
130
|
+
# and certificate file and key will be copied to `/etc/ssl/certs` and `/etc/ssl/private/` directories
|
131
|
+
# default value: false
|
132
|
+
set :nginx_use_ssl, false
|
133
|
+
|
134
|
+
# if set, it will ask to upload certificates from a local path. Otherwise, it will expect
|
135
|
+
# the certificate and key defined in the next 2 variables to be already in the server.
|
136
|
+
set :nginx_upload_local_certificate, { true }
|
137
|
+
|
138
|
+
# remote file name of the certificate, only makes sense if `nginx_use_ssl` is set
|
139
|
+
# default value: `nginx_server_name + ".crt"`
|
140
|
+
set :nginx_ssl_certificate, "#{nginx_server_name}.crt"
|
141
|
+
|
142
|
+
# remote file name of the certificate, only makes sense if `nginx_use_ssl` is set
|
143
|
+
# default value: `nginx_server_name + ".key"`
|
144
|
+
set :nginx_ssl_certificate_key, "#{nginx_server_name}.key"
|
145
|
+
|
146
|
+
# local path to file with certificate, only makes sense if `nginx_use_ssl` is set
|
147
|
+
# this file will be copied to remote server
|
148
|
+
# default value: none (will be prompted if not set)
|
149
|
+
set :nginx_ssl_certificate_local_path, "/home/ivalkeen/ssl/myssl.cert"
|
150
|
+
|
151
|
+
# local path to file with certificate key, only makes sense if `nginx_use_ssl` is set
|
152
|
+
# this file will be copied to remote server
|
153
|
+
# default value: none (will be prompted if not set)
|
154
|
+
set :nginx_ssl_certificate_key_local_path, "/home/ivalkeen/ssl/myssl.key"
|
155
|
+
```
|
156
|
+
|
157
|
+
For example, of you site name is `example.com` and you want to use 8 unicorn workers,
|
158
|
+
your `deploy.rb` will look like this:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
set :server_name, "example.com"
|
162
|
+
set :unicorn_workers, 4
|
163
|
+
require 'capistrano-nginx-unicorn'
|
164
|
+
```
|
165
|
+
|
166
|
+
### Template Customization
|
167
|
+
|
168
|
+
If you want to change default templates, you can generate them using `rails generator`
|
169
|
+
|
170
|
+
rails g capistrano:nginx_unicorn:config
|
171
|
+
|
172
|
+
This will copy default templates to `config/deploy/templates` directory,
|
173
|
+
so you can customize them as you like, and capistrano tasks will use this templates instead of default.
|
174
|
+
|
175
|
+
You can also provide path, where to generate templates:
|
176
|
+
|
177
|
+
rails g capistrano:nginx_unicorn:config config/templates
|
178
|
+
|
179
|
+
# TODO:
|
180
|
+
|
181
|
+
* add tests
|
182
|
+
|
183
|
+
## Contributing
|
184
|
+
|
185
|
+
1. Fork it
|
186
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
187
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
188
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
189
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'capistrano/unicorn_nginx/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "capistrano-unicorn-nginx"
|
8
|
+
gem.version = Capistrano::UnicornNginx::VERSION
|
9
|
+
gem.authors = ["Bruno Sutic"]
|
10
|
+
gem.email = ["bruno.sutic@gmail.com"]
|
11
|
+
gem.description = <<-EOF.gsub(/^\s+/, '')
|
12
|
+
Capistrano tasks for automatic and sensible unicorn + nginx configuraion.
|
13
|
+
|
14
|
+
Enables zero downtime deployments of Rails applications. Configs can be
|
15
|
+
copied to the application using generators and easily customized.
|
16
|
+
|
17
|
+
Works *only* with Capistrano 3+. For Capistrano 2 try version 0.0.8 of this
|
18
|
+
gem: http://rubygems.org/gems/capistrano-nginx-unicorn
|
19
|
+
EOF
|
20
|
+
gem.summary = "Create and manage unicorn + nginx configs from capistrano"
|
21
|
+
gem.homepage = "https://github.com/bruno-/capistrano-unicorn-nginx"
|
22
|
+
|
23
|
+
gem.files = `git ls-files`.split($/)
|
24
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
25
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
26
|
+
gem.require_paths = ["lib"]
|
27
|
+
|
28
|
+
gem.add_dependency "capistrano", ">= 3.1"
|
29
|
+
gem.add_dependency "sshkit", ">= 1.2.0"
|
30
|
+
|
31
|
+
gem.add_development_dependency "rake"
|
32
|
+
end
|
File without changes
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'capistrano/unicorn_nginx/helpers'
|
2
|
+
|
3
|
+
include Capistrano::UnicornNginx::Helpers
|
4
|
+
|
5
|
+
namespace :load do
|
6
|
+
task :defaults do
|
7
|
+
set :templates_path, "config/deploy/templates"
|
8
|
+
set :nginx_server_name, -> { ask(:nginx_server_name, "Nginx server name: ") }
|
9
|
+
set :nginx_config_name, -> { "#{fetch(:application)}_#{fetch(:stage)}" }
|
10
|
+
set :nginx_use_ssl, false
|
11
|
+
set :nginx_pid, "/run/nginx.pid"
|
12
|
+
set :nginx_ssl_certificate, -> { "#{fetch(:nginx_server_name)}.crt" }
|
13
|
+
set :nginx_ssl_certificate_key, -> { "#{fetch(:nginx_server_name)}.key" }
|
14
|
+
set :nginx_upload_local_certificate, true
|
15
|
+
set :nginx_ssl_certificate_local_path, -> { ask(:nginx_ssl_certificate_local_path, "Local path to ssl certificate: ") }
|
16
|
+
set :nginx_ssl_certificate_key_local_path, -> { ask(:nginx_ssl_certificate_key_local_path, "Local path to ssl certificate key: ") }
|
17
|
+
set :nginx_config_path, "/etc/nginx/sites-available"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
namespace :nginx do
|
22
|
+
desc "Setup nginx configuration"
|
23
|
+
task :setup do
|
24
|
+
on roles(:web) do
|
25
|
+
next if file_exists? "#{fetch(:nginx_config_path)}/#{fetch(:nginx_config_name)}"
|
26
|
+
|
27
|
+
execute :mkdir, "-p", shared_path.join("log")
|
28
|
+
template("nginx_conf.erb", "/tmp/nginx_#{fetch(:nginx_config_name)}")
|
29
|
+
if fetch(:nginx_config_path) == "/etc/nginx/sites-available"
|
30
|
+
sudo :mv, "/tmp/nginx_#{fetch(:nginx_config_name)} /etc/nginx/sites-available/#{fetch(:nginx_config_name)}"
|
31
|
+
sudo :ln, "-fs", "/etc/nginx/sites-available/#{fetch(:nginx_config_name)} /etc/nginx/sites-enabled/#{fetch(:nginx_config_name)}"
|
32
|
+
else
|
33
|
+
sudo :mv, "/tmp/#{fetch(:nginx_config_name)} #{fetch(:nginx_config_path)}/#{fetch(:nginx_config_name)}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Setup nginx ssl certs"
|
39
|
+
task :setup_ssl do
|
40
|
+
on roles(:web) do
|
41
|
+
if fetch(:nginx_use_ssl)
|
42
|
+
if fetch(:nginx_upload_local_certificate)
|
43
|
+
upload! fetch(:nginx_ssl_certificate_local_path), "/tmp/#{fetch(:nginx_ssl_certificate)}"
|
44
|
+
upload! fetch(:nginx_ssl_certificate_key_local_path), "/tmp/#{fetch(:nginx_ssl_certificate_key)}"
|
45
|
+
|
46
|
+
sudo :mv, "/tmp/#{fetch(:nginx_ssl_certificate)} /etc/ssl/certs/#{fetch(:nginx_ssl_certificate)}"
|
47
|
+
sudo :mv, "/tmp/#{fetch(:nginx_ssl_certificate_key)} /etc/ssl/private/#{fetch(:nginx_ssl_certificate_key)}"
|
48
|
+
end
|
49
|
+
|
50
|
+
sudo :chown, "root:root /etc/ssl/certs/#{fetch(:nginx_ssl_certificate)}"
|
51
|
+
sudo :chown, "root:root /etc/ssl/private/#{fetch(:nginx_ssl_certificate_key)}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "Reload nginx configuration"
|
57
|
+
task :reload do
|
58
|
+
on roles(:web) do
|
59
|
+
sudo "/etc/init.d/nginx reload"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
namespace :deploy do
|
65
|
+
after :started, "nginx:setup"
|
66
|
+
after :started, "nginx:setup_ssl"
|
67
|
+
after :publishing, "nginx:reload"
|
68
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'capistrano/unicorn_nginx/helpers'
|
2
|
+
|
3
|
+
include Capistrano::UnicornNginx::Helpers
|
4
|
+
|
5
|
+
namespace :load do
|
6
|
+
task :defaults do
|
7
|
+
set :unicorn_service_name, -> { "unicorn_#{fetch(:application)}_#{fetch(:stage)}" }
|
8
|
+
set :templates_path, "config/deploy/templates"
|
9
|
+
set :unicorn_pid, -> { shared_path.join("pids/unicorn.pid") }
|
10
|
+
set :unicorn_config, -> { shared_path.join("config/unicorn.rb") }
|
11
|
+
set :unicorn_log, -> { shared_path.join("log/unicorn.log") }
|
12
|
+
set :unicorn_user, -> { fetch(:user) }
|
13
|
+
set :unicorn_workers, 2
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
namespace :unicorn do
|
18
|
+
desc "Setup Unicorn initializer"
|
19
|
+
task :setup_initializer do
|
20
|
+
on roles(:app) do
|
21
|
+
next if file_exists? "/etc/init.d/#{fetch(:unicorn_service_name)}"
|
22
|
+
|
23
|
+
template "unicorn_init.erb", "/tmp/unicorn_init"
|
24
|
+
execute :chmod, "+x", "/tmp/unicorn_init"
|
25
|
+
sudo :mv, "/tmp/unicorn_init /etc/init.d/#{fetch(:unicorn_service_name)}"
|
26
|
+
sudo "update-rc.d -f #{fetch(:unicorn_service_name)} defaults"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Setup Unicorn app configuration"
|
31
|
+
task :setup_app_config do
|
32
|
+
on roles(:app) do
|
33
|
+
next if file_exists? fetch(:unicorn_config)
|
34
|
+
|
35
|
+
execute :mkdir, "-p", shared_path.join("config")
|
36
|
+
execute :mkdir, "-p", shared_path.join("log")
|
37
|
+
execute :mkdir, "-p", shared_path.join("pids")
|
38
|
+
template "unicorn.rb.erb", fetch(:unicorn_config)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
%w[start stop restart].each do |command|
|
43
|
+
desc "#{command} unicorn"
|
44
|
+
task command do
|
45
|
+
on roles(:app) do
|
46
|
+
execute "service #{fetch(:unicorn_service_name)} #{command}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
namespace :deploy do
|
53
|
+
after :updated, "unicorn:setup_initializer"
|
54
|
+
after :updated, "unicorn:setup_app_config"
|
55
|
+
after :publishing, "unicorn:restart"
|
56
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
module UnicornNginx
|
5
|
+
module Helpers
|
6
|
+
|
7
|
+
def bundle_unicorn(*args)
|
8
|
+
SSHKit::Command.new(:bundle, :exec, :unicorn, args).to_command
|
9
|
+
end
|
10
|
+
|
11
|
+
def template(template_name, target)
|
12
|
+
config_file = "#{fetch(:templates_path)}/#{template_name}"
|
13
|
+
# if no customized file, proceed with default
|
14
|
+
unless File.exists?(config_file)
|
15
|
+
config_file = File.join(File.dirname(__FILE__), "../../generators/capistrano/unicorn_nginx/templates/#{template_name}")
|
16
|
+
end
|
17
|
+
config_stream = StringIO.new(ERB.new(File.read(config_file)).result(binding))
|
18
|
+
upload! config_stream, target
|
19
|
+
end
|
20
|
+
|
21
|
+
def file_exists?(path)
|
22
|
+
test "[ -e #{path} ]"
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
To create local nginx and unicorn configuration files call
|
2
|
+
|
3
|
+
bundle exec rails generate capistrano:unicorn_nginx:config [path]
|
4
|
+
|
5
|
+
The default path is "config/deploy/templates". You can override it like so:
|
6
|
+
|
7
|
+
bundle rails generate capistrano:unicorn_nginx:config "config/templates"
|
8
|
+
|
9
|
+
If you override templates path, don't forget to set "templates_path" variable in your deploy.rb
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Capistrano
|
2
|
+
module UnicornNginx
|
3
|
+
module Generators
|
4
|
+
class ConfigGenerator < Rails::Generators::Base
|
5
|
+
desc "Create local nginx and unicorn configuration files for customization"
|
6
|
+
source_root File.expand_path('../templates', __FILE__)
|
7
|
+
argument :templates_path, type: :string,
|
8
|
+
default: "config/deploy/templates",
|
9
|
+
banner: "path to templates"
|
10
|
+
|
11
|
+
def copy_template
|
12
|
+
copy_file "nginx_conf.erb", "#{templates_path}/nginx_conf.erb"
|
13
|
+
copy_file "unicorn.rb.erb", "#{templates_path}/unicorn.rb.erb"
|
14
|
+
copy_file "unicorn_init.erb", "#{templates_path}/unicorn_init.erb"
|
15
|
+
copy_file "logrotate.erb", "#{templates_path}/logrotate.erb"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
upstream unicorn_<%= fetch(:nginx_config_name) %> {
|
2
|
+
server unix:/tmp/unicorn.<%= fetch(:nginx_config_name) %>.sock fail_timeout=0;
|
3
|
+
}
|
4
|
+
|
5
|
+
<% if fetch(:nginx_use_ssl) %>
|
6
|
+
server {
|
7
|
+
listen 80;
|
8
|
+
rewrite ^(.*) https://$host$1 permanent;
|
9
|
+
}
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
server {
|
13
|
+
<% if fetch(:nginx_use_ssl) %>
|
14
|
+
listen 443;
|
15
|
+
ssl on;
|
16
|
+
ssl_certificate /etc/ssl/certs/<%= fetch(:nginx_ssl_certificate) %>;
|
17
|
+
ssl_certificate_key /etc/ssl/private/<%= fetch(:nginx_ssl_certificate_key) %>;
|
18
|
+
<% else %>
|
19
|
+
listen 80;
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
client_max_body_size 4G;
|
23
|
+
keepalive_timeout 10;
|
24
|
+
|
25
|
+
error_page 500 502 504 /500.html;
|
26
|
+
error_page 503 @503;
|
27
|
+
|
28
|
+
server_name <%= fetch(:nginx_server_name) %>;
|
29
|
+
root <%= current_path %>/public;
|
30
|
+
try_files $uri/index.html $uri @unicorn_<%= fetch(:nginx_config_name) %>;
|
31
|
+
|
32
|
+
location @unicorn_<%= fetch(:nginx_config_name) %> {
|
33
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
34
|
+
proxy_set_header Host $http_host;
|
35
|
+
proxy_redirect off;
|
36
|
+
<% if fetch(:nginx_use_ssl) %>
|
37
|
+
proxy_set_header X-Forwarded-Proto https;
|
38
|
+
<% end %>
|
39
|
+
proxy_pass http://unicorn_<%= fetch(:nginx_config_name) %>;
|
40
|
+
# limit_req zone=one;
|
41
|
+
access_log <%= shared_path %>/log/nginx.access.log;
|
42
|
+
error_log <%= shared_path %>/log/nginx.error.log;
|
43
|
+
}
|
44
|
+
|
45
|
+
location ^~ /assets/ {
|
46
|
+
gzip_static on;
|
47
|
+
expires max;
|
48
|
+
add_header Cache-Control public;
|
49
|
+
}
|
50
|
+
|
51
|
+
location = /50x.html {
|
52
|
+
root html;
|
53
|
+
}
|
54
|
+
|
55
|
+
location = /404.html {
|
56
|
+
root html;
|
57
|
+
}
|
58
|
+
|
59
|
+
location @503 {
|
60
|
+
error_page 405 = /system/maintenance.html;
|
61
|
+
if (-f $document_root/system/maintenance.html) {
|
62
|
+
rewrite ^(.*)$ /system/maintenance.html break;
|
63
|
+
}
|
64
|
+
rewrite ^(.*)$ /503.html break;
|
65
|
+
}
|
66
|
+
|
67
|
+
if ($request_method !~ ^(GET|HEAD|PUT|POST|DELETE|OPTIONS)$ ){
|
68
|
+
return 405;
|
69
|
+
}
|
70
|
+
|
71
|
+
if (-f $document_root/system/maintenance.html) {
|
72
|
+
return 503;
|
73
|
+
}
|
74
|
+
|
75
|
+
location ~ \.(php|html)$ {
|
76
|
+
return 405;
|
77
|
+
}
|
78
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
working_directory "<%= current_path %>"
|
2
|
+
pid "<%= fetch(:unicorn_pid) %>"
|
3
|
+
stderr_path "<%= fetch(:unicorn_log) %>"
|
4
|
+
stdout_path "<%= fetch(:unicorn_log) %>"
|
5
|
+
|
6
|
+
listen "/tmp/unicorn.<%= fetch(:nginx_config_name) %>.sock"
|
7
|
+
worker_processes <%= fetch(:unicorn_workers) %>
|
8
|
+
timeout 30
|
9
|
+
|
10
|
+
preload_app true
|
11
|
+
|
12
|
+
before_exec do |server|
|
13
|
+
ENV["BUNDLE_GEMFILE"] = "<%= current_path %>/Gemfile"
|
14
|
+
end
|
15
|
+
|
16
|
+
before_fork do |server, worker|
|
17
|
+
# Disconnect since the database connection will not carry over
|
18
|
+
if defined? ActiveRecord::Base
|
19
|
+
ActiveRecord::Base.connection.disconnect!
|
20
|
+
end
|
21
|
+
|
22
|
+
# Quit the old unicorn process
|
23
|
+
old_pid = "#{server.config[:pid]}.oldbin"
|
24
|
+
if File.exists?(old_pid) && server.pid != old_pid
|
25
|
+
begin
|
26
|
+
Process.kill("QUIT", File.read(old_pid).to_i)
|
27
|
+
rescue Errno::ENOENT, Errno::ESRCH
|
28
|
+
# someone else did our job for us
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
if defined?(Resque)
|
33
|
+
Resque.redis.quit
|
34
|
+
end
|
35
|
+
|
36
|
+
sleep 1
|
37
|
+
end
|
38
|
+
|
39
|
+
after_fork do |server, worker|
|
40
|
+
# Start up the database connection again in the worker
|
41
|
+
if defined?(ActiveRecord::Base)
|
42
|
+
ActiveRecord::Base.establish_connection
|
43
|
+
end
|
44
|
+
|
45
|
+
if defined?(Resque)
|
46
|
+
Resque.redis = 'localhost:6379'
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
### BEGIN INIT INFO
|
3
|
+
# Provides: unicorn
|
4
|
+
# Required-Start: $remote_fs $syslog
|
5
|
+
# Required-Stop: $remote_fs $syslog
|
6
|
+
# Default-Start: 2 3 4 5
|
7
|
+
# Default-Stop: 0 1 6
|
8
|
+
# Short-Description: Manage unicorn server
|
9
|
+
# Description: Start, stop, restart unicorn server for a specific application.
|
10
|
+
### END INIT INFO
|
11
|
+
set -e
|
12
|
+
|
13
|
+
# Feel free to change any of the following variables for your app:
|
14
|
+
TIMEOUT=${TIMEOUT-60}
|
15
|
+
APP_ROOT=<%= current_path %>
|
16
|
+
PID=<%= fetch(:unicorn_pid) %>
|
17
|
+
|
18
|
+
CMD="cd $APP_ROOT && <%= bundle_unicorn("-D -c", fetch(:unicorn_config), "-E", fetch(:stage)) %>"
|
19
|
+
|
20
|
+
AS_USER=<%= fetch(:unicorn_user) %>
|
21
|
+
set -u
|
22
|
+
|
23
|
+
OLD_PIN="$PID.oldbin"
|
24
|
+
|
25
|
+
sig () {
|
26
|
+
test -s "$PID" && kill -$1 `cat $PID`
|
27
|
+
}
|
28
|
+
|
29
|
+
oldsig () {
|
30
|
+
test -s $OLD_PIN && kill -$1 `cat $OLD_PIN`
|
31
|
+
}
|
32
|
+
|
33
|
+
run () {
|
34
|
+
if [ "$(id -un)" = "$AS_USER" ]; then
|
35
|
+
eval $1
|
36
|
+
else
|
37
|
+
su -c "$1" - $AS_USER
|
38
|
+
fi
|
39
|
+
}
|
40
|
+
|
41
|
+
case "$1" in
|
42
|
+
start)
|
43
|
+
sig 0 && echo >&2 "Already running" && exit 0
|
44
|
+
run "$CMD"
|
45
|
+
;;
|
46
|
+
stop)
|
47
|
+
sig QUIT && exit 0
|
48
|
+
echo >&2 "Not running"
|
49
|
+
;;
|
50
|
+
force-stop)
|
51
|
+
sig TERM && exit 0
|
52
|
+
echo >&2 "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
|
87
|
+
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: capistrano-unicorn-nginx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bruno Sutic
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: capistrano
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sshkit
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.2.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.2.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: |
|
56
|
+
Capistrano tasks for automatic and sensible unicorn + nginx configuraion.
|
57
|
+
Enables zero downtime deployments of Rails applications. Configs can be
|
58
|
+
copied to the application using generators and easily customized.
|
59
|
+
Works *only* with Capistrano 3+. For Capistrano 2 try version 0.0.8 of this
|
60
|
+
gem: http://rubygems.org/gems/capistrano-nginx-unicorn
|
61
|
+
email:
|
62
|
+
- bruno.sutic@gmail.com
|
63
|
+
executables: []
|
64
|
+
extensions: []
|
65
|
+
extra_rdoc_files: []
|
66
|
+
files:
|
67
|
+
- ".gitignore"
|
68
|
+
- Gemfile
|
69
|
+
- LICENSE.md
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- capistrano-unicorn-nginx.gemspec
|
73
|
+
- lib/capistrano-unicorn-nginx.rb
|
74
|
+
- lib/capistrano/tasks/nginx.rake
|
75
|
+
- lib/capistrano/tasks/unicorn.rake
|
76
|
+
- lib/capistrano/unicorn_nginx.rb
|
77
|
+
- lib/capistrano/unicorn_nginx/helpers.rb
|
78
|
+
- lib/capistrano/unicorn_nginx/version.rb
|
79
|
+
- lib/generators/capistrano/unicorn_nginx/USAGE.md
|
80
|
+
- lib/generators/capistrano/unicorn_nginx/config_generator.rb
|
81
|
+
- lib/generators/capistrano/unicorn_nginx/templates/nginx_conf.erb
|
82
|
+
- lib/generators/capistrano/unicorn_nginx/templates/unicorn.rb.erb
|
83
|
+
- lib/generators/capistrano/unicorn_nginx/templates/unicorn_init.erb
|
84
|
+
homepage: https://github.com/bruno-/capistrano-unicorn-nginx
|
85
|
+
licenses: []
|
86
|
+
metadata: {}
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 2.1.5
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: Create and manage unicorn + nginx configs from capistrano
|
107
|
+
test_files: []
|