rubyworks-ec2 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/COPYING ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2007 nutrun.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,11 @@
1
+ = rubyworks-ec2
2
+
3
+ Version: 0.1.4
4
+
5
+ rubyworks-ec2 is a collection of Capistrano 2.0 recipes and utilities for automating the deployment of Rails applications on Amazon EC2 using the RubyWorks Production Stack.
6
+
7
+ Invoke "cap -T" for a list of the available Capistrano tasks.
8
+
9
+ Detailed docs coming soon.
10
+
11
+ In the meantime, visit http://nutrun.com/weblog/rubyworks-production-stack-on-amazon-ec2
@@ -0,0 +1,42 @@
1
+ %w(rubygems rake/gempackagetask rake/rdoctask rake/contrib/sshpublisher).each {|l|require l}
2
+
3
+ task :default => :gem
4
+
5
+ Rake::RDocTask.new('rdoc') do |t|
6
+ t.rdoc_files.include('README', 'COPYING', 'lib/**/*.rb')
7
+ t.main = 'README'
8
+ t.title = "rubyworks-ec2"
9
+ # t.options = ['--inline-source']
10
+ end
11
+
12
+ desc "Upload homepage to RubyForge"
13
+ task :upload_homepage do
14
+ Rake::SshDirPublisher.new("gmalamid@rubyforge.org", "/var/www/gforge-projects/synthesis", "etc/index.html").upload
15
+ end
16
+
17
+ gem_spec = Gem::Specification.new do |s|
18
+ s.name = 'rubyworks-ec2'
19
+ s.rubyforge_project = 'rubyworks-ec2'
20
+ s.version = '0.1.4'
21
+ s.platform = Gem::Platform::RUBY
22
+ s.summary, s.description = 'RubyWorks support'
23
+ s.author = 'George Malamidis, Markus Bengts'
24
+ s.email = 'george@nutrun.com'
25
+ s.homepage = 'http://rubyworks-ec2.rubyforge.org'
26
+ s.has_rdoc = true
27
+ s.rdoc_options += ['--quiet', '--title', 'rubyworks-ec2', '--main', 'README']
28
+ s.extra_rdoc_files = ['README', 'COPYING']
29
+ excluded = FileList['etc/*']
30
+ s.files = FileList['**/*.rb', 'COPYING', 'README', 'Rakefile', 'config/**/*'] - excluded
31
+ s.executables << "capify-for-ec2"
32
+ s.add_dependency('capistrano', '~> 2.0')
33
+ s.add_dependency('aws-s3')
34
+ end
35
+
36
+ Rake::GemPackageTask.new(gem_spec) do |t|
37
+ t.need_zip = false
38
+ t.need_tar = false
39
+ end
40
+
41
+ desc "Remove gem and rdoc artifacts"
42
+ task :clean => [:clobber_package, :clobber_rdoc]
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This could be much nicer with help and other options.
4
+ # Now we just pass all arguments to capify and assume
5
+ # that the first argument is the path to a rails project.
6
+
7
+ system("capify #{ARGV * ' '}")
8
+
9
+ path = ARGV[0]
10
+ capfile = File.join(path, "Capfile")
11
+ deploy_rb = File.join(path, "config/deploy.rb")
12
+ config_server = File.join(path, "config/server")
13
+
14
+ unless File.exist?(capfile)
15
+ raise "Cannot continue without a Capfile"
16
+ end
17
+
18
+ # Add a require statement to the end of Capfile
19
+ if system("grep -q rubyworks-ec2 #{capfile}")
20
+ puts "[skip] #{capfile} already requires rubyworks-ec2"
21
+ else
22
+ puts "[add] require statement to #{capfile}"
23
+ system <<-CMD
24
+ echo '' >> Capfile
25
+ echo 'require "rubyworks-ec2"' >> Capfile
26
+ CMD
27
+ end
28
+
29
+ # Modify config/deploy.rb
30
+ if system("grep -q instance_id #{deploy_rb}") and system("grep -q ezcrypto #{deploy_rb}")
31
+ puts "[skip] #{deploy_rb} already contains necessary configuration"
32
+ else
33
+ puts "[add] configuration template to #{deploy_rb}"
34
+ File.open(deploy_rb, "r+") do |file|
35
+ lines = file.readlines
36
+ file.pos = 0 # write to the beginning of deploy.rb
37
+ file.puts 'set :instance_id, ""'
38
+ file.puts 'set :instance_url, ""'
39
+ file.puts ''
40
+ lines.each do |line|
41
+ file.puts line.sub(/"your .+-server here"/, 'instance_url')
42
+ end
43
+ file.puts ''
44
+ file.puts <<-EOF
45
+ # Replace the examples with your AWS credentials
46
+ set :keypair, "your-keypair"
47
+ set :account_id, "123456789098"
48
+ set :access_key_id, "ABCDE123456789"
49
+ set :secret_access_key, "323848492AHSBCYEBDNCSCUENCCKS"
50
+ set :pk, "pk-323848492AHSBCYEBDNCSCUENCCKS.pem"
51
+ set :cert, "cert-323848492AHSBCYEBDNCSCUENCCKS.pem"
52
+
53
+ # Packages and gems to install on the server
54
+ set :packages, %w(apache2 subversion mysql-server libmysql-ruby less)
55
+ set :gems, %w(aws-s3 ezcrypto)
56
+ EOF
57
+ end
58
+ end
59
+
60
+ # Copy templates for server configuration to config/server
61
+ # FIX: does not work unless path == '.'
62
+ system "cd #{path} && cap configuration:initialize_from_templates"
63
+
64
+ puts "[done] Now you can edit #{deploy_rb} and the files in #{config_server}"
@@ -0,0 +1,50 @@
1
+ NameVirtualHost *
2
+ <VirtualHost *>
3
+ #ServerName site.com
4
+ #ServerAlias www.site.com
5
+
6
+ DocumentRoot /usr/rails/public
7
+
8
+ <Directory "/usr/rails/public">
9
+ Options FollowSymLinks
10
+ AllowOverride All
11
+ Order Allow,Deny
12
+ Allow from All
13
+ </Directory>
14
+
15
+ RewriteEngine On
16
+
17
+ #site down for maintenance
18
+ RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
19
+ RewriteCond %{SCRIPT_FILENAME} !maintenance.html
20
+ RewriteRule ^.*$ /system/maintenance.html [L]
21
+
22
+ #static index
23
+ RewriteRule ^/$ %{DOCUMENT_ROOT}/index.html [QSA]
24
+
25
+ #cached pages
26
+ RewriteRule ^([^.]+)$ $1.html [QSA]
27
+
28
+ #dynamic content
29
+ RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
30
+ RewriteRule .* http://127.0.0.1:3001%{REQUEST_URI} [L,P,QSA]
31
+
32
+ ProxyRequests Off
33
+
34
+ <Proxy *>
35
+ Order deny,allow
36
+ Allow from all
37
+ </Proxy>
38
+
39
+ ProxyPass / http://127.0.0.1:3001/
40
+ ProxyPassReverse / http://127.0.0.1:3001
41
+ ProxyPreserveHost on
42
+
43
+ ProxyPass /images !
44
+ ProxyPass /stylesheets !
45
+ ProxyPass /javascripts !
46
+
47
+ Alias /images %{DOCUMENT_ROOT}/images
48
+ Alias /stylesheets %{DOCUMENT_ROOT}/stylesheets
49
+ Alias /javascripts %{DOCUMENT_ROOT}/javascripts
50
+ </VirtualHost>
@@ -0,0 +1,16 @@
1
+ # /etc/crontab: system-wide crontab
2
+ # Unlike any other crontab you don't have to run the `crontab'
3
+ # command to install the new version when you edit this file
4
+ # and files in /etc/cron.d. These files also have username fields,
5
+ # that none of the other crontabs do.
6
+
7
+ SHELL=/bin/sh
8
+ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
9
+
10
+ # m h dom mon dow user command
11
+ 17 * * * * root cd / && run-parts --report /etc/cron.hourly
12
+ 25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
13
+ 47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
14
+ 52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
15
+ */30 * * * * root (source $HOME/.amazon_keys && /usr/lib/site_ruby/rubyworks/backup_db )
16
+ #
@@ -0,0 +1,44 @@
1
+ # Configuration for Monit, a monitoring tool
2
+ # whose role in RubyWorks stack is to ensure that other components
3
+ # are up and running at all times.
4
+ #
5
+ # Original documentation for Monit is here:
6
+ # http://www.tildeslash.com/monit/doc/manual.php
7
+
8
+ set daemon 15 # Perform a check every 15 seconds
9
+ set logfile /var/log/monit.log
10
+
11
+ # set mailserver mail.bar.com
12
+ # set alert admin@bar.com
13
+ # mail-format {
14
+ # from: rubyworks@rubyforge.org
15
+ # subject: $SERVICE $EVENT at $DATE
16
+ # message: Monit $ACTION $SERVICE at $DATE on $HOST,
17
+ #
18
+ # Yours sincerely,
19
+ # RubyWorks.
20
+ # }
21
+
22
+ # This section configures Monit's web frontend on port http://localhost:2812.
23
+ set httpd port 2812 and
24
+ # only accept connection from localhost. Change to 0.0.0.0 to accept
25
+ # remote connections. Make sure to change the password in the 'allow'
26
+ # statement if you do.
27
+ use address 127.0.0.1
28
+ # When someone connects to the web frontend, perform basic HTTP i
29
+ # authentication and accept username/password admin/MonitPa$$w0rd
30
+ allow admin:MonitPa$$w0rd
31
+
32
+ include /etc/rails/monit.conf
33
+
34
+ check process mysql with pidfile "/var/run/mysqld/mysqld.pid"
35
+ group database
36
+ start program = "/etc/init.d/mysql start"
37
+ stop program = "/etc/init.d/mysql stop"
38
+ if failed host 127.0.0.1 port 3306 protocol mysql then restart
39
+ if totalmem is greater than 600.0 MB for 2 cycles then alert
40
+ if 5 restarts within 5 cycles then timeout
41
+
42
+ check file slow_queries with path "/var/log/mysql/mysql-slow.log"
43
+ group database
44
+ if changed timestamp then alert
@@ -0,0 +1,162 @@
1
+ #
2
+ # The MySQL database server configuration file.
3
+ #
4
+ # You can copy this to one of:
5
+ # - "/etc/mysql/my.cnf" to set global options,
6
+ # - "~/.my.cnf" to set user-specific options.
7
+ #
8
+ # One can use all long options that the program supports.
9
+ # Run program with --help to get a list of available options and with
10
+ # --print-defaults to see which it would actually understand and use.
11
+ #
12
+ # For explanations see
13
+ # http://dev.mysql.com/doc/mysql/en/server-system-variables.html
14
+
15
+ # This will be passed to all mysql clients
16
+ # It has been reported that passwords should be enclosed with ticks/quotes
17
+ # escpecially if they contain "#" chars...
18
+ # Remember to edit /etc/mysql/debian.cnf when changing the socket location.
19
+ [client]
20
+ port = 3306
21
+ socket = /var/run/mysqld/mysqld.sock
22
+ default_character_set = utf8
23
+
24
+ # Here is entries for some specific programs
25
+ # The following values assume you have at least 32M ram
26
+
27
+ # This was formally known as [safe_mysqld]. Both versions are currently parsed.
28
+ [mysqld_safe]
29
+ socket = /var/run/mysqld/mysqld.sock
30
+ nice = 0
31
+
32
+ [mysqld]
33
+ #
34
+ # * Basic Settings
35
+ #
36
+ user = mysql
37
+ pid-file = /var/run/mysqld/mysqld.pid
38
+ socket = /var/run/mysqld/mysqld.sock
39
+ port = 3306
40
+ basedir = /usr
41
+ datadir = /var/lib/mysql
42
+ tmpdir = /tmp
43
+ language = /usr/share/mysql/english
44
+ skip-external-locking
45
+ default_storage_engine = InnoDB
46
+ character_set_server = utf8
47
+ collation_server = utf8_unicode_ci
48
+ #
49
+ # Instead of skip-networking the default is now to listen only on
50
+ # localhost which is more compatible and is not less secure.
51
+ bind-address = 127.0.0.1
52
+ #
53
+ # * Fine Tuning (Most of these options apply to MyISAM only. See InnoDB below.)
54
+ #
55
+ key_buffer = 32M
56
+ max_allowed_packet = 16M
57
+ thread_stack = 192K
58
+ thread_cache = 8
59
+ # Each mongrel process uses exactly one connection all the time. (?)
60
+ # Is there any benefit of a smaller number for max_connections?
61
+ max_connections = 50
62
+ table_cache = 64
63
+ #thread_concurrency = 10
64
+ # each connection requires read_buffer + sort_buffer + less than 1M of RAM
65
+ read_buffer = 1M
66
+ sort_buffer = 2M
67
+ #
68
+ # * Query Cache Configuration
69
+ #
70
+ # Frequently updated tables should use InnoDB. MyISAM tables are mainly read-only,
71
+ # so if we have enough query_cache, it should be fast.
72
+ query_cache_limit = 4M
73
+ query_cache_size = 128M
74
+ #
75
+ # * Logging and Replication
76
+ #
77
+ # Both location gets rotated by the cronjob.
78
+ # Be aware that this log type is a performance killer.
79
+ #log = /var/log/mysql/mysql.log
80
+ #
81
+ # Error logging goes to syslog. This is a Debian improvement :)
82
+ #
83
+ # Here you can see queries with especially long duration
84
+ # (rubyworks-ec2 sets up monit to notify about changes to mysql-slow.log)
85
+ log_slow_queries = /var/log/mysql/mysql-slow.log
86
+ long_query_time = 2
87
+ #log-queries-not-using-indexes
88
+ #
89
+ # The following can be used as easy to replay backup logs or for replication.
90
+ #server-id = 1
91
+ log_bin = /var/log/mysql/mysql-bin.log
92
+ # WARNING: Using expire_logs_days without bin_log crashes the server! See README.Debian!
93
+ expire_logs_days = 10
94
+ max_binlog_size = 100M
95
+ #binlog_do_db = include_database_name
96
+ #binlog_ignore_db = include_database_name
97
+ #
98
+ # * BerkeleyDB
99
+ #
100
+ # Using BerkeleyDB is now discouraged as its support will cease in 5.1.12.
101
+ skip-bdb
102
+ #
103
+ # * InnoDB
104
+ #
105
+ # Read the manual for more InnoDB related options. There are many!
106
+ # http://dev.mysql.com/doc/refman/5.0/en/innodb-parameters.html
107
+
108
+ # ibdata1 could be 20G (or even more) to avoid autoextending during runtime
109
+ # (wonder how well it is compressed if you bundle it to a new image)
110
+ innodb_data_file_path = ibdata1:100M;ibdata2:50M:autoextend
111
+
112
+ # if you have a dedicated instance you should increase the buffer pool size
113
+ innodb_buffer_pool_size = 384M
114
+ innodb_additional_mem_pool = 64M
115
+
116
+ # log file size should be less than 50% of the buffer pool size
117
+ # (changing log file size: http://dev.mysql.com/doc/refman/5.0/en/adding-and-removing.html)
118
+ innodb_log_file_size = 128M
119
+ innodb_log_buffer_size = 8M
120
+
121
+ #
122
+ # * Security Features
123
+ #
124
+ # Read the manual, too, if you want chroot!
125
+ # chroot = /var/lib/mysql/
126
+ #
127
+ # For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
128
+ #
129
+ # ssl-ca=/etc/mysql/cacert.pem
130
+ # ssl-cert=/etc/mysql/server-cert.pem
131
+ # ssl-key=/etc/mysql/server-key.pem
132
+
133
+
134
+
135
+ [mysqldump]
136
+ quick
137
+ quote-names
138
+ max_allowed_packet = 16M
139
+
140
+ [mysql]
141
+ #no-auto-rehash # faster start of mysql but no tab completition
142
+
143
+ [isamchk]
144
+ key_buffer = 16M
145
+
146
+ #
147
+ # * NDB Cluster
148
+ #
149
+ # See /usr/share/doc/mysql-server-*/README.Debian for more information.
150
+ #
151
+ # The following configuration is read by the NDB Data Nodes (ndbd processes)
152
+ # not from the NDB Management Nodes (ndb_mgmd processes).
153
+ #
154
+ # [MYSQL_CLUSTER]
155
+ # ndb-connectstring=127.0.0.1
156
+
157
+
158
+ #
159
+ # * IMPORTANT: Additional settings that can override those from this file!
160
+ #
161
+ !includedir /etc/mysql/conf.d/
162
+
@@ -0,0 +1,77 @@
1
+ # Configuration file for HAProxy, general-purpose proxy used
2
+ # in RubyWorks stack to distribute load between multiple Mongrel processes
3
+ #
4
+ # Original documentation for this file is here:
5
+ # http://haproxy.1wt.eu/download/1.2/doc/haproxy-en.txt
6
+
7
+ global
8
+ # maximum number of simultaneous active connections from an upstream web server
9
+ maxconn 500
10
+
11
+ # Logging to syslog facility local0. HAProxy can only log to a TCP socket, therefore
12
+ # syslogd must be started with -r option. See RubyWorks documentation for detailed
13
+ # instructions.
14
+ log 127.0.0.1 local0
15
+
16
+ # Run under unprivileged rails account
17
+ user rails
18
+ group rails
19
+
20
+ # Uncomment the statement below to turn on verbose logging
21
+ #debug
22
+
23
+ # Settings in the defaults section apply to all services (unless you change it,
24
+ # this configuration defines one service, called rails).
25
+ defaults
26
+
27
+ # apply log settings from the global section above to services
28
+ log global
29
+
30
+ # Proxy incoming traffic as HTTP requests
31
+ mode http
32
+
33
+ # Distribute incoming requests between Mongrels by round robin algorythm.
34
+ # Note that because of 'maxconn 1' settings in the listen section, Mongrels
35
+ # that are busy processing some other request will actually be skipped.
36
+ # So, the actual load-balancing behavior is smarter than simple round robin.
37
+ balance roundrobin
38
+
39
+ # Maximum number of simultaneous active connections from an upstream web server
40
+ # per service
41
+ maxconn 500
42
+
43
+ # Log details about HTTP requests
44
+ option httplog
45
+
46
+ # Abort request if client closes its output channel while waiting for the
47
+ # request. HAProxy documentation has a long explanation for this option.
48
+ option abortonclose
49
+
50
+ # If sending a request to one Mongrel fails, try to send it to another, 3 times
51
+ # before aborting the request
52
+ retries 3
53
+
54
+ # Do not enforce session affinity (i.e., an HTTP session can be served by
55
+ # any Mongrel, not just the one that started the session
56
+ redispatch
57
+
58
+ # Timeout a request if the client did not read any data for 15 seconds
59
+ clitimeout 15000
60
+
61
+ # Timeout a request if Mongrel does not accept a connection for 30 seconds
62
+ contimeout 30000
63
+
64
+ # Timeout a request if Mongrel does not accept the data on the connection,
65
+ # or does not send a response back in 30 seconds
66
+ srvtimeout 30000
67
+
68
+ # Rails service section.
69
+ # Traffic incoming to HAProxy on port 3001 will be distributed to Mongrels on
70
+ # ports 3002-3005, sending no more than one request at a time to each Mongrel
71
+ # HAProxy can handle multiple services (when copying this section,
72
+ # make sure to change names and port numbers)
73
+ listen rails :3001
74
+ server rails-1 localhost:3002 maxconn 1 check
75
+ server rails-2 localhost:3003 maxconn 1 check
76
+ server rails-3 localhost:3004 maxconn 1 check
77
+ server rails-4 localhost:3005 maxconn 1 check
@@ -0,0 +1,61 @@
1
+ # This is the default monit configuration that comes with RubyWorks
2
+ # See also /etc/monit/monitrc
3
+
4
+ check process haproxy
5
+ with pidfile "/var/service/haproxy/supervise/pid"
6
+ start program = "/usr/bin/sv up haproxy"
7
+ stop program = "/usr/bin/sv down haproxy"
8
+ if totalmem is greater than 100.0 MB for 4 cycles then restart
9
+ if failed port 3001 for 3 times within 5 cycles then restart
10
+ if cpu is greater than 50% for 2 cycles then alert
11
+ if cpu is greater than 80% for 3 cycles then restart
12
+ if loadavg(5min) greater than 10 for 8 cycles then restart
13
+ if 20 restarts within 20 cycles then timeout
14
+
15
+ check process mongrel_3002
16
+ with pidfile "/var/service/mongrel_3002/supervise/pid"
17
+ group mongrels
18
+ start program = "/usr/bin/sv up mongrel_3002"
19
+ stop program = "/usr/bin/sv down mongrel_3002"
20
+ if totalmem is greater than 110.0 MB for 4 cycles then restart
21
+ if failed port 3002 for 3 times within 5 cycles then restart
22
+ if cpu is greater than 50% for 2 cycles then alert
23
+ if cpu is greater than 80% for 3 cycles then restart
24
+ if loadavg(5min) greater than 10 for 8 cycles then restart
25
+ if 20 restarts within 20 cycles then timeout
26
+
27
+ check process mongrel_3003
28
+ with pidfile "/var/service/mongrel_3003/supervise/pid"
29
+ group mongrels
30
+ start program = "/usr/bin/sv up mongrel_3003"
31
+ stop program = "/usr/bin/sv down mongrel_3003"
32
+ if totalmem is greater than 110.0 MB for 4 cycles then restart
33
+ if failed port 3003 for 3 times within 5 cycles then restart
34
+ if cpu is greater than 50% for 2 cycles then alert
35
+ if cpu is greater than 80% for 3 cycles then restart
36
+ if loadavg(5min) greater than 10 for 8 cycles then restart
37
+ if 20 restarts within 20 cycles then timeout
38
+
39
+ check process mongrel_3004
40
+ with pidfile "/var/service/mongrel_3004/supervise/pid"
41
+ group mongrels
42
+ start program = "/usr/bin/sv up mongrel_3004"
43
+ stop program = "/usr/bin/sv down mongrel_3004"
44
+ if totalmem is greater than 110.0 MB for 4 cycles then restart
45
+ if failed port 3004 for 3 times within 5 cycles then restart
46
+ if cpu is greater than 50% for 2 cycles then alert
47
+ if cpu is greater than 80% for 3 cycles then restart
48
+ if loadavg(5min) greater than 10 for 8 cycles then restart
49
+ if 20 restarts within 20 cycles then timeout
50
+
51
+ check process mongrel_3005
52
+ with pidfile "/var/service/mongrel_3005/supervise/pid"
53
+ group mongrels
54
+ start program = "/usr/bin/sv up mongrel_3005"
55
+ stop program = "/usr/bin/sv down mongrel_3005"
56
+ if totalmem is greater than 110.0 MB for 4 cycles then restart
57
+ if failed port 3005 for 3 times within 5 cycles then restart
58
+ if cpu is greater than 50% for 2 cycles then alert
59
+ if cpu is greater than 80% for 3 cycles then restart
60
+ if loadavg(5min) greater than 10 for 8 cycles then restart
61
+ if 20 restarts within 20 cycles then timeout
@@ -0,0 +1,39 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ namespace :configuration do
3
+ desc "Copy initial templates for server configuration"
4
+ task :initialize_from_templates do
5
+ if File.exist?("config/server")
6
+ puts "[skip] files that exist in config/server/ are not overwritten"
7
+ else
8
+ puts "[add] adding all configuration files to config/server/"
9
+ system "mkdir config/server"
10
+ end
11
+ system "cp -R -n #{File.dirname(__FILE__)}/../../config/server/ config/server/"
12
+ end
13
+
14
+ desc "svn export or upload recursively all files from config/server"
15
+ task :upload do
16
+ if File.exist?('config/server/.svn')
17
+ # export to temp_dir to avoid uploading .svn directories
18
+ temp_dir = "/tmp/rw-ec2-#{Time.now.strftime("%Y%m%d%H%M%S")}"
19
+ system "svn export config/server #{temp_dir}"
20
+ system "scp -r -p -i #{keypair_full_path} #{temp_dir}/* #{username}@#{instance_url}:/"
21
+ system "rm -rf #{temp_dir}"
22
+ else
23
+ system "scp -r -p -i #{keypair_full_path} config/server/* #{username}@#{instance_url}:/"
24
+ end
25
+ run "chmod 600 /etc/{monit/monitrc,rails/monit.conf}"
26
+ monit::restart
27
+ end
28
+
29
+ desc "Download some configuration files from the server and overwrite local versions"
30
+ task :download do
31
+ %w(mysql monit rails).each do |dir|
32
+ system "mkdir config/server/etc/#{dir}"
33
+ end
34
+ %w(mysql/my.cnf monit/monitrc rails/monit.conf rails/haproxy.conf rails/mongrel_3002.config).each do |file|
35
+ system "scp -i #{keypair_full_path} #{username}@#{instance_url}:/etc/#{file} config/server/etc/#{file}"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,41 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ namespace :db do
3
+ %w(start stop restart).each do |cmd|
4
+ desc "#{cmd.capitalize} mysql-server on the instance"
5
+ task cmd.to_sym do
6
+ run "/etc/init.d/mysql #{cmd}"
7
+ end
8
+ end
9
+
10
+ desc "Back up the instance's database to S3"
11
+ task :backup do
12
+ run "source $HOME/.amazon_keys && /usr/lib/site_ruby/rubyworks/backup_db"
13
+ end
14
+
15
+ desc <<-DESC
16
+ Restore the instance's database to the latest copy from S3,
17
+ or specify the version by setting the VERSION parameter to
18
+ the desired timestamp, e.g 'cap db:restore VERSION=<timestamp>'
19
+ DESC
20
+ task :restore do
21
+ version = ENV['VERSION']
22
+ run "source $HOME/.amazon_keys && /usr/lib/site_ruby/rubyworks/restore_db #{version}"
23
+ end
24
+
25
+ desc "Display a list of database backups from S3"
26
+ task(:list_backups) { S3.list_db_backups access_key_id, secret_access_key, account_id }
27
+
28
+ desc <<-DESC
29
+ Remove Debian's default InnoDB files, start MySQL (creates new InnoDB files)
30
+ and restore to the latest database back up from S3
31
+ DESC
32
+ task :setup do
33
+ stop
34
+ run <<-CMD
35
+ rm -rf /var/lib/mysql/ib*
36
+ CMD
37
+ start
38
+ restore
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,14 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ namespace :deploy do
3
+ task :restart do
4
+ run <<-CMD
5
+ chown -R rails:rails #{deploy_to} &&
6
+ rm -rf /usr/rails &&
7
+ ln -s #{deploy_to}/current /usr/rails &&
8
+ chown -R rails:rails /usr/rails
9
+ CMD
10
+ mongrel::restart
11
+ haproxy::restart
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ namespace :haproxy do
3
+ %w(start stop restart).each do |cmd|
4
+ desc "#{cmd.capitalize} HAProxy"
5
+ task cmd.to_sym do
6
+ run "monit #{cmd} haproxy"
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,43 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ namespace :image do
3
+ desc "Back up and register an image of the running instance to S3"
4
+ task :backup do
5
+ cp_keypair
6
+ clean_up
7
+ bundle
8
+ upload
9
+ register
10
+ end
11
+
12
+ task :clean_up do
13
+ run <<-CMD
14
+ echo '' > $HOME/.bash_history &&
15
+ echo '' > $HOME/.mysql_history &&
16
+ echo '' > $HOME/.ssh/authorized_keys &&
17
+ rm $HOME/.amazon_keys
18
+ CMD
19
+ end
20
+
21
+ task :cp_keypair do
22
+ system "scp -i #{keypair_full_path} #{ec2_dir}/#{pk} #{ec2_dir}/#{cert} #{username}@#{instance_url}:/mnt"
23
+ end
24
+
25
+ task :bundle do
26
+ run <<-CMD
27
+ export RUBYLIB=/usr/lib/site_ruby/ &&
28
+ ec2-bundle-vol -d /mnt -k /mnt/#{pk} -c /mnt/#{cert} -u #{account_id} -s 1536 -p #{timestamp}
29
+ CMD
30
+ end
31
+
32
+ task :upload do
33
+ run <<-CMD
34
+ export RUBYLIB=/usr/lib/site_ruby/ &&
35
+ ec2-upload-bundle -b #{bucket} -m /mnt/#{timestamp}.manifest.xml -a #{access_key_id} -s #{secret_access_key}
36
+ CMD
37
+ end
38
+
39
+ task :register do
40
+ exec "ec2-register #{bucket}/#{timestamp}.manifest.xml"
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,112 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ namespace :instance do
3
+ task :start do
4
+ system "ec2-run-instances #{image_id} -k #{keypair}"
5
+ end
6
+
7
+ task :stop do
8
+ system "ec2-terminate-instances #{instance_id}"
9
+ end
10
+
11
+ desc <<-DESC
12
+ Install RubyWorks Production Stack, install AWS::S3 libraries,
13
+ install database back up and restore on S3 utilities, install Apache 2,
14
+ install, Subversion, install MySQL, create database backup on S3 cron job,
15
+ restore database from S3, set up Rails deployment environment in #{deploy_to},
16
+ deploy application
17
+ DESC
18
+ task :bootstrap do
19
+ use_mnt
20
+ install_rubyworks
21
+ install_packages
22
+ install_gems
23
+ cp_amazon_keys
24
+ cp_db_utils
25
+ configuration::upload
26
+ setup_vhost
27
+ setup_hosts
28
+ db::setup
29
+ deploy::setup
30
+ create_database
31
+ end
32
+
33
+ desc "Move /var to the bigger /mnt partition and link it back to /var"
34
+ task :use_mnt do
35
+ run <<-CMD
36
+ mv /var /mnt/ &&
37
+ ln -s /mnt/var /
38
+ CMD
39
+ end
40
+
41
+ task :install_rubyworks do
42
+ run <<-CMD
43
+ wget http://rubyworks.rubyforge.org/RubyWorks.GPG.key &&
44
+ apt-key add RubyWorks.GPG.key &&
45
+ echo 'deb http://rubyworks.rubyforge.org/debian/DEBS/i386 /' >> /etc/apt/sources.list &&
46
+ apt-get update &&
47
+ apt-get install rubyworks -y
48
+ CMD
49
+ end
50
+
51
+ task :install_packages do
52
+ packages.each do |package|
53
+ run "apt-get install #{package} -y"
54
+ end
55
+ end
56
+
57
+ task :install_gems do
58
+ gems.each do |gem|
59
+ run "gem i #{gem} -y --source http://gems.rubyforge.org/ --no-ri --no-rdoc"
60
+ end
61
+ end
62
+
63
+ task :cp_amazon_keys do
64
+ run <<-CMD
65
+ echo 'export ACCESS_KEY_ID=\"#{access_key_id}\"' > $HOME/.amazon_keys &&
66
+ echo 'export SECRET_ACCESS_KEY=\"#{secret_access_key}\"' >> $HOME/.amazon_keys &&
67
+ echo 'export ACCOUNT_ID=\"#{account_id}\"' >> $HOME/.amazon_keys
68
+ CMD
69
+ end
70
+
71
+ task :cp_db_utils do
72
+ dbbackup = File.open(File.dirname(__FILE__) + '/../util/database_backup.rb', 'r').path
73
+ backup_script = File.open(File.dirname(__FILE__) + '/../util/backup_db.rb', 'r').path
74
+ restore_script = File.open(File.dirname(__FILE__) + '/../util/restore_db.rb', 'r').path
75
+ run "mkdir #{rwdir}"
76
+ system "scp -i #{keypair_full_path} #{dbbackup} #{username}@#{instance_url}:/#{rwdir}/database_backup.rb"
77
+ system "scp -i #{keypair_full_path} #{backup_script} #{username}@#{instance_url}:/#{rwdir}/backup_db"
78
+ system "scp -i #{keypair_full_path} #{restore_script} #{username}@#{instance_url}:/#{rwdir}/restore_db"
79
+ run <<-CMD
80
+ chmod 755 #{rwdir}/backup_db &&
81
+ chmod 755 #{rwdir}/restore_db
82
+ CMD
83
+ end
84
+
85
+ task :setup_vhost do
86
+ run <<-CMD
87
+ a2enmod proxy_http &&
88
+ a2enmod proxy &&
89
+ a2enmod rewrite &&
90
+ /etc/init.d/apache2 reload
91
+ CMD
92
+ end
93
+
94
+ task :setup_hosts do
95
+ run "echo '127.0.0.1 localhost' > /etc/hosts"
96
+ end
97
+
98
+ task :create_database do
99
+ run "echo 'create database if not exists #{application}_production;' | mysql"
100
+ end
101
+
102
+ desc "Remotely login to the running instance"
103
+ task :ssh do
104
+ system "ssh -i #{keypair_full_path} #{username}@#{instance_url}"
105
+ end
106
+
107
+ desc "Copy public key from instance to $HOME/.ec2"
108
+ task :cp_public_key do
109
+ system "scp -i #{keypair_full_path} #{username}@#{instance_url}:/mnt/openssh_id.pub #{ec2_dir}/id_rsa-#{keypair}.pub"
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,10 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ namespace :mongrel do
3
+ %w(start stop restart).each do |cmd|
4
+ desc "#{cmd.capitalize} mongrels"
5
+ task cmd.to_sym do
6
+ run "monit -g mongrels #{cmd} all"
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,24 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ namespace :monit do
3
+ desc "Start monit"
4
+ task :start do
5
+ run "/usr/bin/sv up monit"
6
+ end
7
+
8
+ desc "Stop monit"
9
+ task :stop do
10
+ run "/usr/bin/sv down monit"
11
+ end
12
+
13
+ desc "Restart monit"
14
+ task :restart do
15
+ stop
16
+ start
17
+ end
18
+
19
+ desc "Display status of monitored services"
20
+ task :status do
21
+ run "monit status"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ set :timestamp, Time.now.utc.strftime("%b%d%Y")
3
+ set :ec2_dir, ENV['HOME'] + '/.ec2'
4
+ set :keypair_full_path, "#{ec2_dir}/id_rsa-#{keypair}" if respond_to?(:keypair)
5
+ set :rwdir, '/usr/lib/site_ruby/rubyworks'
6
+ set :deploy_to, "/usr/#{application}" #unless respond_to?(:deploy_to)
7
+ set :image_id, "ami-30f11459"
8
+ set :username, "root"
9
+
10
+ ssh_options[:username] = username
11
+ ssh_options[:keys] = keypair_full_path if respond_to?(:keypair)
12
+ end
@@ -0,0 +1,4 @@
1
+ require "yaml"
2
+ require "aws/s3"
3
+ require File.dirname(__FILE__) + "/s3"
4
+ Dir[File.dirname(__FILE__) + "/recipes/*"].each { |r| require r }
@@ -0,0 +1,7 @@
1
+ module S3
2
+ def list_db_backups akid, sak, account_id
3
+ AWS::S3::Base.establish_connection!(:access_key_id => akid, :secret_access_key => sak)
4
+ AWS::S3::Bucket.find("#{account_id}-rwec2-mysql-backups").objects.each { |o| STDOUT.puts o.key }
5
+ end
6
+ module_function :list_db_backups
7
+ end
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + "/database_backup"
3
+ DatabaseBackup.backup!
@@ -0,0 +1,53 @@
1
+ require "rubygems"
2
+ require "aws/s3"
3
+ require "fileutils"
4
+ require "ezcrypto"
5
+
6
+ class DatabaseBackup
7
+ class << self
8
+ TMP_BACKUP_FILE = "/tmp/mysql-backup-#{Time.now.to_i}"
9
+ BACKUP_BUCKET = "#{ENV['ACCOUNT_ID']}-rwec2-mysql-backups"
10
+
11
+ AWS::S3::Base.establish_connection!(
12
+ :access_key_id => ENV['ACCESS_KEY_ID'],
13
+ :secret_access_key => ENV['SECRET_ACCESS_KEY']
14
+ )
15
+
16
+ def backup!
17
+ unencrypted_contents = `mysqldump --all-databases`
18
+ key = EzCrypto::Key.with_password ENV['SECRET_ACCESS_KEY'], 'saltoftheearth'
19
+ encrypted_contents = key.encrypt unencrypted_contents
20
+ File.open(TMP_BACKUP_FILE, 'w') { |f| f << encrypted_contents}
21
+ begin
22
+ AWS::S3::Bucket.find BACKUP_BUCKET
23
+ rescue AWS::S3::NoSuchBucket
24
+ AWS::S3::Bucket.create BACKUP_BUCKET
25
+ end
26
+ AWS::S3::S3Object.store(TMP_BACKUP_FILE, open(TMP_BACKUP_FILE), BACKUP_BUCKET)
27
+ ensure
28
+ FileUtils.rm_f TMP_BACKUP_FILE if File.exists? TMP_BACKUP_FILE
29
+ end
30
+
31
+ def restore!(version)
32
+ begin
33
+ all_objects = AWS::S3::Bucket.objects(BACKUP_BUCKET)
34
+ latest = if version
35
+ all_objects.detect { |o| o.key =~ /^.*(#{latest}).*$/ }
36
+ else
37
+ all_objects.sort_by { |o| Date.parse(o.about[:last_modified]) }.last
38
+ end
39
+ if latest
40
+ encrypted_contents = latest.value
41
+ key = EzCrypto::Key.with_password ENV['SECRET_ACCESS_KEY'], 'saltoftheearth'
42
+ unencrypted_contents = key.decrypt encrypted_contents
43
+ File.open(TMP_BACKUP_FILE, 'w') { |f| f << unencrypted_contents }
44
+ %x(mysql < #{TMP_BACKUP_FILE})
45
+ end
46
+ rescue AWS::S3::NoSuchBucket
47
+ STDERR.puts "Nothing to restore"
48
+ ensure
49
+ FileUtils.rm_f TMP_BACKUP_FILE if File.exists? TMP_BACKUP_FILE
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + "/database_backup"
3
+ DatabaseBackup.restore! ARGV[0]
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubyworks-ec2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ platform: ruby
6
+ authors:
7
+ - George Malamidis, Markus Bengts
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-01-26 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: capistrano
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: "2.0"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: aws-s3
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: "0"
32
+ version:
33
+ description:
34
+ email: george@nutrun.com
35
+ executables:
36
+ - capify-for-ec2
37
+ extensions: []
38
+
39
+ extra_rdoc_files:
40
+ - README
41
+ - COPYING
42
+ files:
43
+ - lib/recipes/configuration.rb
44
+ - lib/recipes/db.rb
45
+ - lib/recipes/deploy.rb
46
+ - lib/recipes/haproxy.rb
47
+ - lib/recipes/image.rb
48
+ - lib/recipes/instance.rb
49
+ - lib/recipes/mongrel.rb
50
+ - lib/recipes/monit.rb
51
+ - lib/recipes/settings.rb
52
+ - lib/rubyworks-ec2.rb
53
+ - lib/s3.rb
54
+ - lib/util/backup_db.rb
55
+ - lib/util/database_backup.rb
56
+ - lib/util/restore_db.rb
57
+ - COPYING
58
+ - README
59
+ - Rakefile
60
+ - config/server
61
+ - config/server/etc
62
+ - config/server/etc/apache2
63
+ - config/server/etc/apache2/sites-available
64
+ - config/server/etc/apache2/sites-available/default
65
+ - config/server/etc/crontab
66
+ - config/server/etc/monit
67
+ - config/server/etc/monit/monitrc
68
+ - config/server/etc/mysql
69
+ - config/server/etc/mysql/my.cnf
70
+ - config/server/etc/rails
71
+ - config/server/etc/rails/haproxy.conf
72
+ - config/server/etc/rails/monit.conf
73
+ has_rdoc: true
74
+ homepage: http://rubyworks-ec2.rubyforge.org
75
+ post_install_message:
76
+ rdoc_options:
77
+ - --quiet
78
+ - --title
79
+ - rubyworks-ec2
80
+ - --main
81
+ - README
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "0"
89
+ version:
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ version:
96
+ requirements: []
97
+
98
+ rubyforge_project: rubyworks-ec2
99
+ rubygems_version: 1.0.1
100
+ signing_key:
101
+ specification_version: 2
102
+ summary: RubyWorks support
103
+ test_files: []
104
+