brightbox-server-tools 2.0.3 → 2.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|