rubyworks-ec2 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/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
+