dark-capistrano-recipes 0.6.4

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.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Webficient LLC, Phil Misiowiec
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,89 @@
1
+ =Capistrano Recipes
2
+
3
+ Useful Capistrano recipes including:
4
+
5
+ * Create MySQL database and user on server (via prompts)
6
+ * Create standalone copy of database.yml in shared path (via prompts)
7
+ * Log rotation and tailing commands
8
+ * Restart and profile Phusion Passenger application server
9
+ * Configure, start/stop/restart Unicorn application server
10
+
11
+ ==Included Tasks
12
+
13
+ * cap db:create_yaml
14
+ * cap db:mysql:setup
15
+ * cap log:rotate
16
+ * cap log:tail
17
+ * cap passenger:bounce
18
+ * cap passenger:memory
19
+ * cap passenger:status
20
+ * cap nginx:setup
21
+ * cap nginx:start
22
+ * cap nginx:stop
23
+ * cap nginx:restart
24
+ * cap nginx:status
25
+ * cap unicorn:start
26
+ * cap unicorn:stop
27
+ * cap unicorn:restart
28
+ * cap unicorn:setup
29
+ * cap symlinks:make
30
+
31
+ ==Installation
32
+
33
+ Easy as pie...
34
+
35
+ Ensure you have the Capistrano gem installed:
36
+
37
+ sudo gem install capistrano
38
+
39
+ Optionally install the Capistrano extensions gem to give you multistage support:
40
+
41
+ sudo gem install capistrano-ext
42
+
43
+ Install this gem:
44
+
45
+ sudo gem install capistrano-recipes --source=http://gemcutter.com
46
+
47
+ To setup the initial Capistrano deploy file, go to your Rails app folder via command line and enter:
48
+
49
+ capify .
50
+
51
+ ==Configuration
52
+
53
+ Inside the newly created config/deploy.rb, add:
54
+
55
+ require 'capistrano_recipes'
56
+ require 'capistrano/ext/multistage' # only require if you've installed Cap ext gem
57
+
58
+ ===RVM
59
+
60
+ RVM is enabled by default. You can disable it by setting :using_rvm to false, or leverage it
61
+ by setting your rvm_ruby_string to appropriate ones (default is ree)
62
+
63
+ If using_rvm is true, the rvm recipe will load rvm's own capistrano extensions so you don't
64
+ have to worry about it during deploy. Just make sure you have everything set up right, like
65
+ .rvmrc on project root and system-wide install on the servers.
66
+
67
+ See (http://rvm.beginrescueend.com/rvm/install) for more info.
68
+
69
+ ===Nginx
70
+
71
+ If you're using nginx as your web server, set :web_server to :nginx and deploy:setup will
72
+ generate the appropriate configuration file for it based on your other variables, such as
73
+ :application_uses_ssl, etc.
74
+
75
+ ===Passenger
76
+
77
+ If you're running Phusion Passenger (http://www.modrails.com) be sure you add this line to config/deploy.rb:
78
+
79
+ set :server, :passenger
80
+
81
+ ===Unicorn
82
+
83
+ If you're running Unicorn (http://unicorn.bogomips.org/) be sure to add this line instead:
84
+
85
+ set :server, :unicorn
86
+
87
+ ==Copyright
88
+
89
+ Copyright (c) 2009 Webficient LLC, Phil Misiowiec. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "dark-capistrano-recipes"
8
+ gem.summary = %Q{Darkside's Capistrano recipes}
9
+ gem.description = 'Extend the Capistrano gem with these useful recipes'
10
+ gem.email = "leonardobighetti@gmail.com"
11
+ gem.homepage = "http://github.com/darkside/capistrano-recipes"
12
+ gem.authors = ["Phil Misiowiec", "Leonardo Bighetti"]
13
+ gem.add_dependency('capistrano', ['>= 2.5.9'])
14
+ gem.add_dependency('capistrano-ext', ['>= 1.2.1'])
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
20
+ end
21
+
22
+ require 'rake/rdoctask'
23
+ Rake::RDocTask.new do |rdoc|
24
+ rdoc.rdoc_dir = 'rdoc'
25
+ rdoc.title = 'capistrano-recipes'
26
+ rdoc.options << '--line-numbers' << '--inline-source'
27
+ rdoc.rdoc_files.include('README*')
28
+ rdoc.rdoc_files.include('lib/**/*.rb')
29
+ end
30
+
data/VERSION.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :patch: 4
3
+ :major: 0
4
+ :build:
5
+ :minor: 6
@@ -0,0 +1,69 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{dark-capistrano-recipes}
8
+ s.version = "0.6.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Phil Misiowiec", "Leonardo Bighetti"]
12
+ s.date = %q{2010-09-20}
13
+ s.description = %q{Extend the Capistrano gem with these useful recipes}
14
+ s.email = %q{leonardobighetti@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION.yml",
25
+ "dark-capistrano-recipes.gemspec",
26
+ "doc/god/god",
27
+ "doc/god/god.conf",
28
+ "doc/god/god.init",
29
+ "generators/app.god.erb",
30
+ "generators/nginx.conf.erb",
31
+ "generators/unicorn.rb.erb",
32
+ "lib/capistrano_recipes.rb",
33
+ "lib/helpers.rb",
34
+ "lib/recipes/application.rb",
35
+ "lib/recipes/bundler.rb",
36
+ "lib/recipes/db.rb",
37
+ "lib/recipes/deploy.rb",
38
+ "lib/recipes/god.rb",
39
+ "lib/recipes/hooks.rb",
40
+ "lib/recipes/log.rb",
41
+ "lib/recipes/nginx.rb",
42
+ "lib/recipes/passenger.rb",
43
+ "lib/recipes/rvm.rb",
44
+ "lib/recipes/symlinks.rb",
45
+ "lib/recipes/unicorn.rb"
46
+ ]
47
+ s.homepage = %q{http://github.com/darkside/capistrano-recipes}
48
+ s.rdoc_options = ["--charset=UTF-8"]
49
+ s.require_paths = ["lib"]
50
+ s.rubygems_version = %q{1.3.7}
51
+ s.summary = %q{Darkside's Capistrano recipes}
52
+
53
+ if s.respond_to? :specification_version then
54
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
55
+ s.specification_version = 3
56
+
57
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
58
+ s.add_runtime_dependency(%q<capistrano>, [">= 2.5.9"])
59
+ s.add_runtime_dependency(%q<capistrano-ext>, [">= 1.2.1"])
60
+ else
61
+ s.add_dependency(%q<capistrano>, [">= 2.5.9"])
62
+ s.add_dependency(%q<capistrano-ext>, [">= 1.2.1"])
63
+ end
64
+ else
65
+ s.add_dependency(%q<capistrano>, [">= 2.5.9"])
66
+ s.add_dependency(%q<capistrano-ext>, [">= 1.2.1"])
67
+ end
68
+ end
69
+
data/doc/god/god ADDED
@@ -0,0 +1 @@
1
+ GOD_CONFIG=/etc/god/god.conf
data/doc/god/god.conf ADDED
@@ -0,0 +1,102 @@
1
+ APPS_ROOT = Dir.glob("/var/www/apps/*/current/config/app.god")
2
+
3
+ # Helper Methods
4
+ def unicorn(w, config, options = {})
5
+ rails_root = options[:rails_root]
6
+ rails_env = options[:rails_env] || 'production'
7
+ unicorn_group = options[:app] || options[:name] || 'default'
8
+ unicorn_name = "#{unicorn_group}-unicorn"
9
+ unicorn_bin = options[:bin_unicorn] || 'bootup_unicorn_rails'
10
+ unicorn_pid = options[:unicorn_pid] || "#{rails_root}/log/unicorn.pid"
11
+ unicorn_config = "#{rails_root}/config/unicorn.rb"
12
+ unicorn_start = options[:start_cmd] || "cd #{rails_root} && #{unicorn_bin} -c #{unicorn_config} -E #{rails_env} -D"
13
+ # QUIT gracefully shuts down workers
14
+ unicorn_stop = options[:stop_cmd] || "kill -QUIT `cat #{unicorn_pid}`"
15
+ # USR2 causes the master to re-create itself and spawn a new worker pool
16
+ unicorn_restart = options[:restart_cmd] || "kill -USR2 `cat #{unicorn_pid}`"
17
+
18
+
19
+ w.name = unicorn_name
20
+ w.group = unicorn_group
21
+ w.start = unicorn_start
22
+ w.stop = unicorn_stop
23
+ w.restart = unicorn_restart
24
+ w.start_grace = 20.seconds
25
+ w.restart_grace = 20.seconds
26
+ w.pid_file = unicorn_pid
27
+ w.behavior(:clean_pid_file)
28
+
29
+ generic_monitor(w, config, rails_root, options)
30
+ end
31
+
32
+ def generic_monitor(w, config, rails_root, options = {})
33
+ w.uid = options[:user] || 'deploy'
34
+ w.gid = options[:group] || 'www-data'
35
+ w.interval = 60.seconds # default
36
+
37
+ # determine the state on startup
38
+ w.transition(:init, { true => :up, false => :start }) do |on|
39
+ on.condition(:process_running) do |c|
40
+ c.running = true
41
+ end
42
+ end
43
+
44
+ # determine when process has finished starting
45
+ w.transition([:start, :restart], :up) do |on|
46
+ on.condition(:process_running) do |c|
47
+ c.running = true
48
+ end
49
+
50
+ # failsafe
51
+ on.condition(:tries) do |c|
52
+ c.times = 5
53
+ c.transition = :start
54
+ end
55
+ end
56
+
57
+ # start if process is not running
58
+ w.transition(:up, :start) do |on|
59
+ on.condition(:process_exits) do |c|
60
+ end
61
+ end
62
+
63
+ # restart if memory or cpu is too high
64
+ w.transition(:up, :restart) do |on|
65
+ on.condition(:memory_usage) do |c|
66
+ c.interval = 20
67
+ c.above = 100.megabytes
68
+ c.times = [3, 5]
69
+ end
70
+
71
+ on.condition(:cpu_usage) do |c|
72
+ c.interval = 10
73
+ c.above = 20.percent
74
+ c.times = [3, 5]
75
+ end
76
+ end
77
+
78
+ # lifecycle
79
+ w.lifecycle do |on|
80
+ on.condition(:flapping) do |c|
81
+ c.to_state = [:start, :restart]
82
+ c.times = 5
83
+ c.within = 5.minute
84
+ c.transition = :unmonitored
85
+ c.retry_in = 10.minutes
86
+ c.retry_times = 5
87
+ c.retry_within = 2.hours
88
+ end
89
+ end
90
+ end
91
+
92
+ God.log_level = :info
93
+ puts "God is loading the apps now..."
94
+ APPS_ROOT.each do |app|
95
+ begin
96
+ puts "Loading app: #{app}"
97
+ God.load app
98
+ puts "Done"
99
+ rescue Exception => e
100
+ puts "Failed! #{e}"
101
+ end
102
+ end
data/doc/god/god.init ADDED
@@ -0,0 +1,62 @@
1
+ #!/bin/sh
2
+
3
+ ### BEGIN INIT INFO
4
+ # Provides: god
5
+ # Required-Start: $all
6
+ # Required-Stop: $all
7
+ # Default-Start: 2 3 4 5
8
+ # Default-Stop: 0 1 6
9
+ # Short-Description: God
10
+ ### END INIT INFO
11
+
12
+ NAME=god
13
+ DESC=god
14
+
15
+ GOD_BIN=/usr/local/bin/bootup_god
16
+ GOD_PID=/var/run/god.pid
17
+ GOD_LOG=/var/log/god.log
18
+ set -e
19
+
20
+ # Make sure the binary and the config file are present before proceeding
21
+ test -x $GOD_BIN || exit 0
22
+
23
+ # Create this file and put in a variable called GOD_CONFIG, pointing to
24
+ # your God configuration file
25
+ test -f /etc/default/god && . /etc/default/god
26
+ [ $GOD_CONFIG ] || exit 0
27
+
28
+ . /lib/lsb/init-functions
29
+
30
+ RETVAL=0
31
+
32
+ case "$1" in
33
+ start)
34
+ echo -n "Starting $DESC: "
35
+ $GOD_BIN -c $GOD_CONFIG -P $GOD_PID -l $GOD_LOG
36
+ RETVAL=$?
37
+ echo "$NAME."
38
+ ;;
39
+ stop)
40
+ echo -n "Stopping $DESC: "
41
+ kill `cat $GOD_PID`
42
+ RETVAL=$?
43
+ echo "$NAME."
44
+ ;;
45
+ restart)
46
+ echo -n "Restarting $DESC: "
47
+ kill `cat $GOD_PID`
48
+ $GOD_BIN -c $GOD_CONFIG -P $GOD_PID -l $GOD_LOG
49
+ RETVAL=$?
50
+ echo "$NAME."
51
+ ;;
52
+ status)
53
+ $GOD_BIN status
54
+ RETVAL=$?
55
+ ;;
56
+ *)
57
+ echo "Usage: god {start|stop|restart|status}"
58
+ exit 1
59
+ ;;
60
+ esac
61
+
62
+ exit $RETVAL
@@ -0,0 +1,25 @@
1
+ app_name = '<%= application %>'
2
+ rails_root = '<%= deploy_to %>/current'
3
+ unicorn_bin = '<%= unicorn_bin %>'
4
+ unicorn_pid = '<%= unicorn_pid %>'
5
+ unicorn_config = '<%= unicorn_remote_config %>'
6
+ unicorn_start_cmd = '<%= unicorn_start_cmd %>'
7
+ unicorn_stop_cmd = '<%= unicorn_stop_cmd %>'
8
+ unicorn_restart_cmd = '<%= unicorn_restart_cmd %>'
9
+
10
+ # Unicorn
11
+ God.watch do |w|
12
+ unicorn(w, rails_root,
13
+ :memory_limit => 100.megabytes,
14
+ :cpu_limit => 50.percent,
15
+ :bin_unicorn => unicorn_bin,
16
+ :name => app_name,
17
+ :rails_root => rails_root,
18
+ :unicorn_conf => unicorn_config,
19
+ :unicorn_pid => unicorn_pid,
20
+ :start_cmd => unicorn_start_cmd,
21
+ :stop_cmd => unicorn_stop_cmd,
22
+ :restart_cmd => unicorn_restart_cmd,
23
+ :user => '<%= unicorn_user %>',
24
+ :group => '<%= unicorn_group %>')
25
+ end
@@ -0,0 +1,150 @@
1
+ upstream <%= application %>_app_server {
2
+ server unix:<%= unicorn_socket %> fail_timeout=0;
3
+ }
4
+ # <%= application %> Server
5
+ server {
6
+ listen <%= application_port %>;
7
+
8
+ client_max_body_size 500M;
9
+ server_name <%= application %>;
10
+
11
+ # ~2 seconds is often enough for most folks to parse HTML/CSS and
12
+ # retrieve needed images/icons/frames, connections are cheap in
13
+ # nginx so increasing this is generally safe...
14
+ keepalive_timeout 5;
15
+
16
+ # path for static files
17
+ root <%= deploy_to %>/current/public;
18
+ access_log <%= deploy_to %>/current/log/nginx.access.log main;
19
+ error_log <%= deploy_to %>/current/log/nginx.error.log info;
20
+
21
+ # this rewrites all the requests to the maintenance.html
22
+ # page if it exists in the doc root. This is for capistrano's
23
+ # disable web task
24
+ if (-f $document_root/system/maintenance.html) {
25
+ rewrite ^(.*)$ /system/maintenance.html last;
26
+ break;
27
+ }
28
+
29
+ location / {
30
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
31
+ #proxy_set_header X-Forwarded-Proto https;
32
+ proxy_set_header Host $http_host;
33
+ #proxy_redirect off;
34
+
35
+ # If the file exists as a static file serve it directly without
36
+ # running all the other rewite tests on it
37
+ if (-f $request_filename) {
38
+ break;
39
+ }
40
+
41
+ # check for index.html for directory index
42
+ # if its there on the filesystem then rewite
43
+ # the url to add /index.html to the end of it
44
+ # and then break to send it to the next config rules.
45
+ if (-f $request_filename/index.html) {
46
+ rewrite (.*) $1/index.html break;
47
+ }
48
+
49
+ # this is the meat of the rails page caching config
50
+ # it adds .html to the end of the url and then checks
51
+ # the filesystem for that file. If it exists, then we
52
+ # rewite the url to have explicit .html on the end
53
+ # and then send it on its way to the next config rule.
54
+ # if there is no file on the fs then it sets all the
55
+ # necessary headers and proxies to our upstream mongrels
56
+ if (-f $request_filename.html) {
57
+ rewrite (.*) $1.html break;
58
+ }
59
+
60
+ if (!-f $request_filename) {
61
+ proxy_pass http://<%= application %>_app_server;
62
+ break;
63
+ }
64
+
65
+ }
66
+
67
+ # Rails error pages
68
+ error_page 500 502 503 504 /500.html;
69
+ location = /500.html {
70
+ root <%= deploy_to %>/current/public;
71
+ }
72
+ }
73
+ <% if application_uses_ssl %>
74
+ upstream <%= application %>_app_ssl {
75
+ server unix:<%= unicorn_socket %> fail_timeout=0;
76
+ }
77
+ # This server is setup for ssl. Uncomment if
78
+ # you are using ssl as well as port 80.
79
+ server {
80
+ listen <%= application_port_ssl%>;
81
+ server_name <%= application %>;
82
+
83
+ ssl on;
84
+ ssl_certificate /etc/ssl/certs/server.crt;
85
+ ssl_certificate_key /etc/ssl/private/server.key;
86
+ ssl_session_timeout 5m;
87
+ client_max_body_size 50M;
88
+
89
+ root <%= deploy_to %>/current/public;
90
+ access_log <%= deploy_to %>/current/log/nginx.access.log main;
91
+ error_log <%= deploy_to %>/current/log/nginx.error.log info;
92
+
93
+ # this rewrites all the requests to the maintenance.html
94
+ # page if it exists in the doc root. This is for capistrano's
95
+ # disable web task
96
+ if (-f $document_root/system/maintenance.html) {
97
+ rewrite ^(.*)$ /system/maintenance.html last;
98
+ break;
99
+ }
100
+
101
+ location / {
102
+ # needed to forward user's IP address to rails
103
+ proxy_set_header X-Real-IP $remote_addr;
104
+
105
+ # needed for HTTPS
106
+ proxy_set_header X_FORWARDED_PROTO https;
107
+
108
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
109
+ proxy_set_header Host $http_host;
110
+ proxy_redirect off;
111
+ proxy_max_temp_file_size 0;
112
+
113
+
114
+ # If the file exists as a static file serve it directly without
115
+ # running all the other rewite tests on it
116
+ if (-f $request_filename) {
117
+ break;
118
+ }
119
+
120
+ # check for index.html for directory index
121
+ # if its there on the filesystem then rewite
122
+ # the url to add /index.html to the end of it
123
+ # and then break to send it to the next config rules.
124
+ if (-f $request_filename/index.html) {
125
+ rewrite (.*) $1/index.html break;
126
+ }
127
+
128
+ # this is the meat of the rails page caching config
129
+ # it adds .html to the end of the url and then checks
130
+ # the filesystem for that file. If it exists, then we
131
+ # rewite the url to have explicit .html on the end
132
+ # and then send it on its way to the next config rule.
133
+ # if there is no file on the fs then it sets all the
134
+ # necessary headers and proxies to our upstream mongrels
135
+ if (-f $request_filename.html) {
136
+ rewrite (.*) $1.html break;
137
+ }
138
+
139
+ if (!-f $request_filename) {
140
+ proxy_pass http://<%= application %>_app_ssl;
141
+ break;
142
+ }
143
+ }
144
+
145
+ error_page 500 502 503 504 /500.html;
146
+ location = /500.html {
147
+ root <%= deploy_to %>/current/public;
148
+ }
149
+ }
150
+ <% end %>