mdh-ec2onrails 0.9.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (163) hide show
  1. data/CHANGELOG +180 -0
  2. data/COPYING +339 -0
  3. data/Manifest +162 -0
  4. data/README.textile +214 -0
  5. data/Rakefile +36 -0
  6. data/TODO +102 -0
  7. data/ec2onrails.gemspec +42 -0
  8. data/examples/Capfile +3 -0
  9. data/examples/deploy.rb +101 -0
  10. data/examples/s3.yml +9 -0
  11. data/lib/ec2onrails.rb +20 -0
  12. data/lib/ec2onrails/capistrano_utils.rb +43 -0
  13. data/lib/ec2onrails/recipes.rb +844 -0
  14. data/lib/ec2onrails/version.rb +31 -0
  15. data/server/build-ec2onrails.sh +44 -0
  16. data/server/files/etc/aliases +5 -0
  17. data/server/files/etc/aliases.db +0 -0
  18. data/server/files/etc/apache2/apache2.conf +295 -0
  19. data/server/files/etc/apache2/conf.d/app.proxy_cluster.conf +7 -0
  20. data/server/files/etc/apache2/conf.d/app.proxy_frontend.conf +10 -0
  21. data/server/files/etc/apache2/mods-available/proxy.conf +18 -0
  22. data/server/files/etc/apache2/sites-available/app.common +56 -0
  23. data/server/files/etc/apache2/sites-available/app.custom +0 -0
  24. data/server/files/etc/apache2/sites-available/default +14 -0
  25. data/server/files/etc/apache2/sites-available/default-ssl +19 -0
  26. data/server/files/etc/cron.d/backup_app_db_to_s3 +16 -0
  27. data/server/files/etc/cron.daily/app +9 -0
  28. data/server/files/etc/cron.daily/logrotate_post +19 -0
  29. data/server/files/etc/cron.hourly/app +10 -0
  30. data/server/files/etc/cron.monthly/app +10 -0
  31. data/server/files/etc/cron.weekly/app +10 -0
  32. data/server/files/etc/denyhosts.conf +628 -0
  33. data/server/files/etc/dpkg/dpkg.cfg +13 -0
  34. data/server/files/etc/ec2onrails/README +32 -0
  35. data/server/files/etc/ec2onrails/balancer_members +6 -0
  36. data/server/files/etc/ec2onrails/roles.yml +5 -0
  37. data/server/files/etc/environment +2 -0
  38. data/server/files/etc/god/app.god +35 -0
  39. data/server/files/etc/god/db.god +17 -0
  40. data/server/files/etc/god/examples/have_god_daemonize.god +18 -0
  41. data/server/files/etc/god/master.conf +35 -0
  42. data/server/files/etc/god/memcache.god +15 -0
  43. data/server/files/etc/god/notifications.god +14 -0
  44. data/server/files/etc/god/system.god +34 -0
  45. data/server/files/etc/god/web.god +36 -0
  46. data/server/files/etc/init.d/ec2-every-startup +29 -0
  47. data/server/files/etc/init.d/ec2-first-startup +36 -0
  48. data/server/files/etc/init.d/god +42 -0
  49. data/server/files/etc/init.d/nginx +78 -0
  50. data/server/files/etc/init.d/set_roles +3 -0
  51. data/server/files/etc/logrotate.d/apache2 +16 -0
  52. data/server/files/etc/logrotate.d/mongrel +11 -0
  53. data/server/files/etc/logrotate.d/nginx +11 -0
  54. data/server/files/etc/memcached.conf +47 -0
  55. data/server/files/etc/mongrel_cluster/app.yml +9 -0
  56. data/server/files/etc/motd.tail +13 -0
  57. data/server/files/etc/mysql/my.cnf +152 -0
  58. data/server/files/etc/nginx/nginx.conf +296 -0
  59. data/server/files/etc/postfix/main.cf +4 -0
  60. data/server/files/etc/rcS.d/S91ec2-first-startup +1 -0
  61. data/server/files/etc/rcS.d/S92ec2-every-startup +1 -0
  62. data/server/files/etc/rcS.d/S99set_roles +1 -0
  63. data/server/files/etc/ssh/sshd_config +94 -0
  64. data/server/files/etc/sudoers +1 -0
  65. data/server/files/etc/sudoers.full_access +26 -0
  66. data/server/files/etc/sudoers.restricted_access +28 -0
  67. data/server/files/etc/syslog.conf +69 -0
  68. data/server/files/usr/bin/god +26 -0
  69. data/server/files/usr/local/ec2onrails/COPYING +339 -0
  70. data/server/files/usr/local/ec2onrails/bin/archive_file.rb +44 -0
  71. data/server/files/usr/local/ec2onrails/bin/backup_app_db.rb +159 -0
  72. data/server/files/usr/local/ec2onrails/bin/ec2_meta_data.rb +80 -0
  73. data/server/files/usr/local/ec2onrails/bin/exec_runner +73 -0
  74. data/server/files/usr/local/ec2onrails/bin/init_services.rb +64 -0
  75. data/server/files/usr/local/ec2onrails/bin/optimize_mysql.rb +348 -0
  76. data/server/files/usr/local/ec2onrails/bin/rails_env +35 -0
  77. data/server/files/usr/local/ec2onrails/bin/rebundle.sh +70 -0
  78. data/server/files/usr/local/ec2onrails/bin/restore_app_db.rb +58 -0
  79. data/server/files/usr/local/ec2onrails/bin/set_rails_env +40 -0
  80. data/server/files/usr/local/ec2onrails/bin/set_roles.rb +87 -0
  81. data/server/files/usr/local/ec2onrails/bin/setup_web_proxy.rb +109 -0
  82. data/server/files/usr/local/ec2onrails/config +30 -0
  83. data/server/files/usr/local/ec2onrails/lib/aws_helper.rb +76 -0
  84. data/server/files/usr/local/ec2onrails/lib/god_helper.rb +129 -0
  85. data/server/files/usr/local/ec2onrails/lib/god_patch.rb +43 -0
  86. data/server/files/usr/local/ec2onrails/lib/mysql_helper.rb +101 -0
  87. data/server/files/usr/local/ec2onrails/lib/roles_helper.rb +151 -0
  88. data/server/files/usr/local/ec2onrails/lib/s3_helper.rb +99 -0
  89. data/server/files/usr/local/ec2onrails/lib/utils.rb +16 -0
  90. data/server/files/usr/local/ec2onrails/lib/vendor/ini.rb +268 -0
  91. data/server/files/usr/local/ec2onrails/startup-scripts/every-startup/get-hostname.sh +25 -0
  92. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/README +5 -0
  93. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/create-dirs.sh +39 -0
  94. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/generate-default-web-cert-and-key.sh +49 -0
  95. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/misc.sh +27 -0
  96. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/prepare-mysql-data-dir.sh +24 -0
  97. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/setup-credentials.sh +29 -0
  98. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/setup-file-permissions.sh +30 -0
  99. data/server/rakefile.rb +248 -0
  100. data/setup.rb +1585 -0
  101. data/test/autobench.conf +60 -0
  102. data/test/spec/lib/s3_helper_spec.rb +134 -0
  103. data/test/spec/lib/s3_old.yml +3 -0
  104. data/test/spec/test_files/test1 +0 -0
  105. data/test/spec/test_files/test2 +0 -0
  106. data/test/test_app/Capfile +3 -0
  107. data/test/test_app/README +182 -0
  108. data/test/test_app/Rakefile +10 -0
  109. data/test/test_app/app/controllers/application.rb +7 -0
  110. data/test/test_app/app/controllers/db_fast_controller.rb +6 -0
  111. data/test/test_app/app/controllers/fast_controller.rb +5 -0
  112. data/test/test_app/app/controllers/slow_controller.rb +6 -0
  113. data/test/test_app/app/controllers/very_slow_controller.rb +6 -0
  114. data/test/test_app/app/helpers/application_helper.rb +3 -0
  115. data/test/test_app/app/helpers/db_fast_helper.rb +2 -0
  116. data/test/test_app/app/helpers/fast_helper.rb +2 -0
  117. data/test/test_app/app/helpers/slow_helper.rb +2 -0
  118. data/test/test_app/app/helpers/very_slow_helper.rb +2 -0
  119. data/test/test_app/config/boot.rb +109 -0
  120. data/test/test_app/config/database.yml +19 -0
  121. data/test/test_app/config/deploy.rb +21 -0
  122. data/test/test_app/config/environment.rb +60 -0
  123. data/test/test_app/config/environments/development.rb +21 -0
  124. data/test/test_app/config/environments/production.rb +18 -0
  125. data/test/test_app/config/environments/test.rb +19 -0
  126. data/test/test_app/config/routes.rb +27 -0
  127. data/test/test_app/db/schema.rb +7 -0
  128. data/test/test_app/doc/README_FOR_APP +2 -0
  129. data/test/test_app/public/404.html +30 -0
  130. data/test/test_app/public/500.html +30 -0
  131. data/test/test_app/public/dispatch.cgi +10 -0
  132. data/test/test_app/public/dispatch.fcgi +24 -0
  133. data/test/test_app/public/dispatch.rb +10 -0
  134. data/test/test_app/public/favicon.ico +0 -0
  135. data/test/test_app/public/images/rails.png +0 -0
  136. data/test/test_app/public/javascripts/application.js +2 -0
  137. data/test/test_app/public/javascripts/controls.js +963 -0
  138. data/test/test_app/public/javascripts/dragdrop.js +972 -0
  139. data/test/test_app/public/javascripts/effects.js +1120 -0
  140. data/test/test_app/public/javascripts/prototype.js +4225 -0
  141. data/test/test_app/public/robots.txt +1 -0
  142. data/test/test_app/script/about +3 -0
  143. data/test/test_app/script/breakpointer +3 -0
  144. data/test/test_app/script/console +3 -0
  145. data/test/test_app/script/destroy +3 -0
  146. data/test/test_app/script/generate +3 -0
  147. data/test/test_app/script/performance/benchmarker +3 -0
  148. data/test/test_app/script/performance/profiler +3 -0
  149. data/test/test_app/script/performance/request +3 -0
  150. data/test/test_app/script/plugin +3 -0
  151. data/test/test_app/script/process/inspector +3 -0
  152. data/test/test_app/script/process/reaper +3 -0
  153. data/test/test_app/script/process/spawner +3 -0
  154. data/test/test_app/script/runner +3 -0
  155. data/test/test_app/script/server +3 -0
  156. data/test/test_app/test/functional/db_fast_controller_test.rb +18 -0
  157. data/test/test_app/test/functional/fast_controller_test.rb +18 -0
  158. data/test/test_app/test/functional/slow_controller_test.rb +18 -0
  159. data/test/test_app/test/functional/very_slow_controller_test.rb +18 -0
  160. data/test/test_app/test/test_helper.rb +28 -0
  161. data/test/test_ec2onrails.rb +11 -0
  162. data/test/test_helper.rb +2 -0
  163. metadata +274 -0
