brightbox-server-tools 2.0.3 → 2.1.2
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/bin/railsapp-apache +55 -40
- data/bin/railsapp-logrotate +26 -24
- data/bin/railsapp-maintenance +59 -0
- data/bin/railsapp-mongrel +12 -10
- data/bin/railsapp-monit +60 -31
- data/bin/railsapp-nginx +103 -17
- data/brightbox-gemspec.rb +2 -2
- data/lib/brightbox/maintenance-site.tar.gz +0 -0
- data/lib/brightbox/maintenance.rb +24 -0
- data/lib/brightbox/version.rb +3 -1
- data/lib/brightbox/webserver-common.rb +31 -17
- metadata +7 -3
data/bin/railsapp-apache
CHANGED
@@ -27,21 +27,24 @@ def ssl_certificate_key
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
31
|
-
%Q
|
32
|
-
#{config_time_stamp}
|
33
|
-
<VirtualHost *:80>
|
30
|
+
def standard_server_contents
|
31
|
+
%Q@
|
34
32
|
ServerName #{@domain}
|
35
33
|
ServerAlias #{local_app_alias} #{@aliases}
|
36
34
|
DocumentRoot #{@webroot}
|
37
35
|
|
38
36
|
<Directory "#{@webroot}">
|
37
|
+
Header set Cache-Control "max-age=#{@maxage}"
|
39
38
|
Options FollowSymLinks
|
40
39
|
AllowOverride None
|
41
40
|
Order allow,deny
|
42
41
|
Allow from all
|
43
42
|
</Directory>
|
44
43
|
|
44
|
+
<Directory "#{@webroot}/system">
|
45
|
+
Header set Cache-Control "no-cache"
|
46
|
+
</Directory>
|
47
|
+
|
45
48
|
# Configure mongrel_cluster
|
46
49
|
<Proxy balancer://mongrel_cluster>
|
47
50
|
#{balancer_members}
|
@@ -51,58 +54,68 @@ def http_config
|
|
51
54
|
CustomLog /var/log/web/#{@application}.log combined
|
52
55
|
|
53
56
|
# Rails specific rewrite rules
|
54
|
-
|
57
|
+
RewriteEngine On
|
58
|
+
|
59
|
+
# Check for maintenance file and redirect all requests
|
60
|
+
ErrorDocument 503 /system/maintenance.html
|
61
|
+
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
|
62
|
+
RewriteCond %{SCRIPT_FILENAME} !^/system
|
63
|
+
RewriteRule ^.*$ /system/maintenance.html [R=503,L]
|
64
|
+
|
65
|
+
# Rewrite index to check for static
|
66
|
+
RewriteRule ^/$ /index.html [QSA]
|
67
|
+
|
68
|
+
# Rewrite to check for Rails cached page
|
69
|
+
RewriteRule ^([^.]+)$ $1.html [QSA]
|
70
|
+
|
71
|
+
# Redirect all non-static requests to cluster
|
72
|
+
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f [OR]
|
73
|
+
RewriteCond %{REQUEST_METHOD} !^(GET|HEAD)
|
74
|
+
RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]
|
75
|
+
|
76
|
+
# Deflate
|
77
|
+
AddOutputFilterByType DEFLATE text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript
|
78
|
+
BrowserMatch ^Mozilla/4 gzip-only-text/html
|
79
|
+
BrowserMatch ^Mozilla/4\.0[678] no-gzip
|
80
|
+
BrowserMatch \\bMSIE !no-gzip !gzip-only-text/html
|
55
81
|
|
56
82
|
# Add any access limit directives here
|
57
83
|
<Location />
|
58
84
|
Allow from all
|
59
85
|
</Location>
|
86
|
+
@
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def http_config
|
91
|
+
%Q@
|
92
|
+
#{config_time_stamp}
|
93
|
+
<VirtualHost *:80>
|
94
|
+
#{standard_server_contents}
|
60
95
|
</VirtualHost>
|
61
|
-
|
96
|
+
@
|
62
97
|
end
|
63
98
|
|
64
99
|
def https_config
|
65
|
-
%Q
|
100
|
+
%Q@
|
66
101
|
#{config_time_stamp}
|
67
102
|
<VirtualHost _default_:443>
|
68
103
|
SSLEngine On
|
69
104
|
SSLCertificateFile #{@certificate_file}
|
70
105
|
#{ssl_certificate_key}
|
71
106
|
RequestHeader set X_FORWARDED_PROTO "https"
|
72
|
-
|
73
|
-
ServerAlias #{local_app_alias} #{@aliases}
|
74
|
-
DocumentRoot #{@webroot}
|
75
|
-
|
76
|
-
<Directory "#{@webroot}">
|
77
|
-
Options FollowSymLinks
|
78
|
-
AllowOverride None
|
79
|
-
Order allow,deny
|
80
|
-
Allow from all
|
81
|
-
</Directory>
|
82
|
-
|
83
|
-
# Configure mongrel_cluster
|
84
|
-
<Proxy balancer://mongrel_cluster>
|
85
|
-
#{balancer_members}
|
86
|
-
</Proxy>
|
87
|
-
|
88
|
-
ErrorLog /var/log/web/#{@application}.err
|
89
|
-
CustomLog /var/log/web/#{@application}.log combined
|
90
|
-
|
91
|
-
# Rails specific rewrite rules
|
92
|
-
Include /etc/apache2/brightbox-common
|
93
|
-
|
94
|
-
# Add any access limit directives here
|
95
|
-
<Location />
|
96
|
-
Allow from all
|
97
|
-
</Location>
|
107
|
+
#{standard_server_contents}
|
98
108
|
</VirtualHost>
|
99
|
-
|
109
|
+
@
|
100
110
|
end
|
101
111
|
|
102
112
|
|
103
113
|
def activate_modules(modules)
|
104
|
-
|
105
|
-
|
114
|
+
enmod="/usr/sbin/a2enmod"
|
115
|
+
if File.executable?(enmod)
|
116
|
+
modules.each do |mod|
|
117
|
+
system %Q{#{enmod} "#{mod}"}
|
118
|
+
end
|
106
119
|
end
|
107
120
|
end
|
108
121
|
|
@@ -114,14 +127,16 @@ def configure_ports
|
|
114
127
|
end
|
115
128
|
|
116
129
|
def balancer_members
|
117
|
-
(
|
118
|
-
|
130
|
+
@mongrelhost.split(",").collect do |host|
|
131
|
+
(@port..@port+@mongrels-1).collect do |i|
|
132
|
+
" BalancerMember http://#{host}:#{i} retry=5"
|
133
|
+
end
|
119
134
|
end.join("\n")
|
120
135
|
end
|
121
136
|
|
122
137
|
#MAIN PROGRAM
|
123
|
-
@apache_http_modules = %w(proxy_balancer proxy_http rewrite)
|
124
|
-
@apache_https_modules = %w(ssl
|
138
|
+
@apache_http_modules = %w(proxy_balancer proxy_http rewrite headers deflate)
|
139
|
+
@apache_https_modules = %w(ssl)
|
125
140
|
|
126
141
|
#Create a normal HTTP config
|
127
142
|
@config=http_config
|
data/bin/railsapp-logrotate
CHANGED
@@ -21,56 +21,58 @@
|
|
21
21
|
|
22
22
|
require 'rubygems'
|
23
23
|
require 'optparse'
|
24
|
-
require 'erb'
|
25
24
|
require 'fileutils'
|
25
|
+
require 'brightbox/version'
|
26
26
|
|
27
27
|
@size = '100M'
|
28
28
|
@keep = '10'
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
def has_required_options?
|
31
|
+
[@application, @logdir].all?
|
32
|
+
end
|
33
|
+
|
34
|
+
@opts = OptionParser.new do |opts|
|
35
|
+
opts.banner = "#{opts.program_name} creates a logrotate config for a Rails app\n#{opts.banner}"
|
33
36
|
|
34
37
|
opts.on("-nAPPLICATION_NAME", "--name APPLICATION_NAME",
|
35
|
-
"Name of application (a short useful name
|
38
|
+
"Name of application (a short useful name","for the app such as 'myforum')"
|
36
39
|
) { |value| @application = value }
|
37
40
|
opts.on("-lLOG_DIR", "--logdir LOG_DIR",
|
38
|
-
"Full path to the directory containing the
|
41
|
+
"Full path to the directory containing the","rails logs","(e.g: /home/rails/myforum/current/log)"
|
39
42
|
) { |value| @logdir = value }
|
40
43
|
opts.on("-sMAX_LOG_SIZE", "--size MAX_LOG_SIZE",
|
41
|
-
"When the current log file reaches this
|
44
|
+
"When the current log file reaches this","size, rotate it (e.g: 100M, 1G).","Default: #{@size}"
|
42
45
|
) { |value| @size = value }
|
43
46
|
opts.on("-kPERIOD_TO_KEEP", "--keep PERIOD_TO_KEEP",
|
44
|
-
"Number of previous compressed logs to keep
|
47
|
+
"Number of previous compressed logs to keep","(default: #{@keep})"
|
45
48
|
) { |value| @keep = value }
|
46
49
|
|
47
|
-
|
50
|
+
begin
|
51
|
+
opts.parse!(ARGV)
|
52
|
+
raise OptionParser::ParseError,
|
53
|
+
"You must supply the required arguments" unless has_required_options?
|
54
|
+
rescue OptionParser::ParseError => e
|
55
|
+
warn e.message
|
48
56
|
puts opts
|
49
57
|
exit 1
|
50
|
-
else
|
51
|
-
opts.parse!(ARGV)
|
52
|
-
if @logdir.nil? or @application.nil?
|
53
|
-
puts "required option missing"
|
54
|
-
exit 1
|
55
|
-
end
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
61
|
|
60
|
-
|
61
|
-
|
62
|
-
|
62
|
+
def logrotate_config
|
63
|
+
%Q{
|
64
|
+
# Created by #{@opts.program_name} at #{Time.now}
|
65
|
+
#{@logdir}/*.log {
|
63
66
|
compress
|
64
|
-
size
|
65
|
-
rotate
|
67
|
+
size #{@size}
|
68
|
+
rotate #{@keep}
|
66
69
|
missingok
|
67
70
|
compress
|
68
71
|
copytruncate
|
69
72
|
}
|
70
|
-
|
73
|
+
}
|
74
|
+
end
|
71
75
|
|
72
|
-
template = ERB.new(TEMPLATE)
|
73
|
-
config = template.result
|
74
76
|
filename = "/etc/logrotate.d/rails-#{@application}"
|
75
77
|
|
76
|
-
File.open(filename, "w") { |f| f.write
|
78
|
+
File.open(filename, "w") { |f| f.write logrotate_config }
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Brightbox - Easy Ruby Web Application Deployment
|
3
|
+
# Copyright (C) 2008, Neil Wilson, Brightbox Systems
|
4
|
+
#
|
5
|
+
# This file is part of the Brightbox deployment system
|
6
|
+
#
|
7
|
+
# Brightbox gem is free software: you can redistribute it and/or modify it
|
8
|
+
# under the terms of the GNU Affero General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License,
|
10
|
+
# or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
# Affero General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Affero General
|
18
|
+
# Public License along with this program. If not, see
|
19
|
+
# <http://www.gnu.org/licenses/>.
|
20
|
+
#
|
21
|
+
|
22
|
+
begin
|
23
|
+
require 'rubygems'
|
24
|
+
rescue LoadError
|
25
|
+
# no rubygems to load, so we fail silently
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'optparse'
|
29
|
+
require 'brightbox/version'
|
30
|
+
require 'brightbox/maintenance'
|
31
|
+
|
32
|
+
|
33
|
+
opts = OptionParser.new do |opts|
|
34
|
+
opts.banner = "Create the default maintenance site\n"
|
35
|
+
opts.banner << "Usage: #{opts.program_name} <directory_name>\n\n"
|
36
|
+
|
37
|
+
begin
|
38
|
+
opts.parse!(ARGV)
|
39
|
+
rescue OptionParser::ParseError => e
|
40
|
+
warn e.message
|
41
|
+
puts opts
|
42
|
+
exit 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
abort "Please specify the directory where the maintenance site should live e.g. '#{@progname} .'" if ARGV.empty?
|
48
|
+
abort "Too many arguments; please provide a single directory name." unless ARGV.length == 1
|
49
|
+
abort "'#{ARGV.first}' does not exist." unless File.exists?(ARGV.first)
|
50
|
+
abort "'#{ARGV.first}' is not a directory." unless File.directory?(ARGV.first)
|
51
|
+
|
52
|
+
|
53
|
+
system_dir = ARGV.shift
|
54
|
+
if File.exists?(File.join(system_dir, "index.html"))
|
55
|
+
puts "Existing site detected - leaving alone"
|
56
|
+
else
|
57
|
+
puts "Deploying default maintenance site"
|
58
|
+
deploy_maintenance_page(system_dir)
|
59
|
+
end
|
data/bin/railsapp-mongrel
CHANGED
@@ -22,44 +22,46 @@
|
|
22
22
|
require 'rubygems'
|
23
23
|
require 'optparse'
|
24
24
|
require 'fileutils'
|
25
|
+
require 'brightbox/version'
|
25
26
|
require 'erb'
|
26
27
|
|
27
28
|
@mongrelhost = "127.0.0.1"
|
28
29
|
@mongrels = 2
|
30
|
+
@port = 9200
|
29
31
|
@railsenv = "production"
|
30
32
|
@pidfile = "log/mongrel.pid"
|
31
33
|
|
32
34
|
def has_required_options?
|
33
|
-
[@application, @config, @
|
35
|
+
[@application, @config, @railsroot].all?
|
34
36
|
end
|
35
37
|
|
36
38
|
OptionParser.new do |opts|
|
37
|
-
opts.banner = "
|
38
|
-
opts.banner << "Usage: #{$0} [options] [args]"
|
39
|
+
opts.banner = "#{opts.program_name} creates a Mongrel config for a Rails app\n#{opts.banner}"
|
39
40
|
|
40
41
|
opts.on("-n", "--name APPLICATION_NAME",
|
41
|
-
"Name of application (a short useful name
|
42
|
+
"Name of application (a short useful name",
|
43
|
+
"for the app such as: myforum)"
|
42
44
|
) { |value| @application = value }
|
43
45
|
opts.on("-r", "--railsroot RAILS_ROOT",
|
44
|
-
"Full path to rails root
|
46
|
+
"Full path to rails root","(e.g: /home/rails/myforum/current)"
|
45
47
|
) { |value| @railsroot = value }
|
46
48
|
opts.on("-C", "--config MONGREL_CONFIG_FILE",
|
47
|
-
"Location of this application's mongrel
|
49
|
+
"Location of this application's mongrel","config file"
|
48
50
|
) { |value| @config = value }
|
49
51
|
opts.on("-e", "--railsenv RAILS_ENV",
|
50
52
|
"rails environment (default: #{@railsenv})"
|
51
53
|
) { |value| @railsenv = value }
|
52
54
|
opts.on("-p", "--port MONGREL_PORT",
|
53
|
-
"Port of the first mongrel service
|
55
|
+
"Port of the first mongrel service","(default: #{@port})"
|
54
56
|
) { |value| @port = value.to_i }
|
55
57
|
opts.on("-s", "--servers MONGRELS",
|
56
|
-
"Number of mongrel servers running
|
58
|
+
"Number of mongrel servers running","(default: #{@mongrels})"
|
57
59
|
) { |value| @mongrels = value.to_i }
|
58
60
|
opts.on("-h", "--mongrelhost MONGREL_HOST",
|
59
|
-
"IP/host where mongrel is running
|
61
|
+
"IP/host where mongrel is running","(default: #{@mongrelhost})"
|
60
62
|
) { |value| @mongrelhost = value }
|
61
63
|
opts.on("-P", "--pidfile MONGREL_PID_FILE",
|
62
|
-
"Name of Mongrel PID file template
|
64
|
+
"Name of Mongrel PID file template","(default: #{@pidfile})"
|
63
65
|
) { |value| @pidfile = value }
|
64
66
|
|
65
67
|
begin
|
data/bin/railsapp-monit
CHANGED
@@ -22,7 +22,8 @@
|
|
22
22
|
require 'rubygems'
|
23
23
|
require 'optparse'
|
24
24
|
require 'fileutils'
|
25
|
-
require '
|
25
|
+
require 'brightbox/version'
|
26
|
+
require 'uri'
|
26
27
|
|
27
28
|
@mongrelhost = "127.0.0.1"
|
28
29
|
@mongrels = 2
|
@@ -30,45 +31,59 @@ require 'erb'
|
|
30
31
|
@railsuser = "rails"
|
31
32
|
@railsgroup = "rails"
|
32
33
|
@pidfile = "log/mongrel.pid"
|
34
|
+
@port = 9200
|
35
|
+
@check_url = "http://localhost"
|
36
|
+
@max_memory = 110
|
37
|
+
@max_cpu = 80
|
33
38
|
|
34
39
|
def has_required_options?
|
35
|
-
[@
|
40
|
+
[@application, @config, @port, @railsroot].all?
|
36
41
|
end
|
37
42
|
|
38
|
-
OptionParser.new do |opts|
|
39
|
-
opts.banner = "
|
40
|
-
opts.banner << "Usage: #{$0} [options] [args]"
|
43
|
+
@opts = OptionParser.new do |opts|
|
44
|
+
opts.banner = "#{opts.program_name} creates a Monit config for a Rails app\n#{opts.banner}"
|
41
45
|
|
42
46
|
opts.on("-n", "--name APPLICATION_NAME",
|
43
|
-
"Name of application (a short useful name
|
47
|
+
"Name of application (a short useful name",
|
48
|
+
"for the app such as: myforum)"
|
44
49
|
) { |value| @application = value }
|
45
50
|
opts.on("-r", "--railsroot RAILS_ROOT",
|
46
|
-
"Full path to rails root
|
51
|
+
"Full path to rails root",
|
52
|
+
"(e.g: /home/rails/myforum/current)"
|
47
53
|
) { |value| @railsroot = value }
|
48
54
|
opts.on("-C", "--config MONGREL_CONFIG_FILE",
|
49
|
-
"Location of this application's mongrel
|
55
|
+
"Location of this application's mongrel","config file"
|
50
56
|
) { |value| @config = value }
|
51
57
|
opts.on("-e", "--railsenv RAILS_ENV",
|
52
58
|
"rails environment (default: #{@railsenv})"
|
53
59
|
) { |value| @railsenv = value }
|
54
60
|
opts.on("-p", "--port MONGREL_PORT",
|
55
|
-
"Port of the first mongrel service
|
61
|
+
"Port of the first mongrel service","(default: #{@port})"
|
56
62
|
) { |value| @port = value.to_i }
|
57
63
|
opts.on("-s", "--servers MONGRELS",
|
58
|
-
"Number of mongrel servers running
|
64
|
+
"Number of mongrel servers running","(default: #{@mongrels})"
|
59
65
|
) { |value| @mongrels = value.to_i }
|
60
66
|
opts.on("-h", "--mongrelhost MONGREL_HOST",
|
61
|
-
"IP/host where mongrel is running
|
67
|
+
"IP/host where mongrel is running","(default: #{@mongrelhost})"
|
62
68
|
) { |value| @mongrelhost = value }
|
63
69
|
opts.on("-u", "--user USERNAME",
|
64
|
-
"The unix username the mongrel process
|
70
|
+
"The unix username the mongrel process","should be started as (default: #{@railsuser})"
|
65
71
|
) { |value| @railsuser = value }
|
66
72
|
opts.on("-g", "--group USERNAME",
|
67
|
-
"The unix group the mongrel process should
|
73
|
+
"The unix group the mongrel process should","be started as (default: #{@railsgroup})"
|
68
74
|
) { |value| @railsgroup = value }
|
69
75
|
opts.on("-P", "--pidfile MONGREL_PID_FILE",
|
70
|
-
"Name of Mongrel PID file template
|
76
|
+
"Name of Mongrel PID file template","(default: #{@pidfile})"
|
71
77
|
) { |value| @pidfile = value }
|
78
|
+
opts.on("-U", "--checkurl URL_TO_CHECK",
|
79
|
+
"URL to check to make sure application is","live (default: #{@check_url})"
|
80
|
+
) { |value| @check_url = value }
|
81
|
+
opts.on("-m", "--maxmemory MAX_MONGREL_MEM",
|
82
|
+
"Amount of memory mongrel can use before","being killed (default: #{@max_memory}Mb)"
|
83
|
+
) { |value| @max_memory = value }
|
84
|
+
opts.on("-c", "--maxcpu MAX_MONGREL_CPU",
|
85
|
+
"Amount of cpu mongrel can use before","being killed (default: #{@max_cpu}%)"
|
86
|
+
) { |value| @max_cpu = value }
|
72
87
|
|
73
88
|
begin
|
74
89
|
opts.parse(ARGV)
|
@@ -96,38 +111,52 @@ def mongrel_ports
|
|
96
111
|
@port..(@port + @mongrels - 1)
|
97
112
|
end
|
98
113
|
|
114
|
+
def updated_url(current_url, new_port)
|
115
|
+
url_holder = URI.parse(current_url)
|
116
|
+
url_holder.port = new_port
|
117
|
+
url_holder.to_s
|
118
|
+
end
|
119
|
+
|
99
120
|
process_pid_file
|
100
121
|
@mongrel_instances = mongrel_ports.collect do |port|
|
101
122
|
[port, File.join(@railsroot, port_pid_file(port))]
|
102
123
|
end
|
103
124
|
|
104
|
-
|
105
|
-
# Created by
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
125
|
+
def config_time_stamp
|
126
|
+
"# Created by #{@opts.program_name} at #{Time.now}\n"
|
127
|
+
end
|
128
|
+
|
129
|
+
def mongrel_config(port, pidfile)
|
130
|
+
%Q{
|
131
|
+
check process mongrel_#{@application}_#{port} with pidfile #{pidfile}
|
132
|
+
group #{@application}
|
133
|
+
start program = "/usr/bin/mongrel_rails cluster::start -C #{@config} --clean --only #{port}"
|
110
134
|
as uid #{@railsuser} and gid #{@railsgroup}
|
111
|
-
stop program = "/usr/bin/mongrel_rails cluster::stop -C
|
135
|
+
stop program = "/usr/bin/mongrel_rails cluster::stop -C #{@config} --clean --only #{port}"
|
112
136
|
as uid #{@railsuser} and gid #{@railsgroup}
|
113
137
|
|
114
|
-
if failed
|
115
|
-
with timeout
|
138
|
+
if failed url #{updated_url(@check_url, port)}
|
139
|
+
with timeout 15 seconds
|
140
|
+
for 2 cycles
|
116
141
|
then restart
|
117
142
|
|
118
|
-
if mem >
|
119
|
-
if cpu >
|
120
|
-
#if loadavg(5min) greater than 10 for 8 cycles then restart
|
143
|
+
if mem > #{@max_memory} Mb for 3 cycles then restart
|
144
|
+
if cpu > #{@max_cpu}% for 5 cycles then restart
|
121
145
|
if 20 restarts within 20 cycles then timeout
|
122
|
-
|
123
|
-
|
146
|
+
}
|
147
|
+
end
|
148
|
+
|
149
|
+
def monit_config
|
150
|
+
config_time_stamp +
|
151
|
+
@mongrel_instances.collect do |port, pidfile|
|
152
|
+
mongrel_config(port,pidfile)
|
153
|
+
end.join("\n")
|
154
|
+
end
|
124
155
|
|
125
|
-
template = ERB.new(TEMPLATE)
|
126
|
-
config = template.result
|
127
156
|
filename = "/etc/monit/conf.d/rails-#{@application}.monitrc"
|
128
157
|
if File.exists?(filename)
|
129
158
|
FileUtils.mkdir_p("/etc/monit/archived-configs")
|
130
159
|
FileUtils.cp filename, "/etc/monit/archived-configs/rails-#{@application}.monitrc.#{Time.now.strftime('%y%m%d%H%M%S')}"
|
131
160
|
end
|
132
161
|
|
133
|
-
File.open(filename, "w") { |f| f.write
|
162
|
+
File.open(filename, "w") { |f| f.write monit_config }
|
data/bin/railsapp-nginx
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# Brightbox - Easy Ruby Web Application Deployment
|
3
3
|
# Copyright (C) 2008, Neil Wilson, Brightbox Systems
|
4
4
|
#
|
5
|
-
# This file is part of the Brightbox
|
5
|
+
# This file is part of the Brightbox deployment system
|
6
6
|
#
|
7
7
|
# Brightbox gem is free software: you can redistribute it and/or modify it
|
8
8
|
# under the terms of the GNU Affero General Public License as published
|
@@ -23,36 +23,79 @@
|
|
23
23
|
WEBSERVER='nginx'
|
24
24
|
require 'brightbox/webserver-common'
|
25
25
|
|
26
|
-
|
27
|
-
def http_config
|
26
|
+
def standard_server_contents
|
28
27
|
<<-EOT
|
29
|
-
#{config_time_stamp}
|
30
|
-
upstream #{@application}_mongrels {
|
31
|
-
fair;
|
32
|
-
# List of mongrels
|
33
|
-
#{balancer_members}
|
34
|
-
}
|
35
|
-
server {
|
36
28
|
server_name #{@domain} #{local_app_alias} #{@aliases};
|
37
29
|
root #{@webroot};
|
30
|
+
|
31
|
+
log_not_found off;
|
32
|
+
log_format main '$remote_addr $host $remote_user [$time_local] '
|
33
|
+
'"$request" $status $body_bytes_sent "$http_referer" '
|
34
|
+
'"$http_user_agent" "$http_x_forwarded_for"' ;
|
38
35
|
access_log /var/log/web/#{@application}.log main;
|
36
|
+
|
37
|
+
client_body_temp_path /var/spool/nginx-client-body 1 2;
|
38
|
+
client_max_body_size 32m;
|
39
|
+
client_body_buffer_size 32k;
|
40
|
+
|
41
|
+
tcp_nopush on;
|
42
|
+
|
43
|
+
gzip_http_version 1.0;
|
44
|
+
gzip_comp_level 2;
|
45
|
+
gzip_proxied any;
|
46
|
+
gzip_min_length 1100;
|
47
|
+
gzip_buffers 16 8k;
|
48
|
+
gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
|
49
|
+
# Some version of IE 6 don't handle compression well on some mime-types, so just disable for them
|
50
|
+
gzip_disable "MSIE [1-6].(?!.*SV1)";
|
51
|
+
# Set a vary header so downstream proxies don't send cached gzipped content to IE6
|
52
|
+
gzip_vary on;
|
53
|
+
|
54
|
+
# Send along useful info to the mongrels
|
55
|
+
proxy_set_header X-Real-IP $remote_addr;
|
56
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
57
|
+
proxy_set_header Host $host;
|
58
|
+
proxy_set_header X_FORWARDED_PROTO $scheme;
|
59
|
+
proxy_redirect false;
|
60
|
+
proxy_max_temp_file_size 0;
|
61
|
+
proxy_buffering on;
|
62
|
+
proxy_buffer_size 4k;
|
63
|
+
proxy_buffers 16 32k;
|
64
|
+
|
65
|
+
fastcgi_buffer_size 4k;
|
66
|
+
fastcgi_buffers 16 32k;
|
39
67
|
|
40
|
-
|
41
|
-
|
42
|
-
rewrite ^(.*)$ /system/maintenance.html last;
|
43
|
-
break;
|
68
|
+
location /system {
|
69
|
+
add_header Cache-Control no-cache;
|
44
70
|
}
|
45
71
|
|
46
72
|
location / {
|
47
73
|
## General Rails error page stuff
|
48
74
|
error_page 404 /404.html;
|
49
75
|
error_page 422 /422.html;
|
50
|
-
error_page 500
|
76
|
+
error_page 500 /500.html;
|
77
|
+
error_page 502 /502.html;
|
78
|
+
error_page 504 /504.html;
|
51
79
|
error_page 403 /403.html;
|
52
80
|
|
81
|
+
error_page 503 /system/maintenance.html;
|
82
|
+
|
83
|
+
# Capistrano maintenance message support
|
84
|
+
if (-f $document_root/system/maintenance.html) {
|
85
|
+
return 503;
|
86
|
+
break;
|
87
|
+
}
|
88
|
+
|
89
|
+
# Send to mongrels if not a read request
|
90
|
+
if ($request_method !~ "GET|HEAD") {
|
91
|
+
proxy_pass http://#{@application}_mongrels;
|
92
|
+
break;
|
93
|
+
}
|
94
|
+
|
53
95
|
# If the file exists then stop here. Saves 4 more stats and some
|
54
96
|
# rewrites.
|
55
97
|
if (-f $request_filename) {
|
98
|
+
expires #{@maxage};
|
56
99
|
break;
|
57
100
|
}
|
58
101
|
# Rails page caching
|
@@ -66,15 +109,51 @@ server {
|
|
66
109
|
# then send to the mongrels
|
67
110
|
if (!-f $request_filename) {
|
68
111
|
proxy_pass http://#{@application}_mongrels;
|
112
|
+
break;
|
69
113
|
}
|
70
114
|
}
|
115
|
+
EOT
|
116
|
+
end
|
117
|
+
|
118
|
+
def ssl_certificate_key
|
119
|
+
if @key_file
|
120
|
+
" ssl_certificate_key #{key_file};"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def http_config
|
125
|
+
<<-EOT
|
126
|
+
#{config_time_stamp}
|
127
|
+
upstream #{@application}_mongrels {
|
128
|
+
fair;
|
129
|
+
# List of mongrels
|
130
|
+
#{balancer_members}
|
131
|
+
}
|
132
|
+
server {
|
133
|
+
listen 80;
|
134
|
+
#{standard_server_contents}
|
135
|
+
}
|
136
|
+
EOT
|
137
|
+
end
|
138
|
+
|
139
|
+
def https_config
|
140
|
+
<<-EOT
|
141
|
+
#{config_time_stamp}
|
142
|
+
server {
|
143
|
+
listen 443;
|
144
|
+
ssl on;
|
145
|
+
ssl_certificate #{@certificate_file};
|
146
|
+
#{ssl_certificate_key}
|
147
|
+
#{standard_server_contents}
|
71
148
|
}
|
72
149
|
EOT
|
73
150
|
end
|
74
151
|
|
75
152
|
def balancer_members
|
76
|
-
(
|
77
|
-
|
153
|
+
@mongrelhost.split(",").collect do |host|
|
154
|
+
(@port..@port+@mongrels-1).collect do |i|
|
155
|
+
" server #{host}:#{i};"
|
156
|
+
end
|
78
157
|
end.join("\n")
|
79
158
|
end
|
80
159
|
|
@@ -83,3 +162,10 @@ end
|
|
83
162
|
#Create a normal HTTP config
|
84
163
|
@config=http_config
|
85
164
|
configure_site(@application)
|
165
|
+
|
166
|
+
#Create an SSL site if requested
|
167
|
+
if @certificate
|
168
|
+
@config=https_config
|
169
|
+
configure_site("default-ssl")
|
170
|
+
end
|
171
|
+
|
data/brightbox-gemspec.rb
CHANGED
@@ -30,7 +30,7 @@ end
|
|
30
30
|
@server = Gem::Specification.new do |s|
|
31
31
|
add_common(s)
|
32
32
|
s.name = "brightbox-server-tools"
|
33
|
-
s.files = FileList["LICENSE", "Rakefile", "*.rb", "bin/railsapp-*","{
|
33
|
+
s.files = FileList["LICENSE", "Rakefile", "*.rb", "bin/railsapp-*","lib/**/*.{rb,gz}"].exclude(/recipe/).to_a
|
34
34
|
s.summary = "Brightbox Server configuration scripts"
|
35
35
|
s.executables = FileList["bin/railsapp-*"].sub(/bin\//,'')
|
36
36
|
end
|
@@ -39,7 +39,7 @@ end
|
|
39
39
|
add_common(s)
|
40
40
|
s.name = "brightbox"
|
41
41
|
s.files = FileList["LICENSE", "Rakefile", "*.rb", "lib/**/*.rb","bin/brightbox"].exclude("lib/brightbox/webserver-common.rb").to_a
|
42
|
-
s.add_dependency("capistrano", ">= 2.
|
42
|
+
s.add_dependency("capistrano", ">= 2.5")
|
43
43
|
s.summary = "Brightbox rails deployment scripts for Capistrano"
|
44
44
|
s.executable = 'brightbox'
|
45
45
|
end
|
Binary file
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Brightbox - Easy Ruby Web Application Deployment
|
2
|
+
# Copyright (C) 2008, Neil Wilson, Brightbox Systems
|
3
|
+
#
|
4
|
+
# This file is part of the Brightbox deployment system
|
5
|
+
#
|
6
|
+
# Brightbox gem is free software: you can redistribute it and/or modify it
|
7
|
+
# under the terms of the GNU Affero General Public License as published
|
8
|
+
# by the Free Software Foundation, either version 3 of the License,
|
9
|
+
# or (at your option) any later version.
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
+
# Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Affero General
|
17
|
+
# Public License along with this program. If not, see
|
18
|
+
# <http://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
def deploy_maintenance_page(system_directory)
|
22
|
+
maintenance_site = File.join(File.dirname(__FILE__),"maintenance-site.tar.gz")
|
23
|
+
system ("tar --directory #{system_directory} --extract --gzip --file #{maintenance_site}")
|
24
|
+
end
|
data/lib/brightbox/version.rb
CHANGED
@@ -21,16 +21,18 @@
|
|
21
21
|
require 'rubygems'
|
22
22
|
require 'optparse'
|
23
23
|
require 'fileutils'
|
24
|
+
require 'brightbox/version'
|
24
25
|
|
25
26
|
@mongrelhost = "127.0.0.1"
|
26
27
|
@mongrels = 2
|
28
|
+
@port = 9200
|
27
29
|
@aliases = nil
|
28
30
|
@certificate = nil
|
29
31
|
@key_file = nil
|
30
|
-
@
|
32
|
+
@maxage = 315360000
|
31
33
|
|
32
34
|
def has_required_options?
|
33
|
-
[@application, @webroot, @domain
|
35
|
+
[@application, @webroot, @domain].all? &&
|
34
36
|
(@certificate || @certificate_key.nil?)
|
35
37
|
end
|
36
38
|
|
@@ -40,11 +42,11 @@ def certificate_file
|
|
40
42
|
test_path = File.join('','etc','ssl','certs', cert_base + '.*')
|
41
43
|
candidates = Dir[test_path]
|
42
44
|
if candidates.empty?
|
43
|
-
abort "#{@
|
45
|
+
abort "#{@opts.program_name}: Unable to find certificate file for #{@cert_base}"
|
44
46
|
end
|
45
47
|
result = candidates.pop
|
46
48
|
unless candidates.empty?
|
47
|
-
abort "#{@
|
49
|
+
abort "#{@opts.program_name}: #{@cert_base} resolves to more than one file. Please be more specific"
|
48
50
|
end
|
49
51
|
result
|
50
52
|
end
|
@@ -61,50 +63,62 @@ def key_file
|
|
61
63
|
return nil if candidates.empty?
|
62
64
|
result = candidates.pop
|
63
65
|
unless candidates.empty?
|
64
|
-
abort "#{@
|
66
|
+
abort "#{@opts.program_name}: #{key_base} resolves to more than one file. Please be more specific"
|
65
67
|
end
|
66
68
|
result
|
67
69
|
end
|
68
70
|
|
69
|
-
OptionParser.new do |opts|
|
70
|
-
opts.banner = "#{
|
71
|
-
opts.banner << "Usage: #{@app_name} [options] [args]"
|
71
|
+
@opts = OptionParser.new do |opts|
|
72
|
+
opts.banner = "#{opts.program_name} creates an #{WEBSERVER} config for a Rails app\n#{opts.banner}"
|
72
73
|
|
73
74
|
opts.on("-n APPLICATION_NAME", "--name APPLICATION_NAME",
|
74
|
-
"Name of application (a short useful
|
75
|
+
"Name of application (a short useful",
|
76
|
+
"name for the app such as 'myforum')"
|
75
77
|
) { |value| @application = value }
|
76
78
|
|
77
79
|
opts.on("-w", "--webroot WEB_ROOT",
|
78
|
-
"Full path to web root
|
80
|
+
"Full path to web root",
|
81
|
+
"(e.g: /home/rails/myforum/current/public)"
|
79
82
|
) { |value| @webroot = value }
|
80
83
|
|
81
84
|
opts.on("-d", "--domain DOMAIN_NAME",
|
82
|
-
"Domain name for application
|
85
|
+
"Domain name for application",
|
86
|
+
"(e.g: www.example.com)"
|
83
87
|
) { |value| @domain = value }
|
84
88
|
|
85
89
|
opts.on("-a", "--aliases ALIASES",
|
86
|
-
"Aliases for domain name, comma separated
|
90
|
+
"Aliases for domain name, comma separated",
|
91
|
+
"(e.g: www.example.org,www.example.net)"
|
87
92
|
) { |value| @aliases = value.to_s.split(',').join(' ')}
|
88
93
|
|
89
94
|
opts.on("-p", "--port MONGREL_PORT", Integer,
|
90
|
-
"Port of the first mongrel service"
|
95
|
+
"Port of the first mongrel service",
|
96
|
+
"(default: #{@port})"
|
91
97
|
) { |value| @port = value.to_i }
|
92
98
|
|
93
99
|
opts.on("-s", "--servers MONGRELS", Integer,
|
94
|
-
"Number of mongrel servers running
|
100
|
+
"Number of mongrel servers running",
|
101
|
+
"(default: #{@mongrels})"
|
95
102
|
) { |value| @mongrels = value.to_i }
|
96
103
|
|
97
104
|
opts.on("-h", "--mongrelhost MONGREL_HOST",
|
98
|
-
"ip/host where mongrel is running
|
105
|
+
"ip/host where mongrel is running",
|
106
|
+
"(default: #{@mongrelhost})"
|
99
107
|
) { |value| @mongrelhost = value }
|
100
108
|
|
101
109
|
opts.on("-c", "--ssl-cert CERTIFICATE_NAME",
|
102
|
-
"create an SSL configuration
|
110
|
+
"create an SSL configuration",
|
111
|
+
"using CERTIFICATE_NAME"
|
103
112
|
) { |value| @certificate = value }
|
104
113
|
|
105
114
|
opts.on("-k", "--ssl-key KEY_NAME",
|
106
115
|
"Name of private key to use CERTIFICATE"
|
107
116
|
) { |value| @certificate_key = value }
|
117
|
+
|
118
|
+
opts.on("-m", "--max-age MAX_AGE",
|
119
|
+
"Number of seconds to keep static assets","in cache",
|
120
|
+
"(default: #{@maxage})"
|
121
|
+
) { |value| @maxage = value }
|
108
122
|
|
109
123
|
begin
|
110
124
|
opts.parse(ARGV)
|
@@ -145,7 +159,7 @@ def configure_site(site_name)
|
|
145
159
|
end
|
146
160
|
|
147
161
|
def config_time_stamp
|
148
|
-
"# Created by #{@
|
162
|
+
"# Created by #{@opts.program_name} at #{Time.now}"
|
149
163
|
end
|
150
164
|
|
151
165
|
def local_app_alias
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brightbox-server-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Leach
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2008-
|
13
|
+
date: 2008-10-08 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -18,6 +18,7 @@ description:
|
|
18
18
|
email: support@brightbox.co.uk
|
19
19
|
executables:
|
20
20
|
- railsapp-nginx
|
21
|
+
- railsapp-maintenance
|
21
22
|
- railsapp-apache
|
22
23
|
- railsapp-logrotate
|
23
24
|
- railsapp-monit
|
@@ -31,12 +32,15 @@ files:
|
|
31
32
|
- Rakefile
|
32
33
|
- brightbox-gemspec.rb
|
33
34
|
- bin/railsapp-nginx
|
35
|
+
- bin/railsapp-maintenance
|
34
36
|
- bin/railsapp-apache
|
35
37
|
- bin/railsapp-logrotate
|
36
38
|
- bin/railsapp-monit
|
37
39
|
- bin/railsapp-mongrel
|
38
40
|
- lib/brightbox/version.rb
|
39
41
|
- lib/brightbox/webserver-common.rb
|
42
|
+
- lib/brightbox/maintenance.rb
|
43
|
+
- lib/brightbox/maintenance-site.tar.gz
|
40
44
|
has_rdoc: false
|
41
45
|
homepage: http://wiki.brightbox.co.uk/docs:thebrightboxgem
|
42
46
|
post_install_message:
|
@@ -59,7 +63,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
63
|
requirements: []
|
60
64
|
|
61
65
|
rubyforge_project: brightbox
|
62
|
-
rubygems_version: 1.
|
66
|
+
rubygems_version: 1.2.0
|
63
67
|
signing_key:
|
64
68
|
specification_version: 2
|
65
69
|
summary: Brightbox Server configuration scripts
|