ScholarNexus-ec2onrails 0.9.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. data/CHANGELOG +180 -0
  2. data/COPYING +339 -0
  3. data/Manifest +167 -0
  4. data/README.textile +211 -0
  5. data/Rakefile +37 -0
  6. data/TODO +104 -0
  7. data/ec2onrails.gemspec +42 -0
  8. data/examples/Capfile +3 -0
  9. data/examples/deploy.rb +107 -0
  10. data/examples/s3.yml +9 -0
  11. data/lib/ec2onrails/capistrano_utils.rb +43 -0
  12. data/lib/ec2onrails/recipes/db.rb +359 -0
  13. data/lib/ec2onrails/recipes/deploy.rb +30 -0
  14. data/lib/ec2onrails/recipes/server.rb +489 -0
  15. data/lib/ec2onrails/recipes.rb +141 -0
  16. data/lib/ec2onrails/version.rb +31 -0
  17. data/lib/ec2onrails.rb +20 -0
  18. data/server/build-ec2onrails.sh +44 -0
  19. data/server/files/etc/aliases +5 -0
  20. data/server/files/etc/aliases.db +0 -0
  21. data/server/files/etc/apache2/apache2.conf +295 -0
  22. data/server/files/etc/apache2/conf.d/app.proxy_cluster.conf +7 -0
  23. data/server/files/etc/apache2/conf.d/app.proxy_frontend.conf +10 -0
  24. data/server/files/etc/apache2/mods-available/proxy.conf +18 -0
  25. data/server/files/etc/apache2/sites-available/app.common +61 -0
  26. data/server/files/etc/apache2/sites-available/app.custom +0 -0
  27. data/server/files/etc/apache2/sites-available/default +14 -0
  28. data/server/files/etc/apache2/sites-available/default-ssl +19 -0
  29. data/server/files/etc/cron.d/ec2onrails +21 -0
  30. data/server/files/etc/cron.daily/app +24 -0
  31. data/server/files/etc/cron.daily/logrotate_post +19 -0
  32. data/server/files/etc/cron.hourly/app +24 -0
  33. data/server/files/etc/cron.monthly/app +24 -0
  34. data/server/files/etc/cron.weekly/app +24 -0
  35. data/server/files/etc/denyhosts.conf +628 -0
  36. data/server/files/etc/dpkg/dpkg.cfg +13 -0
  37. data/server/files/etc/ec2onrails/README +32 -0
  38. data/server/files/etc/ec2onrails/balancer_members +6 -0
  39. data/server/files/etc/ec2onrails/roles.yml +5 -0
  40. data/server/files/etc/environment +2 -0
  41. data/server/files/etc/god/app.god +40 -0
  42. data/server/files/etc/god/db.god +17 -0
  43. data/server/files/etc/god/dkim_filter.god +20 -0
  44. data/server/files/etc/god/examples/have_god_daemonize.god +18 -0
  45. data/server/files/etc/god/master.conf +35 -0
  46. data/server/files/etc/god/memcache.god +15 -0
  47. data/server/files/etc/god/notifications.god +14 -0
  48. data/server/files/etc/god/system.god +34 -0
  49. data/server/files/etc/god/web.god +38 -0
  50. data/server/files/etc/init.d/ec2-every-startup +29 -0
  51. data/server/files/etc/init.d/ec2-first-startup +36 -0
  52. data/server/files/etc/init.d/god +42 -0
  53. data/server/files/etc/init.d/nginx +78 -0
  54. data/server/files/etc/init.d/set_roles +3 -0
  55. data/server/files/etc/logrotate.d/apache2 +16 -0
  56. data/server/files/etc/logrotate.d/mongrel +11 -0
  57. data/server/files/etc/logrotate.d/nginx +11 -0
  58. data/server/files/etc/memcached.conf +47 -0
  59. data/server/files/etc/mongrel_cluster/app.yml +9 -0
  60. data/server/files/etc/motd.tail +13 -0
  61. data/server/files/etc/mysql/my.cnf +152 -0
  62. data/server/files/etc/nginx/nginx.conf +305 -0
  63. data/server/files/etc/postfix/main.cf +4 -0
  64. data/server/files/etc/rcS.d/S91ec2-first-startup +1 -0
  65. data/server/files/etc/rcS.d/S92ec2-every-startup +1 -0
  66. data/server/files/etc/rcS.d/S99set_roles +1 -0
  67. data/server/files/etc/ssh/sshd_config +94 -0
  68. data/server/files/etc/sudoers +1 -0
  69. data/server/files/etc/sudoers.full_access +26 -0
  70. data/server/files/etc/sudoers.restricted_access +28 -0
  71. data/server/files/etc/syslog.conf +69 -0
  72. data/server/files/usr/bin/god +26 -0
  73. data/server/files/usr/local/ec2onrails/COPYING +339 -0
  74. data/server/files/usr/local/ec2onrails/bin/archive_file.rb +44 -0
  75. data/server/files/usr/local/ec2onrails/bin/backup_app_db.rb +159 -0
  76. data/server/files/usr/local/ec2onrails/bin/ec2_meta_data.rb +80 -0
  77. data/server/files/usr/local/ec2onrails/bin/exec_runner +76 -0
  78. data/server/files/usr/local/ec2onrails/bin/init_services.rb +71 -0
  79. data/server/files/usr/local/ec2onrails/bin/optimize_mysql.rb +348 -0
  80. data/server/files/usr/local/ec2onrails/bin/rails_env +34 -0
  81. data/server/files/usr/local/ec2onrails/bin/rebundle.sh +70 -0
  82. data/server/files/usr/local/ec2onrails/bin/restore_app_db.rb +58 -0
  83. data/server/files/usr/local/ec2onrails/bin/set_rails_env +40 -0
  84. data/server/files/usr/local/ec2onrails/bin/set_roles.rb +87 -0
  85. data/server/files/usr/local/ec2onrails/bin/setup_web_proxy.rb +113 -0
  86. data/server/files/usr/local/ec2onrails/bin/update_hostname +40 -0
  87. data/server/files/usr/local/ec2onrails/config +30 -0
  88. data/server/files/usr/local/ec2onrails/lib/aws_helper.rb +76 -0
  89. data/server/files/usr/local/ec2onrails/lib/god_helper.rb +129 -0
  90. data/server/files/usr/local/ec2onrails/lib/god_patch.rb +43 -0
  91. data/server/files/usr/local/ec2onrails/lib/mysql_helper.rb +101 -0
  92. data/server/files/usr/local/ec2onrails/lib/roles_helper.rb +151 -0
  93. data/server/files/usr/local/ec2onrails/lib/s3_helper.rb +99 -0
  94. data/server/files/usr/local/ec2onrails/lib/utils.rb +16 -0
  95. data/server/files/usr/local/ec2onrails/lib/vendor/ini.rb +268 -0
  96. data/server/files/usr/local/ec2onrails/startup-scripts/every-startup/get-hostname.sh +23 -0
  97. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/README +5 -0
  98. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/create-dirs.sh +39 -0
  99. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/generate-default-web-cert-and-key.sh +49 -0
  100. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/misc.sh +27 -0
  101. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/prepare-mysql-data-dir.sh +24 -0
  102. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/setup-credentials.sh +29 -0
  103. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/setup-file-permissions.sh +30 -0
  104. data/server/rakefile.rb +249 -0
  105. data/setup.rb +1585 -0
  106. data/test/autobench.conf +60 -0
  107. data/test/spec/lib/s3_helper_spec.rb +134 -0
  108. data/test/spec/lib/s3_old.yml +3 -0
  109. data/test/spec/test_files/test1 +0 -0
  110. data/test/spec/test_files/test2 +0 -0
  111. data/test/test_app/Capfile +3 -0
  112. data/test/test_app/README +182 -0
  113. data/test/test_app/Rakefile +10 -0
  114. data/test/test_app/app/controllers/application.rb +7 -0
  115. data/test/test_app/app/controllers/db_fast_controller.rb +6 -0
  116. data/test/test_app/app/controllers/fast_controller.rb +5 -0
  117. data/test/test_app/app/controllers/slow_controller.rb +6 -0
  118. data/test/test_app/app/controllers/very_slow_controller.rb +6 -0
  119. data/test/test_app/app/helpers/application_helper.rb +3 -0
  120. data/test/test_app/app/helpers/db_fast_helper.rb +2 -0
  121. data/test/test_app/app/helpers/fast_helper.rb +2 -0
  122. data/test/test_app/app/helpers/slow_helper.rb +2 -0
  123. data/test/test_app/app/helpers/very_slow_helper.rb +2 -0
  124. data/test/test_app/config/boot.rb +109 -0
  125. data/test/test_app/config/database.yml +19 -0
  126. data/test/test_app/config/deploy.rb +21 -0
  127. data/test/test_app/config/environment.rb +60 -0
  128. data/test/test_app/config/environments/development.rb +21 -0
  129. data/test/test_app/config/environments/production.rb +18 -0
  130. data/test/test_app/config/environments/test.rb +19 -0
  131. data/test/test_app/config/routes.rb +27 -0
  132. data/test/test_app/db/schema.rb +7 -0
  133. data/test/test_app/doc/README_FOR_APP +2 -0
  134. data/test/test_app/public/404.html +30 -0
  135. data/test/test_app/public/500.html +30 -0
  136. data/test/test_app/public/dispatch.cgi +10 -0
  137. data/test/test_app/public/dispatch.fcgi +24 -0
  138. data/test/test_app/public/dispatch.rb +10 -0
  139. data/test/test_app/public/favicon.ico +0 -0
  140. data/test/test_app/public/images/rails.png +0 -0
  141. data/test/test_app/public/javascripts/application.js +2 -0
  142. data/test/test_app/public/javascripts/controls.js +963 -0
  143. data/test/test_app/public/javascripts/dragdrop.js +972 -0
  144. data/test/test_app/public/javascripts/effects.js +1120 -0
  145. data/test/test_app/public/javascripts/prototype.js +4225 -0
  146. data/test/test_app/public/robots.txt +1 -0
  147. data/test/test_app/script/about +3 -0
  148. data/test/test_app/script/breakpointer +3 -0
  149. data/test/test_app/script/console +3 -0
  150. data/test/test_app/script/destroy +3 -0
  151. data/test/test_app/script/generate +3 -0
  152. data/test/test_app/script/performance/benchmarker +3 -0
  153. data/test/test_app/script/performance/profiler +3 -0
  154. data/test/test_app/script/performance/request +3 -0
  155. data/test/test_app/script/plugin +3 -0
  156. data/test/test_app/script/process/inspector +3 -0
  157. data/test/test_app/script/process/reaper +3 -0
  158. data/test/test_app/script/process/spawner +3 -0
  159. data/test/test_app/script/runner +3 -0
  160. data/test/test_app/script/server +3 -0
  161. data/test/test_app/test/functional/db_fast_controller_test.rb +18 -0
  162. data/test/test_app/test/functional/fast_controller_test.rb +18 -0
  163. data/test/test_app/test/functional/slow_controller_test.rb +18 -0
  164. data/test/test_app/test/functional/very_slow_controller_test.rb +18 -0
  165. data/test/test_app/test/test_helper.rb +28 -0
  166. data/test/test_ec2onrails.rb +11 -0
  167. data/test/test_helper.rb +2 -0
  168. metadata +277 -0
