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.
@@ -27,21 +27,24 @@ def ssl_certificate_key
27
27
  end
28
28
  end
29
29
 
30
- def http_config
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
- Include /etc/apache2/brightbox-common
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
- ServerName #{@domain}
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
- modules.each do |mod|
105
- system %Q{/usr/sbin/a2enmod "#{mod}"}
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
- (@port..@port+@mongrels-1).collect do |i|
118
- " BalancerMember http://#{@mongrelhost}:#{i} retry=5"
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 headers)
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
@@ -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
- OptionParser.new do |opts|
31
- opts.banner = "brightbox-logrotate creates a logrotate config for a Rails app\n"
32
- opts.banner << "Usage: #{$0} [options] [args]"
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 for the app such as 'myforum')"
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 rails logs (e.g: /home/rails/myforum/current/log)"
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 size, rotate it (e.g: 100M, 1G). Default: #{@size}"
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 (default: #{@keep})"
47
+ "Number of previous compressed logs to keep","(default: #{@keep})"
45
48
  ) { |value| @keep = value }
46
49
 
47
- if ARGV.empty?
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
- TEMPLATE = <<EOT
61
- # Created by brightbox-logrotate at <%= Time.now %>
62
- <%= @logdir %>/*.log {
62
+ def logrotate_config
63
+ %Q{
64
+ # Created by #{@opts.program_name} at #{Time.now}
65
+ #{@logdir}/*.log {
63
66
  compress
64
- size <%= @size %>
65
- rotate <%= @keep %>
67
+ size #{@size}
68
+ rotate #{@keep}
66
69
  missingok
67
70
  compress
68
71
  copytruncate
69
72
  }
70
- EOT
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 config }
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
@@ -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, @pidfile, @port, @mongrels, @railsenv, @railsroot, @mongrelhost].all?
35
+ [@application, @config, @railsroot].all?
34
36
  end
35
37
 
36
38
  OptionParser.new do |opts|
37
- opts.banner = "brightbox-mongrel creates a Mongrel config for a Rails app\n"
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 for the app such as: myforum)"
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 (e.g: /home/rails/myforum/current)"
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 config file"
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 (e.g: 9200)"
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 (default: #{@mongrels})"
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 (default: #{@mongrelhost})"
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 (default: #{@pidfile})"
64
+ "Name of Mongrel PID file template","(default: #{@pidfile})"
63
65
  ) { |value| @pidfile = value }
64
66
 
65
67
  begin
@@ -22,7 +22,8 @@
22
22
  require 'rubygems'
23
23
  require 'optparse'
24
24
  require 'fileutils'
25
- require 'erb'
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
- [@railsuser, @railsgroup, @application, @config, @pidfile, @port, @mongrels, @railsenv, @railsroot, @mongrelhost].all?
40
+ [@application, @config, @port, @railsroot].all?
36
41
  end
37
42
 
38
- OptionParser.new do |opts|
39
- opts.banner = "brightbox-monit creates a Monit config for a Rails app\n"
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 for the app such as: myforum)"
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 (e.g: /home/rails/myforum/current)"
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 config file"
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 (e.g: 9200)"
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 (default: #{@mongrels})"
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 (default: #{@mongrelhost})"
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 should be started as (default: #{@railsuser})"
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 be started as (default: #{@railsgroup})"
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 (default: #{@pidfile})"
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
- TEMPLATE = <<EOT
105
- # Created by brightbox-monit at <%= Time.now %>
106
- <% @mongrel_instances.each do |port, pidfile| %>
107
- check process mongrel_<%= @application %>_<%= port %> with pidfile <%= pidfile %>
108
- group <%= @application %>
109
- start program = "/usr/bin/mongrel_rails cluster::start -C <%= @config %> --clean --only <%= port %>"
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 <%= @config %> --clean --only <%= port %>"
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 host <%= @mongrelhost %> port <%= port %> protocol http
115
- with timeout 30 seconds
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 > 110 Mb for 3 cycles then restart
119
- if cpu > 80% for 5 cycles then restart
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
- <% end %>
123
- EOT
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 config }
162
+ File.open(filename, "w") { |f| f.write monit_config }
@@ -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 @application system
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
- # Capistrano maintenance message support
41
- if (-f $document_root/system/maintenance.html) {
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 502 503 504 /500.html;
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
- (@port..@port+@mongrels-1).collect do |i|
77
- " server #{@mongrelhost}:#{i};"
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
+
@@ -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-*","{lib,spec}/**/*.rb"].exclude(/recipe/).to_a
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.3")
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
@@ -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
@@ -1,3 +1,5 @@
1
1
  module Brightbox
2
- VERSION = "2.0.3"
2
+ VERSION = "2.1.2"
3
3
  end
4
+ # Set global scope version so that OptionParser picks it up.
5
+ ::Version = Brightbox::VERSION
@@ -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
- @app_name = File.basename $0
32
+ @maxage = 315360000
31
33
 
32
34
  def has_required_options?
33
- [@application, @webroot, @domain, @port].all? &&
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 "#{@app_name}: Unable to find certificate file for #{@cert_base}"
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 "#{@app_name}: #{@cert_base} resolves to more than one file. Please be more specific"
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 "#{@app_name}: #{key_base} resolves to more than one file. Please be more specific"
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 = "#{@app_name} creates an #{WEBSERVER} config for a Rails app\n"
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 name for the app such as 'myforum')"
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 (e.g: /home/rails/myforum/current/public)"
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 (e.g: www.example.com)"
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 (e.g: www.example.org,www.example.net)"
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 (default: #{@mongrels})"
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 (default: #{@mongrelhost})"
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 using CERTIFICATE_NAME"
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 #{@app_name} at #{Time.now}"
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.0.3
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-06-16 00:00:00 +01:00
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.1.1
66
+ rubygems_version: 1.2.0
63
67
  signing_key:
64
68
  specification_version: 2
65
69
  summary: Brightbox Server configuration scripts