@@ -0,0 +1,42 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{ec2onrails}
3
+ s.version = "0.9.10"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Paul Dowman, Adam Greene"]
7
+ s.date = %q{2008-12-19}
8
+ s.description = %q{Client-side libraries (Capistrano tasks) for managing and deploying to EC2 on Rails servers.}
9
+ s.email = %q{paul@pauldowman.com}
10
+ s.extra_rdoc_files = ["CHANGELOG", "lib/ec2onrails/capistrano_utils.rb", "lib/ec2onrails/recipes.rb", "lib/ec2onrails/version.rb", "lib/ec2onrails.rb", "README.textile"]
11
+ s.files = ["CHANGELOG", "COPYING", "ec2onrails.gemspec", "examples/Capfile", "examples/deploy.rb", "examples/s3.yml", "lib/ec2onrails/capistrano_utils.rb", "lib/ec2onrails/recipes.rb", "lib/ec2onrails/version.rb", "lib/ec2onrails.rb", "Manifest", "Rakefile", "README.textile", "server/build-ec2onrails.sh", "server/files/etc/aliases", "server/files/etc/aliases.db", "server/files/etc/apache2/apache2.conf", "server/files/etc/apache2/conf.d/app.proxy_cluster.conf", "server/files/etc/apache2/conf.d/app.proxy_frontend.conf", "server/files/etc/apache2/mods-available/proxy.conf", "server/files/etc/apache2/sites-available/app.common", "server/files/etc/apache2/sites-available/app.custom", "server/files/etc/apache2/sites-available/default", "server/files/etc/apache2/sites-available/default-ssl", "server/files/etc/cron.d/backup_app_db_to_s3", "server/files/etc/cron.daily/app", "server/files/etc/cron.daily/logrotate_post", "server/files/etc/cron.hourly/app", "server/files/etc/cron.monthly/app", "server/files/etc/cron.weekly/app", "server/files/etc/denyhosts.conf", "server/files/etc/dpkg/dpkg.cfg", "server/files/etc/ec2onrails/balancer_members", "server/files/etc/ec2onrails/README", "server/files/etc/ec2onrails/roles.yml", "server/files/etc/environment", "server/files/etc/god/app.god", "server/files/etc/god/db.god", "server/files/etc/god/examples/have_god_daemonize.god", "server/files/etc/god/master.conf", "server/files/etc/god/memcache.god", "server/files/etc/god/notifications.god", "server/files/etc/god/system.god", "server/files/etc/god/web.god", "server/files/etc/init.d/ec2-every-startup", "server/files/etc/init.d/ec2-first-startup", "server/files/etc/init.d/god", "server/files/etc/init.d/nginx", "server/files/etc/init.d/set_roles", "server/files/etc/logrotate.d/apache2", "server/files/etc/logrotate.d/mongrel", "server/files/etc/logrotate.d/nginx", "server/files/etc/memcached.conf", "server/files/etc/mongrel_cluster/app.yml", "server/files/etc/motd.tail", "server/files/etc/mysql/my.cnf", "server/files/etc/nginx/nginx.conf", "server/files/etc/postfix/main.cf", "server/files/etc/rcS.d/S91ec2-first-startup", "server/files/etc/rcS.d/S92ec2-every-startup", "server/files/etc/rcS.d/S99set_roles", "server/files/etc/ssh/sshd_config", "server/files/etc/sudoers", "server/files/etc/sudoers.full_access", "server/files/etc/sudoers.restricted_access", "server/files/etc/syslog.conf", "server/files/usr/bin/god", "server/files/usr/local/ec2onrails/bin/archive_file.rb", "server/files/usr/local/ec2onrails/bin/backup_app_db.rb", "server/files/usr/local/ec2onrails/bin/ec2_meta_data.rb", "server/files/usr/local/ec2onrails/bin/exec_runner", "server/files/usr/local/ec2onrails/bin/init_services.rb", "server/files/usr/local/ec2onrails/bin/optimize_mysql.rb", "server/files/usr/local/ec2onrails/bin/rails_env", "server/files/usr/local/ec2onrails/bin/rebundle.sh", "server/files/usr/local/ec2onrails/bin/restore_app_db.rb", "server/files/usr/local/ec2onrails/bin/set_rails_env", "server/files/usr/local/ec2onrails/bin/set_roles.rb", "server/files/usr/local/ec2onrails/bin/setup_web_proxy.rb", "server/files/usr/local/ec2onrails/config", "server/files/usr/local/ec2onrails/COPYING", "server/files/usr/local/ec2onrails/lib/aws_helper.rb", "server/files/usr/local/ec2onrails/lib/god_helper.rb", "server/files/usr/local/ec2onrails/lib/god_patch.rb", "server/files/usr/local/ec2onrails/lib/mysql_helper.rb", "server/files/usr/local/ec2onrails/lib/roles_helper.rb", "server/files/usr/local/ec2onrails/lib/s3_helper.rb", "server/files/usr/local/ec2onrails/lib/utils.rb", "server/files/usr/local/ec2onrails/lib/vendor/ini.rb", "server/files/usr/local/ec2onrails/startup-scripts/every-startup/get-hostname.sh", "server/files/usr/local/ec2onrails/startup-scripts/first-startup/create-dirs.sh", "server/files/usr/local/ec2onrails/startup-scripts/first-startup/generate-default-web-cert-and-key.sh", "server/files/usr/local/ec2onrails/startup-scripts/first-startup/misc.sh", "server/files/usr/local/ec2onrails/startup-scripts/first-startup/prepare-mysql-data-dir.sh", "server/files/usr/local/ec2onrails/startup-scripts/first-startup/README", "server/files/usr/local/ec2onrails/startup-scripts/first-startup/setup-credentials.sh", "server/files/usr/local/ec2onrails/startup-scripts/first-startup/setup-file-permissions.sh", "server/rakefile.rb", "setup.rb", "test/autobench.conf", "test/spec/lib/s3_helper_spec.rb", "test/spec/lib/s3_old.yml", "test/spec/test_files/test1", "test/spec/test_files/test2", "test/test_app/app/controllers/application.rb", "test/test_app/app/controllers/db_fast_controller.rb", "test/test_app/app/controllers/fast_controller.rb", "test/test_app/app/controllers/slow_controller.rb", "test/test_app/app/controllers/very_slow_controller.rb", "test/test_app/app/helpers/application_helper.rb", "test/test_app/app/helpers/db_fast_helper.rb", "test/test_app/app/helpers/fast_helper.rb", "test/test_app/app/helpers/slow_helper.rb", "test/test_app/app/helpers/very_slow_helper.rb", "test/test_app/Capfile", "test/test_app/config/boot.rb", "test/test_app/config/database.yml", "test/test_app/config/deploy.rb", "test/test_app/config/environment.rb", "test/test_app/config/environments/development.rb", "test/test_app/config/environments/production.rb", "test/test_app/config/environments/test.rb", "test/test_app/config/routes.rb", "test/test_app/db/schema.rb", "test/test_app/doc/README_FOR_APP", "test/test_app/public/404.html", "test/test_app/public/500.html", "test/test_app/public/dispatch.cgi", "test/test_app/public/dispatch.fcgi", "test/test_app/public/dispatch.rb", "test/test_app/public/favicon.ico", "test/test_app/public/images/rails.png", "test/test_app/public/javascripts/application.js", "test/test_app/public/javascripts/controls.js", "test/test_app/public/javascripts/dragdrop.js", "test/test_app/public/javascripts/effects.js", "test/test_app/public/javascripts/prototype.js", "test/test_app/public/robots.txt", "test/test_app/Rakefile", "test/test_app/README", "test/test_app/script/about", "test/test_app/script/breakpointer", "test/test_app/script/console", "test/test_app/script/destroy", "test/test_app/script/generate", "test/test_app/script/performance/benchmarker", "test/test_app/script/performance/profiler", "test/test_app/script/performance/request", "test/test_app/script/plugin", "test/test_app/script/process/inspector", "test/test_app/script/process/reaper", "test/test_app/script/process/spawner", "test/test_app/script/runner", "test/test_app/script/server", "test/test_app/test/functional/db_fast_controller_test.rb", "test/test_app/test/functional/fast_controller_test.rb", "test/test_app/test/functional/slow_controller_test.rb", "test/test_app/test/functional/very_slow_controller_test.rb", "test/test_app/test/test_helper.rb", "test/test_ec2onrails.rb", "test/test_helper.rb", "TODO"]
12
+ s.has_rdoc = true
13
+ s.homepage = %q{http://ec2onrails.rubyforge.org}
14
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Ec2onrails", "--main", "README.textile"]
15
+ s.require_paths = ["lib"]
16
+ s.rubyforge_project = %q{ec2onrails}
17
+ s.rubygems_version = %q{1.3.1}
18
+ s.summary = %q{Client-side libraries (Capistrano tasks) for managing and deploying to EC2 on Rails servers.}
19
+ s.test_files = ["test/test_app/test/functional/db_fast_controller_test.rb", "test/test_app/test/functional/fast_controller_test.rb", "test/test_app/test/functional/slow_controller_test.rb", "test/test_app/test/functional/very_slow_controller_test.rb", "test/test_app/test/test_helper.rb", "test/test_ec2onrails.rb", "test/test_helper.rb"]
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 2
24
+
25
+ if current_version >= 3 then
26
+ s.add_runtime_dependency(%q<capistrano>, [">= 0", "= 2.4.3"])
27
+ s.add_runtime_dependency(%q<archive-tar-minitar>, [">= 0", "= 0.5.2"])
28
+ s.add_runtime_dependency(%q<optiflag>, [">= 0", "= 0.6.5"])
29
+ s.add_development_dependency(%q<rake>, [">= 0.7.1"])
30
+ else
31
+ s.add_dependency(%q<capistrano>, [">= 0", "= 2.4.3"])
32
+ s.add_dependency(%q<archive-tar-minitar>, [">= 0", "= 0.5.2"])
33
+ s.add_dependency(%q<optiflag>, [">= 0", "= 0.6.5"])
34
+ s.add_dependency(%q<rake>, [">= 0.7.1"])
35
+ end
36
+ else
37
+ s.add_dependency(%q<capistrano>, [">= 0", "= 2.4.3"])
38
+ s.add_dependency(%q<archive-tar-minitar>, [">= 0", "= 0.5.2"])
39
+ s.add_dependency(%q<optiflag>, [">= 0", "= 0.6.5"])
40
+ s.add_dependency(%q<rake>, [">= 0.7.1"])
41
+ end
42
+ end
data/examples/Capfile ADDED
@@ -0,0 +1,3 @@
1
+ load 'deploy' if respond_to?(:namespace) # cap2 differentiator
2
+ load 'config/deploy'
3
+ require 'ec2onrails/recipes'
@@ -0,0 +1,101 @@
1
+ # This is a sample Capistrano config file for EC2 on Rails.
2
+ # It should be edited and customized.
3
+
4
+ set :application, "yourapp"
5
+
6
+ set :repository, "http://svn.foo.com/svn/#{application}/trunk"
7
+
8
+ # NOTE: for some reason Capistrano requires you to have both the public and
9
+ # the private key in the same folder, the public key should have the
10
+ # extension ".pub".
11
+ ssh_options[:keys] = ["#{ENV['HOME']}/.ssh/your-ec2-key"]
12
+
13
+ # Your EC2 instances. Use the ec2-xxx....amazonaws.com hostname, not
14
+ # any other name (in case you have your own DNS alias) or it won't
15
+ # be able to resolve to the internal IP address.
16
+ role :web, "ec2-12-xx-xx-xx.z-1.compute-1.amazonaws.com"
17
+ role :app, "ec2-34-xx-xx-xx.z-1.compute-1.amazonaws.com"
18
+ role :memcache, "ec2-12-xx-xx-xx.z-1.compute-1.amazonaws.com"
19
+ role :db, "ec2-56-xx-xx-xx.z-1.compute-1.amazonaws.com", :primary => true
20
+ # role :db, "ec2-56-xx-xx-xx.z-1.compute-1.amazonaws.com", :primary => true, :ebs_vol_id => 'vol-12345abc'
21
+ # optinally, you can specify Amazon's EBS volume ID if the database is persisted
22
+ # via Amazon's EBS. See the main README for more information.
23
+
24
+ # Whatever you set here will be taken set as the default RAILS_ENV value
25
+ # on the server. Your app and your hourly/daily/weekly/monthly scripts
26
+ # will run with RAILS_ENV set to this value.
27
+ set :rails_env, "production"
28
+
29
+ # EC2 on Rails config.
30
+ # NOTE: Some of these should be omitted if not needed.
31
+ set :ec2onrails_config, {
32
+ # S3 bucket and "subdir" used by the ec2onrails:db:restore task
33
+ # NOTE: this only applies if you are not using EBS
34
+ :restore_from_bucket => "your-bucket",
35
+ :restore_from_bucket_subdir => "database",
36
+
37
+ # S3 bucket and "subdir" used by the ec2onrails:db:archive task
38
+ # This does not affect the automatic backup of your MySQL db to S3, it's
39
+ # just for manually archiving a db snapshot to a different bucket if
40
+ # desired.
41
+ # NOTE: this only applies if you are not using EBS
42
+ :archive_to_bucket => "your-other-bucket",
43
+ :archive_to_bucket_subdir => "db-archive/#{Time.new.strftime('%Y-%m-%d--%H-%M-%S')}",
44
+
45
+ # Set a root password for MySQL. Run "cap ec2onrails:db:set_root_password"
46
+ # to enable this. This is optional, and after doing this the
47
+ # ec2onrails:db:drop task won't work, but be aware that MySQL accepts
48
+ # connections on the public network interface (you should block the MySQL
49
+ # port with the firewall anyway).
50
+ # If you don't care about setting the mysql root password then remove this.
51
+ :mysql_root_password => "your-mysql-root-password",
52
+
53
+ # Any extra Ubuntu packages to install if desired
54
+ # If you don't want to install extra packages then remove this.
55
+ :packages => ["logwatch", "imagemagick"],
56
+
57
+ # Any extra RubyGems to install if desired: can be "gemname" or if a
58
+ # particular version is desired "gemname -v 1.0.1"
59
+ # If you don't want to install extra rubygems then remove this
60
+ # NOTE: if you are using rails 2.1, ec2onrails calls 'sudo rake gem:install',
61
+ # which will install gems defined in your rails configuration
62
+ :rubygems => ["rmagick", "rfacebook -v 0.9.7"],
63
+
64
+ # Defines the web proxy that will be used. Choices are :apache or :nginx
65
+ :web_proxy_server => :apache,
66
+
67
+ # extra security measures are taken if this is true, BUT it makes initial
68
+ # experimentation and setup a bit tricky. For example, if you do not
69
+ # have your ssh keys setup correctly, you will be locked out of your
70
+ # server after 3 attempts for upto 3 months.
71
+ :harden_server => false,
72
+
73
+ # Set the server timezone. run "cap -e ec2onrails:server:set_timezone" for
74
+ # details
75
+ :timezone => "UTC",
76
+
77
+ # Files to deploy to the server (they'll be owned by root). It's intended
78
+ # mainly for customized config files for new packages installed via the
79
+ # ec2onrails:server:install_packages task. Subdirectories and files inside
80
+ # here will be placed in the same structure relative to the root of the
81
+ # server's filesystem.
82
+ # If you don't need to deploy customized config files to the server then
83
+ # remove this.
84
+ :server_config_files_root => "../server_config",
85
+
86
+ # If config files are deployed, some services might need to be restarted.
87
+ # If you don't need to deploy customized config files to the server then
88
+ # remove this.
89
+ :services_to_restart => %w(postfix sysklogd),
90
+
91
+ # Set an email address to forward admin mail messages to. If you don't
92
+ # want to receive mail from the server (e.g. monit alert messages) then
93
+ # remove this.
94
+ :mail_forward_address => "you@yourdomain.com",
95
+
96
+ # Set this if you want SSL to be enabled on the web server. The SSL cert
97
+ # and key files need to exist on the server, The cert file should be in
98
+ # /etc/ssl/certs/default.pem and the key file should be in
99
+ # /etc/ssl/private/default.key (see :server_config_files_root).
100
+ :enable_ssl => true
101
+ }
data/examples/s3.yml ADDED
@@ -0,0 +1,9 @@
1
+ staging:
2
+ aws_access_key: ABC123
3
+ aws_secret_access_key: abc123abc123abc123abc123
4
+ bucket_base_name: yourbucket
5
+
6
+ production:
7
+ aws_access_key: DEF456
8
+ aws_secret_access_key: def456def456def456def456
9
+ bucket_base_name: yourbucket
data/lib/ec2onrails.rb ADDED
@@ -0,0 +1,20 @@
1
+ # This file is part of EC2 on Rails.
2
+ # http://rubyforge.org/projects/ec2onrails/
3
+ #
4
+ # Copyright 2007 Paul Dowman, http://pauldowman.com/
5
+ #
6
+ # EC2 on Rails is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # EC2 on Rails 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
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+
20
+ $:.unshift File.dirname(__FILE__)
@@ -0,0 +1,43 @@
1
+ module Ec2onrails
2
+ module CapistranoUtils
3
+ def run_local(command)
4
+ result = system command
5
+ raise("error: #{$?}") unless result
6
+ end
7
+
8
+ def run_init_script(script, arg)
9
+ # since init scripts might have the execute bit unset by the set_roles script we need to check
10
+ sudo "sh -c 'if [ -x /etc/init.d/#{script} ] ; then /etc/init.d/#{script} #{arg}; fi'"
11
+ end
12
+
13
+ # return hostnames for the role named role_sym that has the specified options
14
+ def hostnames_for_role(role_sym, options = {})
15
+ role = roles[role_sym]
16
+ unless role
17
+ return []
18
+ end
19
+ # make sure we match the server with all the passed in options, BUT the server can
20
+ # have additional options defined. e.g.: :primary => true and :ebs_vol_id => 'vol-1234abcd'
21
+ # but we want to select the server where :primary => true
22
+ role.select{|s|
23
+ match = true
24
+ options.each_pair{|k,v| match = false if s.options[k] != v}
25
+ }.collect{|s| s.host}
26
+ end
27
+
28
+ # Like the capture method, but does not print out error stream and swallows
29
+ # an exception if the process's exit code != 0
30
+ def quiet_capture(command, options={})
31
+ output = ""
32
+ invoke_command(command, options.merge(:once => true)) do |ch, stream, data|
33
+ case stream
34
+ when :out then output << data
35
+ # when :err then warn "[err :: #{ch[:server]}] #{data}"
36
+ end
37
+ end
38
+ ensure
39
+ return (output || '').strip
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,844 @@
1
+ # This file is part of EC2 on Rails.
2
+ # http://rubyforge.org/projects/ec2onrails/
3
+ #
4
+ # Copyright 2007 Paul Dowman, http://pauldowman.com/
5
+ #
6
+ # EC2 on Rails is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # EC2 on Rails 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
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ require 'fileutils'
20
+ include FileUtils
21
+ require 'tmpdir'
22
+ require 'pp'
23
+ require 'zlib'
24
+ require 'archive/tar/minitar'
25
+ include Archive::Tar
26
+
27
+ require 'ec2onrails/version'
28
+ require 'ec2onrails/capistrano_utils'
29
+ include Ec2onrails::CapistranoUtils
30
+
31
+ Capistrano::Configuration.instance.load do
32
+
33
+ unless ec2onrails_config
34
+ raise "ec2onrails_config variable not set. (It should be a hash.)"
35
+ end
36
+
37
+ cfg = ec2onrails_config
38
+
39
+ #:apache or :nginx
40
+ cfg[:web_proxy_server] ||= :apache
41
+
42
+ set :ec2onrails_version, Ec2onrails::VERSION::STRING
43
+ set :image_id_32_bit, Ec2onrails::VERSION::AMI_ID_32_BIT
44
+ set :image_id_64_bit, Ec2onrails::VERSION::AMI_ID_64_BIT
45
+ set :deploy_to, "/mnt/app"
46
+ set :use_sudo, false
47
+ set :user, "app"
48
+
49
+ #in case any changes were made to the configs, like changing the number of mongrels
50
+ before "deploy:cold", "ec2onrails:server:grant_sudo_access"
51
+ after "deploy:symlink", "ec2onrails:server:set_roles", "ec2onrails:server:init_services"
52
+ after "deploy:cold", "ec2onrails:db:init_backup", "ec2onrails:db:optimize", "ec2onrails:server:restrict_sudo_access"
53
+ after "ec2onrails:server:install_gems", "ec2onrails:server:add_gem_sources"
54
+
55
+ #NOTE: some default setups (like engineyard's) do some symlinking of config files after
56
+ # deploy:update_code. The ordering here matters as we need to have those symlinks in place
57
+ # but we need to have the gems in place before the rails env is loaded up, or else it will
58
+ # fail. By adding it to the callback queue AFTER all the tasks have loaded up, we make sure
59
+ # it is done at the very end.
60
+ #
61
+ # *IF* you had tasks also triggered after update_code that run rake tasks
62
+ # (like compressing javascript and stylesheets), move those over to before "deploy:symlink"
63
+ # and you'll be set!
64
+ on :load do
65
+ after "deploy:update_code", "ec2onrails:server:run_rails_rake_gems_install"
66
+ end
67
+
68
+
69
+ # override default start/stop/restart tasks
70
+ namespace :deploy do
71
+ desc <<-DESC
72
+ Overrides the default Capistrano deploy:start, uses \
73
+ 'god start app'
74
+ DESC
75
+ task :start, :roles => :app do
76
+ sudo "god start app"
77
+ # sudo "god monitor app"
78
+ end
79
+
80
+ desc <<-DESC
81
+ Overrides the default Capistrano deploy:stop, uses \
82
+ 'god stop app'
83
+ DESC
84
+ task :stop, :roles => :app do
85
+ # sudo "god unmonitor app"
86
+ sudo "god stop app"
87
+ end
88
+
89
+ desc <<-DESC
90
+ Overrides the default Capistrano deploy:restart, uses \
91
+ 'god restart app'
92
+ DESC
93
+ task :restart, :roles => :app do
94
+ sudo "god restart app"
95
+ end
96
+ end
97
+
98
+ namespace :ec2onrails do
99
+ desc <<-DESC
100
+ Show the AMI id's of the current images for this version of \
101
+ EC2 on Rails.
102
+ DESC
103
+ task :ami_ids do
104
+ puts "32-bit server image for EC2 on Rails #{ec2onrails_version}: #{image_id_32_bit}"
105
+ puts "64-bit server image for EC2 on Rails #{ec2onrails_version}: #{image_id_64_bit}"
106
+ end
107
+
108
+ desc <<-DESC
109
+ Copies the public key from the server using the external "ssh"
110
+ command because Net::SSH, which is used by Capistrano, needs it.
111
+ This will only work if you have an ssh command in the path.
112
+ If Capistrano can successfully connect to your EC2 instance you
113
+ don't need to do this. It will copy from the first server in the
114
+ :app role, this can be overridden by specifying the HOST
115
+ environment variable
116
+ DESC
117
+ task :get_public_key_from_server do
118
+ host = find_servers_for_task(current_task).first.host
119
+ privkey = ssh_options[:keys][0]
120
+ pubkey = "#{privkey}.pub"
121
+ msg = <<-MSG
122
+ Your first key in ssh_options[:keys] is #{privkey}, presumably that's
123
+ your EC2 private key. The public key will be copied from the server
124
+ named '#{host}' and saved locally as #{pubkey}. Continue? [y/n]
125
+ MSG
126
+ choice = nil
127
+ while choice != "y" && choice != "n"
128
+ choice = Capistrano::CLI.ui.ask(msg).downcase
129
+ msg = "Please enter 'y' or 'n'."
130
+ end
131
+ if choice == "y"
132
+ run_local "scp -i '#{privkey}' app@#{host}:.ssh/authorized_keys #{pubkey}"
133
+ end
134
+ end
135
+
136
+ desc <<-DESC
137
+ Prepare a newly-started instance for a cold deploy.
138
+ DESC
139
+ task :setup do
140
+ ec2onrails.server.allow_sudo do
141
+ server.set_mail_forward_address
142
+ server.set_timezone
143
+ server.install_packages
144
+ server.install_gems
145
+ server.deploy_files
146
+ server.setup_web_proxy
147
+ server.set_roles
148
+ server.enable_ssl if cfg[:enable_ssl]
149
+ server.set_rails_env
150
+ server.restart_services
151
+ deploy.setup
152
+ db.create
153
+ server.harden_server
154
+ db.enable_ebs
155
+ end
156
+ end
157
+
158
+ desc <<-DESC
159
+ Deploy and restore database from S3
160
+ DESC
161
+ task :restore_db_and_deploy do
162
+ db.recreate
163
+ deploy.update_code
164
+ deploy.symlink
165
+ db.restore
166
+ deploy.migrations
167
+ end
168
+
169
+ namespace :ec2 do
170
+ desc <<-DESC
171
+ DESC
172
+ task :configure_firewall do
173
+ # TODO
174
+ end
175
+ end
176
+
177
+ namespace :db do
178
+ desc <<-DESC
179
+ [internal] Load configuration info for the database from
180
+ config/database.yml, and start mysql (it must be running
181
+ in order to interact with it).
182
+ DESC
183
+ task :load_config do
184
+ unless hostnames_for_role(:db, :primary => true).empty?
185
+ db_config = YAML::load(ERB.new(File.read("config/database.yml")).result)[rails_env.to_s] || {}
186
+ cfg[:db_name] ||= db_config['database']
187
+ cfg[:db_user] ||= db_config['username'] || db_config['user']
188
+ cfg[:db_password] ||= db_config['password']
189
+ cfg[:db_host] ||= db_config['host']
190
+ cfg[:db_port] ||= db_config['port']
191
+ cfg[:db_socket] ||= db_config['socket']
192
+
193
+ if (cfg[:db_host].nil? || cfg[:db_host].empty?) && (cfg[:db_socket].nil? || cfg[:db_socket].empty?)
194
+ raise "ERROR: missing database config. Make sure database.yml contains a '#{rails_env}' section with either 'host: hostname' or 'socket: /var/run/mysqld/mysqld.sock'."
195
+ end
196
+
197
+ [cfg[:db_name], cfg[:db_user], cfg[:db_password]].each do |s|
198
+ if s.nil? || s.empty?
199
+ raise "ERROR: missing database config. Make sure database.yml contains a '#{rails_env}' section with a database name, user, and password."
200
+ elsif s.match(/['"]/)
201
+ raise "ERROR: database config string '#{s}' contains quotes."
202
+ end
203
+ end
204
+ end
205
+ end
206
+
207
+ desc <<-DESC
208
+ Create the MySQL database. Assumes there is no MySQL root \
209
+ password. To create a MySQL root password create a task that's run \
210
+ after this task using an after hook.
211
+ DESC
212
+ task :create, :roles => :db do
213
+ on_rollback { drop }
214
+ load_config
215
+ start
216
+ sleep(5) #make sure the db has some time to start up!
217
+
218
+
219
+ # remove the default test database, though sometimes it doesn't exist (perhaps it isn't there anymore?)
220
+ run %{mysql -u root -e "drop database if exists test; flush privileges;"}
221
+
222
+ # removing anonymous mysql accounts
223
+ run %{mysql -u root -D mysql -e "delete from db where User = ''; flush privileges;"}
224
+ run %{mysql -u root -D mysql -e "delete from user where User = ''; flush privileges;"}
225
+
226
+ # qoting of database names allows special characters eg (the-database-name)
227
+ # the quotes need to be double escaped. Once for capistrano and once for the host shell
228
+ run %{mysql -u root -e "create database if not exists \\`#{cfg[:db_name]}\\`;"}
229
+ run %{mysql -u root -e "grant all on \\`#{cfg[:db_name]}\\`.* to '#{cfg[:db_user]}'@'%' identified by '#{cfg[:db_password]}';"}
230
+ run %{mysql -u root -e "grant reload on *.* to '#{cfg[:db_user]}'@'%' identified by '#{cfg[:db_password]}';"}
231
+ run %{mysql -u root -e "grant super on *.* to '#{cfg[:db_user]}'@'%' identified by '#{cfg[:db_password]}';"}
232
+ end
233
+
234
+ desc <<-DESC
235
+ Move the MySQL database to Amazon's Elastic Block Store (EBS), \
236
+ which is a persistant data store for the cloud.
237
+ OPTIONAL PARAMETERS:
238
+ * SIZE: Pass in num in gigs, like 10, to set the size, otherwise it will \
239
+ default to 10 gigs.
240
+ * VOLUME_ID: The volume_id to use for the mysql database
241
+ NOTE: keep track of the volume ID, as you'll want to keep this for your \
242
+ records and probably add it to the :db role in your deploy.rb file \
243
+ (see the ec2onrails sample deploy.rb file for additional information)
244
+ DESC
245
+ task :enable_ebs, :roles => :db, :only => { :primary => true } do
246
+ # based off of Eric's work:
247
+ # http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1663&categoryID=100
248
+ #
249
+ # EXPLAINATION:
250
+ # There is a lot going on here! At the end, the setup should be:
251
+ # * create EBS volume if run outside of the ec2onrails:setup and
252
+ # VOLUME_ID is not passed in when the cap task is called
253
+ # * EBS volume attached to /dev/sdh
254
+ # * format to xfs if new or do a xfs_check if previously existed
255
+ # * mounted on /var/local and update /etc/fstab
256
+ # * move /mnt/mysql_data -> /var/local/mysql_data
257
+ # * move /mnt/log/mysql -> /var/local/log/mysql
258
+ # * change mysql configs by writing /etc/mysql/conf.d/mysql-ec2-ebs.cnf
259
+ # * keep a copy of the mysql configs with the EBS volume, and if that volume is hooked into
260
+ # another instance, make sure the mysql configs that go with that volume are symlinked to /etc/mysql
261
+ # * update the file locations of the mysql binary logs in /mnt/log/mysql/mysql-bin.index
262
+ # * symlink the moved folders to their old position... makes the move to EBS transparent
263
+ # * Amazon doesn't contain EBS information in the meta-data API (yet). So write
264
+ # /etc/ec2onrails/ebs_info.yml
265
+ # to contain the meta-data information that we need
266
+ #
267
+ # DESIGN CONSIDERATIONS
268
+ # * only moving mysql data to EBS. seems the most obvious, and if we move over other components
269
+ # we will have to share that bandwidth (1 Gbps pipe to SAN). So limiting to what we really need
270
+ # * not moving all mysql logic over (tmp scratch space stays local). Again, this is to limit
271
+ # unnecessary bandwidth usage, PLUS, we are charged per million IO to EBS
272
+ #
273
+ # TODO:
274
+ # * make sure if we have a predefined ebs_vol_id, that we error out with a nice msg IF the zones do not match
275
+ # * can we move more of the mysql cache files back to the local disk and off of EBS, like the innodb table caches?
276
+ # * right now we force this task to only be run on one server; that works for db :primary => true
277
+ # But what is the best way to make this work if it needs to setup multiple servers (like db slaves)?
278
+ # I need to figure out how to do a direct mapping from a server definition to a ebs_vol_id
279
+ # * when we enable slaves and we setup ebs volumes on them, make it transparent to the user.
280
+ # have the slave create a snapshot of the db.master volume, and then use that to mount from
281
+ # * need to do a rollback that if the volume is created but something fails, lets uncreate it?
282
+ # carefull though! If it fails towards the end when information is copied over, it could cause information
283
+ # to be lost!
284
+ #
285
+
286
+ mysql_dir_root = '/var/local'
287
+ block_mnt = '/dev/sdh'
288
+ servers = find_servers_for_task(current_task)
289
+
290
+ if servers.empty?
291
+ raise Capistrano::NoMatchingServersError, "`#{task.fully_qualified_name}' is only run for servers matching #{task.options.inspect}, but no servers matched"
292
+ elsif servers.size > 1
293
+ raise Capistrano::Error, "`#{task.fully_qualified_name}' is can only be run on one server, not #{server.size}"
294
+ end
295
+
296
+ vol_id = ENV['VOLUME_ID'] || servers.first.options[:ebs_vol_id]
297
+
298
+ #HACK! capistrano doesn't allow arguments to be passed in if we call this task as a method, like 'db.enable_ebs'
299
+ # the places where we do call it like that, we don't want to force a move to ebs, so....
300
+ # if the call frame is > 1 (ie, another task called it), do NOT force the ebs move
301
+ no_force = task_call_frames.size > 1
302
+ prev_created = !(vol_id.nil? || vol_id.empty?)
303
+ #no vol_id was passed in, but perhaps it is already mounted...?
304
+ prev_created = true if !quiet_capture("mount | grep -inr '#{mysql_dir_root}' || echo ''").empty?
305
+
306
+ unless no_force && (vol_id.nil? || vol_id.empty?)
307
+ zone = quiet_capture("/usr/local/ec2onrails/bin/ec2_meta_data.rb -key 'placement/availability-zone'")
308
+ instance_id = quiet_capture("/usr/local/ec2onrails/bin/ec2_meta_data.rb -key 'instance-id'")
309
+
310
+ unless prev_created
311
+ puts "creating new ebs volume...."
312
+ size = ENV["SIZE"] || "10"
313
+ cmd = "ec2-create-volume -s #{size} -z #{zone} 2>&1"
314
+ puts "running: #{cmd}"
315
+ output = `#{cmd}`
316
+ puts output
317
+ vol_id = (output =~ /^VOLUME\t(.+?)\t/ && $1)
318
+ puts "NOTE: remember that vol_id"
319
+ sleep(2)
320
+ end
321
+ vol_id.strip! if vol_id
322
+ if quiet_capture("mount | grep -inr '#{block_mnt}' || echo ''").empty?
323
+ cmd = "ec2-attach-volume -d #{block_mnt} -i #{instance_id} #{vol_id} 2>&1"
324
+ puts "running: #{cmd}"
325
+ output = `#{cmd}`
326
+ puts output
327
+ if output =~ /Client.InvalidVolume.ZoneMismatch/i
328
+ raise Exception, "The volume you are trying to attach does not reside in the zone of your instance. Stopping!"
329
+ end
330
+
331
+
332
+ sleep(10)
333
+ end
334
+
335
+ ec2onrails.server.allow_sudo do
336
+ # try to format the volume... if it is already formatted, lets run a check on
337
+ # it to make sure it is ok, and then continue on
338
+ # if errors, the device is busy...something else is going on here and it is already mounted... skip!
339
+ if prev_created
340
+ # Stop the db (mysql server) for cases where this is being run after the original run
341
+ # If EBS partiion is already mounted and being used by mysql, it will fail when umount is run
342
+ god_status = quiet_capture("sudo god status")
343
+ god_status = god_status.empty? ? {} : YAML::load(god_status)
344
+ start_stop_db = false
345
+ start_stop_db = god_status['db']['mysql'] == 'up'
346
+ if start_stop_db
347
+ stop
348
+ puts "Waiting for mysql to stop"
349
+ sleep(10)
350
+ end
351
+ quiet_capture("sudo umount #{mysql_dir_root}") #unmount if need to
352
+ sudo "xfs_check #{block_mnt}"
353
+ # Restart the db if it
354
+ start if start_stop_db
355
+ else
356
+ sudo "mkfs.xfs #{block_mnt}"
357
+ end
358
+
359
+ # if not added to /etc/fstab, lets do so
360
+ sudo "sh -c \"grep -iqn '#{mysql_dir_root}' /etc/fstab || echo '#{block_mnt} #{mysql_dir_root} xfs noatime 0 0' >> /etc/fstab\""
361
+ sudo "mkdir -p #{mysql_dir_root}"
362
+ #if not already mounted, lets mount it
363
+ sudo "sh -c \"mount | grep -iqn '#{mysql_dir_root}' || mount '#{mysql_dir_root}'\""
364
+
365
+ #ok, now lets move the mysql stuff off of /mnt -> mysql_dir_root
366
+ stop rescue nil #already stopped
367
+ sudo "mkdir -p #{mysql_dir_root}/log"
368
+ #move the data over, but keep a symlink to the new location for backwards compatibility
369
+ #and do not do it if /mnt/mysql_data has already been moved
370
+ quiet_capture("sudo sh -c 'test ! -d #{mysql_dir_root}/mysql_data && mv /mnt/mysql_data #{mysql_dir_root}/'")
371
+ sudo "mv /mnt/mysql_data /mnt/mysql_data_old 2>/dev/null || echo"
372
+ sudo "ln -fs #{mysql_dir_root}/mysql_data /mnt/mysql_data"
373
+
374
+ #but keep the tmpdir on mnt
375
+ sudo "sh -c 'mkdir -p /mnt/tmp/mysql && chown mysql:mysql /mnt/tmp/mysql'"
376
+ #move the logs over, but keep a symlink to the new location for backwards compatibility
377
+ #and do not do it if the logs have already been moved
378
+ quiet_capture("sudo sh -c 'test ! -d #{mysql_dir_root}/log/mysql_data && mv /mnt/log/mysql #{mysql_dir_root}/log/'")
379
+ sudo "ln -fs #{mysql_dir_root}/log/mysql /mnt/log/mysql"
380
+ quiet_capture("sudo sh -c \"test -f #{mysql_dir_root}/log/mysql/mysql-bin.index && \
381
+ perl -pi -e 's%/mnt/log/%#{mysql_dir_root}/log/%' #{mysql_dir_root}/log/mysql/mysql-bin.index\"") rescue false
382
+
383
+ if quiet_capture("test -d /var/local/etc/mysql && echo 'yes'").empty?
384
+ txt = <<-FILE
385
+ [mysqld]
386
+ datadir = #{mysql_dir_root}/mysql_data
387
+ tmpdir = /mnt/tmp/mysql
388
+ log_bin = #{mysql_dir_root}/log/mysql/mysql-bin.log
389
+ log_slow_queries = #{mysql_dir_root}/log/mysql/mysql-slow.log
390
+ FILE
391
+ put txt, '/tmp/mysql-ec2-ebs.cnf'
392
+ sudo 'mv /tmp/mysql-ec2-ebs.cnf /etc/mysql/conf.d/mysql-ec2-ebs.cnf'
393
+
394
+ #keep a copy
395
+ sudo "rsync -aR /etc/mysql #{mysql_dir_root}/"
396
+ end
397
+ # lets use the mysql configs on the EBS volume
398
+ sudo "mv /etc/mysql /etc/mysql.orig 2>/dev/null"
399
+ sudo "ln -sf #{mysql_dir_root}/etc/mysql /etc/mysql"
400
+
401
+ #just put a README on the drive so we know what this volume is for!
402
+ txt = <<-FILE
403
+ This volume is setup to be used by Ec2onRails in conjunction with Amazon's EBS, for primary MySql database persistence.
404
+ RAILS_ENV: #{fetch(:rails_env, 'undefined')}
405
+ DOMAIN: #{fetch(:domain, 'undefined')}
406
+
407
+ Modify this volume at your own risk
408
+ FILE
409
+
410
+ put txt, "/tmp/VOLUME-README"
411
+ sudo "mv /tmp/VOLUME-README #{mysql_dir_root}/VOLUME-README"
412
+ #update the list of ebs volumes
413
+ #TODO: abstract this away into a helper method!!
414
+ #TODO: this first touch should *not* be needed... quiet_capture should return an empty string
415
+ # if the cat on a non-existant file fails (as it should). this isn't causing issues
416
+ # for me, but a few users have complained.... bad gemspec or something?
417
+ # COMMENTING OUT for now to see if the recent gemspec update improved things...
418
+ # ebs_info = quiet_capture("touch /etc/ec2onrails/ebs_info.yml")
419
+ ebs_info = quiet_capture("cat /etc/ec2onrails/ebs_info.yml")
420
+ ebs_info = ebs_info.empty? ? {} : YAML::load(ebs_info)
421
+ ebs_info[mysql_dir_root] = {'block_loc' => block_mnt, 'volume_id' => vol_id}
422
+ put(ebs_info.to_yaml, "/tmp/ebs_info.yml")
423
+ sudo "mv /tmp/ebs_info.yml /etc/ec2onrails/ebs_info.yml"
424
+ #lets start it back up
425
+ start
426
+ end #end of sudo
427
+ end
428
+ end
429
+
430
+
431
+ desc <<-DESC
432
+ [internal] Make sure the MySQL server has been started, just in case the db role
433
+ hasn't been set, e.g. when called from ec2onrails:setup.
434
+ (But don't enable monitoring on it.)
435
+ DESC
436
+ task :start, :roles => :db do
437
+ sudo "god start db"
438
+ # sudo "god monitor db"
439
+ end
440
+
441
+ task :stop, :roles => :db do
442
+ # sudo "god unmonitor db"
443
+ sudo "god stop db"
444
+ end
445
+
446
+
447
+ desc <<-DESC
448
+ Drop the MySQL database. Assumes there is no MySQL root \
449
+ password. If there is a MySQL root password, create a task that removes \
450
+ it and run that task before this one using a before hook.
451
+ DESC
452
+ task :drop, :roles => :db do
453
+ load_config
454
+ run %{mysql -u root -e "drop database if exists \\`#{cfg[:db_name]}\\`;"}
455
+ end
456
+
457
+ desc <<-DESC
458
+ db:drop and db:create.
459
+ DESC
460
+ task :recreate, :roles => :db do
461
+ drop
462
+ create
463
+ end
464
+
465
+ desc <<-DESC
466
+ Set a root password for MySQL, using the variable mysql_root_password \
467
+ if it is set. If this is done db:drop won't work.
468
+ DESC
469
+ task :set_root_password, :roles => :db do
470
+ if cfg[:mysql_root_password]
471
+ run %{mysql -u root -e "UPDATE mysql.user SET Password=PASSWORD('#{cfg[:mysql_root_password]}') WHERE User='root'; FLUSH PRIVILEGES;"}
472
+ end
473
+ end
474
+
475
+ desc <<-DESC
476
+ Dump the MySQL database to the S3 bucket specified by \
477
+ ec2onrails_config[:archive_to_bucket]. The filename will be \
478
+ "database-archive/<timestamp>/dump.sql.gz".
479
+ DESC
480
+ task :archive, :roles => :db do
481
+ run "/usr/local/ec2onrails/bin/backup_app_db.rb --bucket #{cfg[:archive_to_bucket]} --dir #{cfg[:archive_to_bucket_subdir]}"
482
+ end
483
+
484
+ desc <<-DESC
485
+ Restore the MySQL database from the S3 bucket specified by \
486
+ ec2onrails_config[:restore_from_bucket]. The archive filename is \
487
+ expected to be the default, "mysqldump.sql.gz".
488
+ DESC
489
+ task :restore, :roles => :db do
490
+ run "/usr/local/ec2onrails/bin/restore_app_db.rb --bucket #{cfg[:restore_from_bucket]} --dir #{cfg[:restore_from_bucket_subdir]}"
491
+ end
492
+
493
+ desc <<-DESC
494
+ [internal] Initialize the default backup folder on S3 (i.e. do a full
495
+ backup of the newly-created db so the automatic incremental backups
496
+ make sense).
497
+ DESC
498
+ task :init_backup, :roles => :db do
499
+ server.allow_sudo do
500
+ sudo "/usr/local/ec2onrails/bin/backup_app_db.rb --reset"
501
+ end
502
+ end
503
+
504
+ # do NOT run if the flag does not exist. This is placed by a startup script
505
+ # and it is only run on the first-startup. This means after the db has been
506
+ # optimized, this task will not work again.
507
+ #
508
+ # Of course you can overload it or call the file directly
509
+ task :optimize, :roles => :db do
510
+ if !quiet_capture("test -e /tmp/optimize_db_flag && echo 'file exists'").empty?
511
+ begin
512
+ sudo "/usr/local/ec2onrails/bin/optimize_mysql.rb"
513
+ ensure
514
+ sudo "rm -rf /tmp/optimize_db_flag" #remove so we cannot run again
515
+ end
516
+ else
517
+ puts "skipping as it looks like this task has already been run"
518
+ end
519
+ end
520
+
521
+ end
522
+
523
+ namespace :server do
524
+ desc <<-DESC
525
+ Tell the servers what roles they are in. This configures them with \
526
+ the appropriate settings for each role, and starts and/or stops the \
527
+ relevant services.
528
+ DESC
529
+ task :set_roles do
530
+ # TODO generate this based on the roles that actually exist so arbitrary new ones can be added
531
+ roles = {
532
+ :web => hostnames_for_role(:web),
533
+ :app => hostnames_for_role(:app),
534
+ :db_primary => hostnames_for_role(:db, :primary => true),
535
+ # doing th ebelow can cause errors elsewhere unless :db is populated.
536
+ # :db => hostnames_for_role(:db),
537
+ :memcache => hostnames_for_role(:memcache)
538
+ }
539
+ roles_yml = YAML::dump(roles)
540
+ put roles_yml, "/tmp/roles.yml"
541
+ server.allow_sudo do
542
+ sudo "cp /tmp/roles.yml /etc/ec2onrails"
543
+ #we want everyone to be able to read to it
544
+ sudo "chmod a+r /etc/ec2onrails/roles.yml"
545
+ sudo "/usr/local/ec2onrails/bin/set_roles.rb"
546
+ end
547
+ end
548
+
549
+ task :init_services do
550
+ server.allow_sudo do
551
+ sudo "/usr/local/ec2onrails/bin/init_services.rb"
552
+ end
553
+ end
554
+
555
+ task :setup_web_proxy, :roles => :web do
556
+ sudo "/usr/local/ec2onrails/bin/setup_web_proxy.rb --mode #{cfg[:web_proxy_server].to_s}"
557
+ end
558
+
559
+ desc <<-DESC
560
+ Change the default value of RAILS_ENV on the server. Technically
561
+ this changes the server's mongrel config to use a different value
562
+ for "environment". The value is specified in :rails_env.
563
+ Be sure to do deploy:restart after this.
564
+ DESC
565
+ task :set_rails_env do
566
+ rails_env = fetch(:rails_env, "production")
567
+ sudo "/usr/local/ec2onrails/bin/set_rails_env #{rails_env}"
568
+ end
569
+
570
+ desc <<-DESC
571
+ Upgrade to the newest versions of all Ubuntu packages.
572
+ DESC
573
+ task :upgrade_packages do
574
+ sudo "aptitude -q update"
575
+ sudo "sh -c 'export DEBIAN_FRONTEND=noninteractive; aptitude -q -y safe-upgrade'"
576
+ end
577
+
578
+ desc <<-DESC
579
+ Upgrade to the newest versions of all rubygems.
580
+ DESC
581
+ task :upgrade_gems do
582
+ sudo "gem update --system --no-rdoc --no-ri"
583
+ sudo "gem update --no-rdoc --no-ri" do |ch, str, data|
584
+ ch[:data] ||= ""
585
+ ch[:data] << data
586
+ if data =~ />\s*$/
587
+ puts data
588
+ choice = Capistrano::CLI.ui.ask("The gem command is asking for a number:")
589
+ ch.send_data("#{choice}\n")
590
+ else
591
+ puts data
592
+ end
593
+ end
594
+ end
595
+
596
+ desc <<-DESC
597
+ Install extra Ubuntu packages. Set ec2onrails_config[:packages], it \
598
+ should be an array of strings.
599
+ NOTE: the package installation will be non-interactive, if the packages \
600
+ require configuration either set ec2onrails_config[:interactive_packages] \
601
+ like you would for ec2onrails_config[:packages] (we'll flood the server \
602
+ with 'Y' inputs), or log in as 'root' and run \
603
+ 'dpkg-reconfigure packagename' or replace the package's config files \
604
+ using the 'ec2onrails:server:deploy_files' task.
605
+ DESC
606
+ task :install_packages do
607
+ sudo "aptitude -q update"
608
+ if cfg[:packages] && cfg[:packages].any?
609
+ sudo "sh -c 'export DEBIAN_FRONTEND=noninteractive; aptitude -q -y install #{cfg[:packages].join(' ')}'"
610
+ end
611
+ if cfg[:interactive_packages] && cfg[:interactive_packages].any?
612
+ # sudo "aptitude install #{cfg[:interactive_packages].join(' ')}", {:env => {'DEBIAN_FRONTEND' => 'readline'} }
613
+ #trying to pick WHEN to send a Y is a bit tricky...it totally depends on the
614
+ #interactive package you want to install. FLOODING it with 'Y'... but not sure how
615
+ #'correct' or robust this is
616
+ cmd = "sudo sh -c 'export DEBIAN_FRONTEND=readline; aptitude -y -q install #{cfg[:interactive_packages].join(' ')}'"
617
+ run(cmd) do |channel, stream, data|
618
+ channel.send_data "Y\n"
619
+ end
620
+ end
621
+ end
622
+
623
+ desc <<-DESC
624
+ Provide extra security measures. Set ec2onrails_config[:harden_server] = true \
625
+ to allow the hardening of the server.
626
+ These security measures are those which can make initial setup and playing around
627
+ with Ec2onRails tricky. For example, you can be logged out of your server forever
628
+ DESC
629
+ task :harden_server do
630
+ #NOTES: for those security features that will get in the way of ease-of-use
631
+ # hook them in here
632
+ if cfg[:harden_server]
633
+ #lets install some extra packages:
634
+ # denyhosts: sshd security tool. config file is already installed...
635
+ #
636
+ security_pkgs = %w{denyhosts}
637
+ sudo "sh -c 'export DEBIAN_FRONTEND=noninteractive; aptitude -q -y install #{security_pkgs.join(' ')}'"
638
+ end
639
+ end
640
+
641
+ desc <<-DESC
642
+ Install extra rubygems. Set ec2onrails_config[:rubygems], it should \
643
+ be with an array of strings.
644
+ DESC
645
+ task :install_gems do
646
+ if cfg[:rubygems]
647
+ cfg[:rubygems].each do |gem|
648
+ sudo "gem install #{gem} --no-rdoc --no-ri" do |ch, str, data|
649
+ ch[:data] ||= ""
650
+ ch[:data] << data
651
+ if data =~ />\s*$/
652
+ puts data
653
+ choice = Capistrano::CLI.ui.ask("The gem command is asking for a number:")
654
+ ch.send_data("#{choice}\n")
655
+ else
656
+ puts data
657
+ end
658
+ end
659
+ end
660
+ end
661
+ end
662
+
663
+ task :run_rails_rake_gems_install do
664
+ #if running under Rails 2.1, lets trigger 'rake gems:install', but in such a way
665
+ #so it fails gracefully if running rails < 2.1
666
+ # ALSO, this might be the first time rake is run, and running it as sudo means that
667
+ # if any plugins are loaded and create directories... like what image_science does for
668
+ # ruby_inline, then the dirs will be created as root. so trigger the rails loading
669
+ # very quickly before the sudo is called
670
+ # run "cd #{release_path} && rake RAILS_ENV=#{rails_env} -T 1>/dev/null && sudo rake RAILS_ENV=#{rails_env} gems:install"
671
+ ec2onrails.server.allow_sudo do
672
+ output = quiet_capture "cd #{release_path} && rake RAILS_ENV=#{rails_env} db:version 2>&1 1>/dev/null || sudo rake RAILS_ENV=#{rails_env} gems:install"
673
+ puts output
674
+ end
675
+ end
676
+
677
+ desc <<-DESC
678
+ Add extra gem sources to rubygems (to able to fetch gems from for example gems.github.com).
679
+ Set ec2onrails_config[:rubygems_sources], it should be with an array of strings.
680
+ DESC
681
+ task :add_gem_sources do
682
+ if cfg[:rubygems_sources]
683
+ cfg[:rubygems_sources].each do |gem_source|
684
+ sudo "gem sources -a #{gem_source}"
685
+ end
686
+ end
687
+ end
688
+
689
+ desc <<-DESC
690
+ A convenience task to upgrade existing packages and gems and install \
691
+ specified new ones.
692
+ DESC
693
+ task :upgrade_and_install_all do
694
+ upgrade_packages
695
+ upgrade_gems
696
+ install_packages
697
+ install_gems
698
+ end
699
+
700
+ desc <<-DESC
701
+ Set the timezone using the value of the variable named timezone. \
702
+ Valid options for timezone can be determined by the contents of \
703
+ /usr/share/zoneinfo, which can be seen here: \
704
+ http://packages.ubuntu.com/cgi-bin/search_contents.pl?searchmode=filelist&word=tzdata&version=gutsy&arch=all&page=1&number=all \
705
+ Remove 'usr/share/zoneinfo/' from the filename, and use the last \
706
+ directory and file as the value. For example 'Africa/Abidjan' or \
707
+ 'posix/GMT' or 'Canada/Eastern'.
708
+ DESC
709
+ task :set_timezone do
710
+ if cfg[:timezone]
711
+ ec2onrails.server.allow_sudo do
712
+ sudo "bash -c 'echo #{cfg[:timezone]} > /etc/timezone'"
713
+ sudo "cp /usr/share/zoneinfo/#{cfg[:timezone]} /etc/localtime"
714
+ end
715
+ end
716
+ end
717
+
718
+ desc <<-DESC
719
+ Deploy a set of config files to the server, the files will be owned by \
720
+ root. This doesn't delete any files from the server. This is intended
721
+ mainly for customized config files for new packages installed via the \
722
+ ec2onrails:server:install_packages task. Subdirectories and files \
723
+ inside here will be placed within the same directory structure \
724
+ relative to the root of the server's filesystem.
725
+ DESC
726
+ task :deploy_files do
727
+ if cfg[:server_config_files_root]
728
+ begin
729
+ filename = "config_files.tar"
730
+ local_file = "#{Dir.tmpdir}/#{filename}"
731
+ remote_file = "/tmp/#{filename}"
732
+ FileUtils.cd(cfg[:server_config_files_root]) do
733
+ File.open(local_file, 'wb') { |tar| Minitar.pack(".", tar) }
734
+ end
735
+ put File.read(local_file), remote_file
736
+ sudo "tar xvf #{remote_file} -o -C /"
737
+ ensure
738
+ rm_rf local_file
739
+ sudo "rm -f #{remote_file}"
740
+ end
741
+ end
742
+ end
743
+
744
+ desc <<-DESC
745
+ Restart a set of services. Set ec2onrails_config[:services_to_restart] \
746
+ to an array of strings. It's assumed that each service has a script \
747
+ in /etc/init.d
748
+ DESC
749
+ task :restart_services do
750
+ if cfg[:services_to_restart] && cfg[:services_to_restart].any?
751
+ cfg[:services_to_restart].each do |service|
752
+ run_init_script(service, "restart")
753
+ end
754
+ end
755
+ end
756
+
757
+ desc <<-DESC
758
+ Set the email address that mail to the app user forwards to.
759
+ DESC
760
+ task :set_mail_forward_address do
761
+ run "echo '#{cfg[:mail_forward_address]}' >> /home/app/.forward" if cfg[:mail_forward_address]
762
+ # put cfg[:admin_mail_forward_address], "/home/admin/.forward" if cfg[:admin_mail_forward_address]
763
+ end
764
+
765
+ desc <<-DESC
766
+ Enable ssl for the web server. The SSL cert file should be in
767
+ /etc/ssl/certs/default.pem and the SSL key file should be in
768
+ /etc/ssl/private/default.key (use the deploy_files task).
769
+ DESC
770
+ task :enable_ssl, :roles => :web do
771
+ #TODO: enable for nginx
772
+ sudo "a2enmod ssl"
773
+ sudo "a2enmod headers" # the headers module is necessary to forward a header so that rails can detect it is handling an SSL connection. NPG 7/11/08
774
+ sudo "a2ensite default-ssl"
775
+ run_init_script("web_proxy", "restart")
776
+ end
777
+
778
+ desc <<-DESC
779
+ Restrict the main user's sudo access.
780
+ Defaults the user to only be able to \
781
+ sudo to god
782
+ DESC
783
+ task :restrict_sudo_access do
784
+ old_user = fetch(:user)
785
+ begin
786
+ set :user, 'root'
787
+ sessions.clear #clear out sessions cache..... this way the ssh connections are reinitialized
788
+ sudo "cp -f /etc/sudoers.restricted_access /etc/sudoers"
789
+ # run "ln -sf /etc/sudoers.restricted_access /etc/sudoers"
790
+ ensure
791
+ set :user, old_user
792
+ sessions.clear
793
+ end
794
+ end
795
+
796
+ desc <<-DESC
797
+ Grant *FULL* sudo access to the main user.
798
+ DESC
799
+ task :grant_sudo_access do
800
+ allow_sudo
801
+ end
802
+
803
+ @within_sudo = 0
804
+ def allow_sudo
805
+ begin
806
+ @within_sudo += 1
807
+ old_user = fetch(:user)
808
+ if @within_sudo > 1
809
+ yield if block_given?
810
+ true
811
+ elsif capture("ls -l /etc/sudoers /etc/sudoers.full_access | awk '{print $5}'").split.uniq.size == 1
812
+ yield if block_given?
813
+ false
814
+ else
815
+ begin
816
+ # need to cheet and temporarily set the user to ROOT so we
817
+ # can (re)grant full sudo access.
818
+ # we can do this because the root and app user have the same
819
+ # ssh login preferences....
820
+ #
821
+ # TODO:
822
+ # do not escalate priv. to root...use another user like 'admin' that has full sudo access
823
+ set :user, 'root'
824
+ sessions.clear #clear out sessions cache..... this way the ssh connections are reinitialized
825
+ run "cp -f /etc/sudoers.full_access /etc/sudoers"
826
+ set :user, old_user
827
+ sessions.clear
828
+ yield if block_given?
829
+ ensure
830
+ server.restrict_sudo_access if block_given?
831
+ set :user, old_user
832
+ sessions.clear
833
+ true
834
+ end
835
+ end
836
+ ensure
837
+ @within_sudo -= 1
838
+ end
839
+ end
840
+ end
841
+
842
+ end
843
+ end
844
+