@@ -0,0 +1,489 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ cfg = ec2onrails_config
3
+
4
+ namespace :ec2onrails do
5
+ namespace :server do
6
+ desc <<-DESC
7
+ Tell the servers what roles they are in. This configures them with \
8
+ the appropriate settings for each role, and starts and/or stops the \
9
+ relevant services.
10
+ DESC
11
+ task :set_roles do
12
+ # TODO generate this based on the roles that actually exist so arbitrary new ones can be added
13
+ # user_defined_roles = roles
14
+ # roles.each do |k,v|
15
+ # puts "#{k}, #{v.servers.first.options.inspect}"
16
+ # {:primary=>true}
17
+ #
18
+ # end
19
+ #
20
+ roles = {
21
+ :web => hostnames_for_role(:web),
22
+ :app => hostnames_for_role(:app),
23
+ :db_primary => hostnames_for_role(:db, :primary => true),
24
+ # doing th ebelow can cause errors elsewhere unless :db is populated.
25
+ # :db => hostnames_for_role(:db),
26
+ :memcache => hostnames_for_role(:memcache)
27
+ }
28
+ roles_yml = YAML::dump(roles)
29
+ put roles_yml, "/tmp/roles.yml"
30
+ server.allow_sudo do
31
+ sudo "cp /tmp/roles.yml /etc/ec2onrails"
32
+ #we want everyone to be able to read to it
33
+ sudo "chmod a+r /etc/ec2onrails/roles.yml"
34
+ sudo "/usr/local/ec2onrails/bin/set_roles.rb"
35
+ end
36
+ end
37
+
38
+ task :init_services do
39
+ server.allow_sudo do
40
+ #lets pick up the new configuration files
41
+ sudo "/usr/local/ec2onrails/bin/init_services.rb"
42
+ end
43
+ end
44
+
45
+ task :setup_web_proxy, :roles => :web do
46
+ sudo "/usr/local/ec2onrails/bin/setup_web_proxy.rb --mode #{cfg[:web_proxy_server].to_s}"
47
+ end
48
+
49
+ task :setup_elastic_ip, :roles => :web do
50
+ #TODO: for elastic IP
51
+ # * make sure the hostname is reset on the web server
52
+ # * make sure the roles.yml file is updated for ALL servers....
53
+ vol_id = ENV['ELASTIC_IP'] || servers.first.options[:elastic_ip]
54
+ ec2onrails.server.allow_sudo do
55
+ server.set_roles
56
+ end
57
+ end
58
+
59
+ desc <<-DESC
60
+ Change the default value of RAILS_ENV on the server. Technically
61
+ this changes the server's mongrel config to use a different value
62
+ for "environment". The value is specified in :rails_env.
63
+ Be sure to do deploy:restart after this.
64
+ DESC
65
+ task :set_rails_env do
66
+ rails_env = fetch(:rails_env, "production")
67
+ sudo "/usr/local/ec2onrails/bin/set_rails_env #{rails_env}"
68
+ end
69
+
70
+ desc <<-DESC
71
+ Upgrade to the newest versions of all Ubuntu packages.
72
+ DESC
73
+ task :upgrade_packages do
74
+ sudo "aptitude -q update"
75
+ sudo "sh -c 'export DEBIAN_FRONTEND=noninteractive; aptitude -q -y safe-upgrade'"
76
+ end
77
+
78
+ desc <<-DESC
79
+ Upgrade to the newest versions of all rubygems.
80
+ DESC
81
+ task :upgrade_gems do
82
+ sudo "gem update --system --no-rdoc --no-ri"
83
+ sudo "gem update --no-rdoc --no-ri" do |ch, str, data|
84
+ ch[:data] ||= ""
85
+ ch[:data] << data
86
+ if data =~ />\s*$/
87
+ puts data
88
+ choice = Capistrano::CLI.ui.ask("The gem command is asking for a number:")
89
+ ch.send_data("#{choice}\n")
90
+ else
91
+ puts data
92
+ end
93
+ end
94
+ end
95
+
96
+ desc <<-DESC
97
+ Install extra Ubuntu packages. Set ec2onrails_config[:packages], it \
98
+ should be an array of strings.
99
+ NOTE: the package installation will be non-interactive, if the packages \
100
+ require configuration either set ec2onrails_config[:interactive_packages] \
101
+ like you would for ec2onrails_config[:packages] (we'll flood the server \
102
+ with 'Y' inputs), or log in as 'root' and run \
103
+ 'dpkg-reconfigure packagename' or replace the package's config files \
104
+ using the 'ec2onrails:server:deploy_files' task.
105
+ DESC
106
+ task :install_packages do
107
+ ec2onrails.server.allow_sudo do
108
+ sudo "aptitude -q update"
109
+ if cfg[:packages] && cfg[:packages].any?
110
+ sudo "sh -c 'export DEBIAN_FRONTEND=noninteractive; aptitude -q -y install #{cfg[:packages].join(' ')}'"
111
+ end
112
+ if cfg[:interactive_packages] && cfg[:interactive_packages].any?
113
+ # sudo "aptitude install #{cfg[:interactive_packages].join(' ')}", {:env => {'DEBIAN_FRONTEND' => 'readline'} }
114
+ #trying to pick WHEN to send a Y is a bit tricky...it totally depends on the
115
+ #interactive package you want to install. FLOODING it with 'Y'... but not sure how
116
+ #'correct' or robust this is
117
+ cmd = "sudo sh -c 'export DEBIAN_FRONTEND=readline; aptitude -y -q install #{cfg[:interactive_packages].join(' ')}'"
118
+ run(cmd) do |channel, stream, data|
119
+ channel.send_data "Y\n"
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ task :configure_firewall do
126
+ # TODO
127
+ end
128
+
129
+
130
+ desc <<-DESC
131
+ Provide extra security measures. Set ec2onrails_config[:harden_server] = true \
132
+ to allow the hardening of the server.
133
+ These security measures are those which can make initial setup and playing around
134
+ with Ec2onRails tricky. For example, you can be logged out of your server forever
135
+ DESC
136
+ task :harden_server do
137
+ #NOTES: for those security features that will get in the way of ease-of-use
138
+ # hook them in here
139
+ # Like encrypting the mnt directory
140
+ # http://groups.google.com/group/ec2ubuntu/web/encrypting-mnt-using-cryptsetup-on-ubuntu-7-10-gutsy-on-amazon-ec2
141
+ if cfg[:harden_server]
142
+ #lets install some extra packages:
143
+ # denyhosts: sshd security tool. config file is already installed...
144
+ #
145
+ security_pkgs = %w{denyhosts}
146
+ sudo "sh -c 'export DEBIAN_FRONTEND=noninteractive; aptitude -q -y install #{security_pkgs.join(' ')}'"
147
+
148
+ #lets setup dkim
149
+ setup_email_signing
150
+ end
151
+ end
152
+
153
+ #based on the recipe here (but which is missing a few key steps!)
154
+ #http://www.howtoforge.com/quick-and-easy-setup-for-domainkeys-using-ubuntu-postfix-and-dkim-filter
155
+ desc <<-DESC
156
+ enables dkim signing of outgoing msgs. This helps with fightint spam.
157
+ You'll have to update your dns records to take advantage of this, but we'll
158
+ help you out with that
159
+ NOTE: set ec2onrails_config[:service_domain] = 'yourdomain.com' before running this task
160
+ DESC
161
+ task :setup_email_signing, :roles => :app do
162
+ ec2onrails.server.allow_sudo do
163
+ if cfg[:service_domain].nil? || cfg[:service_domain].empty?
164
+ raise "ERROR: missing the :service_domain key. Please set that in your deploy script if you would like to use this task."
165
+ end
166
+
167
+ domain = cfg[:service_domain]
168
+ postmaster_email = "postmaster@#{domain}"
169
+
170
+ #make the selector something that will help us roll over and expire the old key next year
171
+ selector = "mail#{Time.now.year.to_s[-2..-1]}" #ie, mail09
172
+
173
+ sudo "sh -c 'export DEBIAN_FRONTEND=noninteractive; aptitude -q -y install postfix dkim-filter'"
174
+ #do NOT change the size of the key; making it longer can cause problems with some of the dkim implementations
175
+
176
+ keys_exist = File.exist?("config/mail/dkim/dkim_#{selector}.private.key") && File.exist?("config/mail/dkim/dkim_#{selector}.public.key")
177
+
178
+ unless keys_exist
179
+ #lets make them!
180
+ cmds = <<-CMDS
181
+ mkdir -p config/mail/dkim;
182
+ cd config/mail/dkim;
183
+ openssl genrsa -out dkim_#{selector}.private.key 1024;
184
+ openssl rsa -in dkim_#{selector}.private.key -out dkim_#{selector}.public.key -pubout -outform PEM
185
+ CMDS
186
+ system cmds
187
+ end
188
+
189
+ pub_key = File.read("config/mail/dkim/dkim_#{selector}.public.key")
190
+ pub_key = pub_key.split("\n")[1..-2].join(' ')
191
+
192
+ #lets get the private and public keys up to the server
193
+ put File.read("config/mail/dkim/dkim_#{selector}.private.key"), "/tmp/dkim_#{selector}.private.key"
194
+ put File.read("config/mail/dkim/dkim_#{selector}.public.key"), "/tmp/dkim_#{selector}.public.key"
195
+ sudo "mkdir -p /var/dkim-filter"
196
+ sudo "mv /tmp/dkim_#{selector}.p*.key /var/dkim-filter/."
197
+
198
+ #saw a note that Canonicalization relaxed was helpful for rails applications...
199
+ #haven't tested that yet
200
+ dkim_filter_conf = <<-SCRIPT
201
+ # Log to syslog
202
+ Syslog yes
203
+
204
+ # Sign for example.com with key in /etc/mail/dkim.key using
205
+ Domain #{domain}
206
+ KeyFile /var/dkim-filter/dkim_#{selector}.private.key
207
+ Selector #{selector}
208
+
209
+ # Common settings. See dkim-filter.conf(5) for more information.
210
+ AutoRestart no
211
+ Background yes
212
+ SubDomains no
213
+ Canonicalization relaxed
214
+ SCRIPT
215
+
216
+ put dkim_filter_conf, "/tmp/dkim-filter.conf.tmp"
217
+ sudo "mv /etc/dkim-filter.conf /etc/dkim-filter.conf.orig"
218
+ sudo "mv /tmp/dkim-filter.conf.tmp /etc/dkim-filter.conf"
219
+ cmds = <<-CMDS
220
+ sudo postconf -e 'myhostname = #{domain}';
221
+ sudo postconf -e 'mydomain = #{domain}';
222
+ sudo postconf -e 'myorigin = $mydomain';
223
+ sudo postconf -e 'mynetworks_style=subnet';
224
+ sudo postconf -e 'biff = no';
225
+ sudo postconf -e 'alias_maps = hash:/etc/aliases';
226
+ sudo postconf -e 'alias_database = hash:/etc/aliases';
227
+ sudo postconf -e 'mydestination = localdomain, localhost, localhost.localdomain, localhost';
228
+ sudo postconf -e 'relay_domains=$mydestination';
229
+ sudo postconf -e 'mynetworks = 127.0.0.0/8';
230
+ sudo postconf -e 'smtpd_milters = inet:localhost:8891';
231
+ sudo postconf -e 'non_smtpd_milters = inet:localhost:8891';
232
+ sudo postconf -e 'milter_protocol = 2';
233
+ sudo postconf -e 'milter_default_action = accept'
234
+ CMDS
235
+ sudo cmds
236
+
237
+ #lets lock it down
238
+ sudo "chown -R dkim-filter:dkim-filter /var/dkim-filter"
239
+ sudo "chmod 600 /var/dkim-filter/*"
240
+
241
+ puts "*" * 80
242
+ puts "NOTE: you need to do a few things"
243
+ puts " * created public and private DKIM keys to config/mail/dkim_#{selector}.*.key" unless keys_exist
244
+ puts "\n"
245
+ msg = <<-MSG
246
+ * Enter these *TWO* records into your DNS record:
247
+ #{selector}._domainkey.#{domain} IN TXT 'k=rsa; t=y; p=#{pub_key}'
248
+ _domainkey.#{domain} IN TXT 't=y; o=~; r=#{postmaster_email}'
249
+
250
+ I would recommend signing into your ec2 instance and running some test emails. Gmail is very fast in updating their records, but yahoo (as of this writing) is slow and inconsistent. But you can run a command like this to various email address to see how it works:
251
+
252
+ echo 'something searchable so you can find it in your spam filter! did dkim work?' | mail -s "my dkim email; lets see how it went" adam@someservice.com
253
+
254
+
255
+ NOTE: in the near future, when things are looking good, if you take away the 't=y; ' from the above two records, it tells the email services that you are no longer testing the service and to treat your signings with tough love.
256
+
257
+
258
+ MSG
259
+ puts msg
260
+
261
+ #sometimes the dkim-filter restart fails; it seems to be a race condition with some of the postfix changes going in...
262
+ #but a sleep here seems to do the trick.
263
+ sleep(10)
264
+ output = quiet_capture "sudo /etc/init.d/dkim-filter restart"
265
+ if output =~ /smfi_opensocket\(\) failed/
266
+ #ah, if we didn't sleep enough above, lets try it one more time; but this time it will fail if we still get
267
+ #the smfi_opensocket error
268
+ sleep(5)
269
+ sudo "/etc/init.d/dkim-filter restart 2>&1"
270
+ end
271
+ sleep(2)
272
+ sudo "/etc/init.d/postfix restart 2>&1"
273
+ end
274
+
275
+ end
276
+
277
+
278
+ desc <<-DESC
279
+ Install extra rubygems. Set ec2onrails_config[:rubygems], it should \
280
+ be with an array of strings.
281
+ DESC
282
+ task :install_gems do
283
+ if cfg[:rubygems]
284
+ cfg[:rubygems].each do |gem|
285
+ sudo "gem install #{gem} --no-rdoc --no-ri" do |ch, str, data|
286
+ ch[:data] ||= ""
287
+ ch[:data] << data
288
+ if data =~ />\s*$/
289
+ puts data
290
+ choice = Capistrano::CLI.ui.ask("The gem command is asking for a number:")
291
+ ch.send_data("#{choice}\n")
292
+ else
293
+ puts data
294
+ end
295
+ end
296
+ end
297
+ end
298
+ end
299
+
300
+ task :run_rails_rake_gems_install do
301
+ #if running under Rails 2.1, lets trigger 'rake gems:install', but in such a way
302
+ #so it fails gracefully if running rails < 2.1
303
+ # ALSO, this might be the first time rake is run, and running it as sudo means that
304
+ # if any plugins are loaded and create directories... like what image_science does for
305
+ # ruby_inline, then the dirs will be created as root. so trigger the rails loading
306
+ # very quickly before the sudo is called
307
+ # run "cd #{release_path} && rake RAILS_ENV=#{rails_env} -T 1>/dev/null && sudo rake RAILS_ENV=#{rails_env} gems:install"
308
+ ec2onrails.server.allow_sudo do
309
+ 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"
310
+ puts output
311
+ end
312
+ end
313
+
314
+ desc <<-DESC
315
+ Add extra gem sources to rubygems (to able to fetch gems from for example gems.github.com).
316
+ Set ec2onrails_config[:rubygems_sources], it should be with an array of strings.
317
+ DESC
318
+ task :add_gem_sources do
319
+ if cfg[:rubygems_sources]
320
+ cfg[:rubygems_sources].each do |gem_source|
321
+ sudo "gem sources -a #{gem_source}"
322
+ end
323
+ end
324
+ end
325
+
326
+ desc <<-DESC
327
+ A convenience task to upgrade existing packages and gems and install \
328
+ specified new ones.
329
+ DESC
330
+ task :upgrade_and_install_all do
331
+ upgrade_packages
332
+ upgrade_gems
333
+ install_packages
334
+ install_gems
335
+ end
336
+
337
+ desc <<-DESC
338
+ Set the timezone using the value of the variable named timezone. \
339
+ Valid options for timezone can be determined by the contents of \
340
+ /usr/share/zoneinfo, which can be seen here: \
341
+ http://packages.ubuntu.com/cgi-bin/search_contents.pl?searchmode=filelist&word=tzdata&version=gutsy&arch=all&page=1&number=all \
342
+ Remove 'usr/share/zoneinfo/' from the filename, and use the last \
343
+ directory and file as the value. For example 'Africa/Abidjan' or \
344
+ 'posix/GMT' or 'Canada/Eastern'.
345
+ DESC
346
+ task :set_timezone do
347
+ if cfg[:timezone]
348
+ ec2onrails.server.allow_sudo do
349
+ sudo "bash -c 'echo #{cfg[:timezone]} > /etc/timezone'"
350
+ sudo "cp /usr/share/zoneinfo/#{cfg[:timezone]} /etc/localtime"
351
+ end
352
+ end
353
+ end
354
+
355
+ desc <<-DESC
356
+ Deploy a set of config files to the server, the files will be owned by \
357
+ root. This doesn't delete any files from the server. This is intended
358
+ mainly for customized config files for new packages installed via the \
359
+ ec2onrails:server:install_packages task. Subdirectories and files \
360
+ inside here will be placed within the same directory structure \
361
+ relative to the root of the server's filesystem.
362
+ DESC
363
+ task :deploy_files do
364
+ if cfg[:server_config_files_root]
365
+ begin
366
+ filename = "config_files.tar"
367
+ local_file = "#{Dir.tmpdir}/#{filename}"
368
+ remote_file = "/tmp/#{filename}"
369
+ FileUtils.cd(cfg[:server_config_files_root]) do
370
+ File.open(local_file, 'wb') { |tar| Minitar.pack(".", tar) }
371
+ end
372
+ put File.read(local_file), remote_file
373
+ sudo "tar xvf #{remote_file} -o -C /"
374
+ ensure
375
+ rm_rf local_file
376
+ sudo "rm -f #{remote_file}"
377
+ end
378
+ end
379
+ end
380
+
381
+ desc <<-DESC
382
+ Restart a set of services. Set ec2onrails_config[:services_to_restart] \
383
+ to an array of strings. It's assumed that each service has a script \
384
+ in /etc/init.d
385
+ DESC
386
+ task :restart_services do
387
+ if cfg[:services_to_restart] && cfg[:services_to_restart].any?
388
+ cfg[:services_to_restart].each do |service|
389
+ run_init_script(service, "restart")
390
+ end
391
+ end
392
+ end
393
+
394
+ desc <<-DESC
395
+ Set the email address that mail to the app user forwards to.
396
+ DESC
397
+ task :set_mail_forward_address do
398
+ run "echo '#{cfg[:mail_forward_address]}' >> /home/app/.forward" if cfg[:mail_forward_address]
399
+ # put cfg[:admin_mail_forward_address], "/home/admin/.forward" if cfg[:admin_mail_forward_address]
400
+ end
401
+
402
+ desc <<-DESC
403
+ Enable ssl for the web server. The SSL cert file should be in
404
+ /etc/ssl/certs/default.pem and the SSL key file should be in
405
+ /etc/ssl/private/default.key (use the deploy_files task).
406
+ DESC
407
+ task :enable_ssl, :roles => :web do
408
+ #TODO: enable for nginx
409
+ sudo "a2enmod ssl"
410
+ 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
411
+ sudo "a2ensite default-ssl"
412
+ run_init_script("web_proxy", "restart")
413
+ end
414
+
415
+ desc <<-DESC
416
+ Restrict the main user's sudo access.
417
+ Defaults the user to only be able to \
418
+ sudo to god
419
+ DESC
420
+ task :restrict_sudo_access do
421
+ old_user = fetch(:user)
422
+ begin
423
+ set :user, 'root'
424
+ sessions.clear #clear out sessions cache..... this way the ssh connections are reinitialized
425
+
426
+ sudo "test ! -L /etc/sudoers || ( echo 'removing symlink /etc/sudoers' ; unlink /etc/sudoers )"
427
+ sudo "cp -f /etc/sudoers.restricted_access /etc/sudoers && chmod 440 /etc/sudoers"
428
+ # this doesn't work; sudo needs the file to not be a symlink
429
+ # run "ln -sf /etc/sudoers.restricted_access /etc/sudoers"
430
+
431
+ ensure
432
+ set :user, old_user
433
+ sessions.clear
434
+ end
435
+ end
436
+
437
+ desc <<-DESC
438
+ Grant *FULL* sudo access to the main user.
439
+ DESC
440
+ task :grant_sudo_access do
441
+ allow_sudo
442
+ end
443
+
444
+ @within_sudo = 0
445
+ def allow_sudo
446
+ begin
447
+ @within_sudo += 1
448
+ old_user = fetch(:user)
449
+ if @within_sudo > 1
450
+ yield if block_given?
451
+ true
452
+ elsif capture("ls -l /etc/sudoers /etc/sudoers.full_access | awk '{print $5}'").split.uniq.size == 1
453
+ yield if block_given?
454
+ false
455
+ else
456
+ begin
457
+ # need to cheet and temporarily set the user to ROOT so we
458
+ # can (re)grant full sudo access.
459
+ # we can do this because the root and app user have the same
460
+ # ssh login preferences....
461
+ #
462
+ # TODO:
463
+ # do not escalate priv. to root...use another user like 'admin' that has full sudo access
464
+ set :user, 'root'
465
+ sessions.clear #clear out sessions cache..... this way the ssh connections are reinitialized
466
+
467
+
468
+ # note, this approach prevents end users from effectively editing the sudoers file directly :(
469
+ sudo "test ! -L /etc/sudoers || ( echo 'removing symlink /etc/sudoers' ; unlink /etc/sudoers )"
470
+ run "cp /etc/sudoers.full_access /etc/sudoers && chmod 440 /etc/sudoers"
471
+ set :user, old_user
472
+ sessions.clear
473
+ yield if block_given?
474
+ ensure
475
+ server.restrict_sudo_access if block_given?
476
+ set :user, old_user
477
+ sessions.clear
478
+ true
479
+ end
480
+ end
481
+ ensure
482
+ @within_sudo -= 1
483
+ end
484
+ end
485
+ end
486
+
487
+ end
488
+
489
+ end
@@ -0,0 +1,141 @@
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
+
32
+
33
+ Dir[File.join(File.dirname(__FILE__), "recipes/*")].find_all{|x| File.file? x}.each do |recipe|
34
+ require recipe
35
+ end
36
+
37
+
38
+ Capistrano::Configuration.instance.load do
39
+
40
+ unless ec2onrails_config
41
+ raise "ec2onrails_config variable not set. (It should be a hash.)"
42
+ end
43
+
44
+ cfg = ec2onrails_config
45
+
46
+ #:apache or :nginx
47
+ cfg[:web_proxy_server] ||= :apache
48
+
49
+ set :ec2onrails_version, Ec2onrails::VERSION::STRING
50
+ set :image_id_32_bit, Ec2onrails::VERSION::AMI_ID_32_BIT
51
+ set :image_id_64_bit, Ec2onrails::VERSION::AMI_ID_64_BIT
52
+ set :deploy_to, "/mnt/app"
53
+ set :use_sudo, false
54
+ set :user, "app"
55
+
56
+ #in case any changes were made to the configs, like changing the number of mongrels
57
+ before "deploy:cold", "ec2onrails:setup"
58
+
59
+ after "deploy:symlink", "ec2onrails:server:set_roles", "ec2onrails:server:init_services"
60
+ after "deploy:cold", "ec2onrails:db:init_backup", "ec2onrails:db:optimize", "ec2onrails:server:restrict_sudo_access"
61
+ after "ec2onrails:server:install_gems", "ec2onrails:server:add_gem_sources"
62
+
63
+ #NOTE: some default setups (like engineyard's) do some symlinking of config files after
64
+ # deploy:update_code. The ordering here matters as we need to have those symlinks in place
65
+ # but we need to have the gems in place before the rails env is loaded up, or else it will
66
+ # fail. By adding it to the callback queue AFTER all the tasks have loaded up, we make sure
67
+ # it is done at the very end.
68
+ #
69
+ # *IF* you had tasks also triggered after update_code that run rake tasks
70
+ # (like compressing javascript and stylesheets), move those over to before "deploy:symlink"
71
+ # and you'll be set!
72
+ on :load do
73
+ after "deploy:update_code", "ec2onrails:server:run_rails_rake_gems_install"
74
+ end
75
+
76
+
77
+ namespace :ec2onrails do
78
+ desc <<-DESC
79
+ Show the AMI id's of the current images for this version of \
80
+ EC2 on Rails.
81
+ DESC
82
+ task :ami_ids do
83
+ puts "32-bit server image for EC2 on Rails #{ec2onrails_version}: #{image_id_32_bit}"
84
+ puts "64-bit server image for EC2 on Rails #{ec2onrails_version}: #{image_id_64_bit}"
85
+ end
86
+
87
+ desc <<-DESC
88
+ Copies the public key from the server using the external "ssh"
89
+ command because Net::SSH, which is used by Capistrano, needs it.
90
+ This will only work if you have an ssh command in the path.
91
+ If Capistrano can successfully connect to your EC2 instance you
92
+ don't need to do this. It will copy from the first server in the
93
+ :app role, this can be overridden by specifying the HOST
94
+ environment variable
95
+ DESC
96
+ task :get_public_key_from_server do
97
+ host = find_servers_for_task(current_task).first.host
98
+ privkey = ssh_options[:keys][0]
99
+ pubkey = "#{privkey}.pub"
100
+ msg = <<-MSG
101
+ Your first key in ssh_options[:keys] is #{privkey}, presumably that's
102
+ your EC2 private key. The public key will be copied from the server
103
+ named '#{host}' and saved locally as #{pubkey}. Continue? [y/n]
104
+ MSG
105
+ choice = nil
106
+ while choice != "y" && choice != "n"
107
+ choice = Capistrano::CLI.ui.ask(msg).downcase
108
+ msg = "Please enter 'y' or 'n'."
109
+ end
110
+ if choice == "y"
111
+ run_local "scp -i '#{privkey}' app@#{host}:.ssh/authorized_keys #{pubkey}"
112
+ end
113
+ end
114
+
115
+ desc <<-DESC
116
+ Prepare a newly-started instance for a cold deploy.
117
+ DESC
118
+ task :setup do
119
+ ec2onrails.server.allow_sudo do
120
+ server.set_mail_forward_address
121
+ server.set_timezone
122
+ server.install_packages
123
+ server.install_gems
124
+ server.deploy_files
125
+ server.setup_web_proxy
126
+ server.set_roles
127
+ server.enable_ssl if cfg[:enable_ssl]
128
+ server.set_rails_env
129
+ server.restart_services
130
+ deploy.setup
131
+ db.create
132
+ server.harden_server
133
+ db.enable_ebs
134
+ db.set_root_password
135
+ end
136
+ end
137
+
138
+ end
139
+ end
140
+
141
+
@@ -0,0 +1,31 @@
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
+ module Ec2onrails #:nodoc:
20
+ module VERSION #:nodoc:
21
+ MAJOR = 0
22
+ MINOR = 9
23
+ TINY = 10
24
+ # GEM_UPDATE = 0
25
+ # STRING = [MAJOR, MINOR, TINY, GEM_UPDATE].join('.')
26
+ STRING = [MAJOR, MINOR, TINY].join('.')
27
+
28
+ AMI_ID_32_BIT = 'ami-c9bc58a0'
29
+ AMI_ID_64_BIT = 'ami-cbbc58a2'
30
+ end
31
+ end
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__)