ScholarNexus-ec2onrails 0.9.10
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +180 -0
- data/COPYING +339 -0
- data/Manifest +167 -0
- data/README.textile +211 -0
- data/Rakefile +37 -0
- data/TODO +104 -0
- data/ec2onrails.gemspec +42 -0
- data/examples/Capfile +3 -0
- data/examples/deploy.rb +107 -0
- data/examples/s3.yml +9 -0
- data/lib/ec2onrails/capistrano_utils.rb +43 -0
- data/lib/ec2onrails/recipes/db.rb +359 -0
- data/lib/ec2onrails/recipes/deploy.rb +30 -0
- data/lib/ec2onrails/recipes/server.rb +489 -0
- data/lib/ec2onrails/recipes.rb +141 -0
- data/lib/ec2onrails/version.rb +31 -0
- data/lib/ec2onrails.rb +20 -0
- data/server/build-ec2onrails.sh +44 -0
- data/server/files/etc/aliases +5 -0
- data/server/files/etc/aliases.db +0 -0
- data/server/files/etc/apache2/apache2.conf +295 -0
- data/server/files/etc/apache2/conf.d/app.proxy_cluster.conf +7 -0
- data/server/files/etc/apache2/conf.d/app.proxy_frontend.conf +10 -0
- data/server/files/etc/apache2/mods-available/proxy.conf +18 -0
- data/server/files/etc/apache2/sites-available/app.common +61 -0
- data/server/files/etc/apache2/sites-available/app.custom +0 -0
- data/server/files/etc/apache2/sites-available/default +14 -0
- data/server/files/etc/apache2/sites-available/default-ssl +19 -0
- data/server/files/etc/cron.d/ec2onrails +21 -0
- data/server/files/etc/cron.daily/app +24 -0
- data/server/files/etc/cron.daily/logrotate_post +19 -0
- data/server/files/etc/cron.hourly/app +24 -0
- data/server/files/etc/cron.monthly/app +24 -0
- data/server/files/etc/cron.weekly/app +24 -0
- data/server/files/etc/denyhosts.conf +628 -0
- data/server/files/etc/dpkg/dpkg.cfg +13 -0
- data/server/files/etc/ec2onrails/README +32 -0
- data/server/files/etc/ec2onrails/balancer_members +6 -0
- data/server/files/etc/ec2onrails/roles.yml +5 -0
- data/server/files/etc/environment +2 -0
- data/server/files/etc/god/app.god +40 -0
- data/server/files/etc/god/db.god +17 -0
- data/server/files/etc/god/dkim_filter.god +20 -0
- data/server/files/etc/god/examples/have_god_daemonize.god +18 -0
- data/server/files/etc/god/master.conf +35 -0
- data/server/files/etc/god/memcache.god +15 -0
- data/server/files/etc/god/notifications.god +14 -0
- data/server/files/etc/god/system.god +34 -0
- data/server/files/etc/god/web.god +38 -0
- data/server/files/etc/init.d/ec2-every-startup +29 -0
- data/server/files/etc/init.d/ec2-first-startup +36 -0
- data/server/files/etc/init.d/god +42 -0
- data/server/files/etc/init.d/nginx +78 -0
- data/server/files/etc/init.d/set_roles +3 -0
- data/server/files/etc/logrotate.d/apache2 +16 -0
- data/server/files/etc/logrotate.d/mongrel +11 -0
- data/server/files/etc/logrotate.d/nginx +11 -0
- data/server/files/etc/memcached.conf +47 -0
- data/server/files/etc/mongrel_cluster/app.yml +9 -0
- data/server/files/etc/motd.tail +13 -0
- data/server/files/etc/mysql/my.cnf +152 -0
- data/server/files/etc/nginx/nginx.conf +305 -0
- data/server/files/etc/postfix/main.cf +4 -0
- data/server/files/etc/rcS.d/S91ec2-first-startup +1 -0
- data/server/files/etc/rcS.d/S92ec2-every-startup +1 -0
- data/server/files/etc/rcS.d/S99set_roles +1 -0
- data/server/files/etc/ssh/sshd_config +94 -0
- data/server/files/etc/sudoers +1 -0
- data/server/files/etc/sudoers.full_access +26 -0
- data/server/files/etc/sudoers.restricted_access +28 -0
- data/server/files/etc/syslog.conf +69 -0
- data/server/files/usr/bin/god +26 -0
- data/server/files/usr/local/ec2onrails/COPYING +339 -0
- data/server/files/usr/local/ec2onrails/bin/archive_file.rb +44 -0
- data/server/files/usr/local/ec2onrails/bin/backup_app_db.rb +159 -0
- data/server/files/usr/local/ec2onrails/bin/ec2_meta_data.rb +80 -0
- data/server/files/usr/local/ec2onrails/bin/exec_runner +76 -0
- data/server/files/usr/local/ec2onrails/bin/init_services.rb +71 -0
- data/server/files/usr/local/ec2onrails/bin/optimize_mysql.rb +348 -0
- data/server/files/usr/local/ec2onrails/bin/rails_env +34 -0
- data/server/files/usr/local/ec2onrails/bin/rebundle.sh +70 -0
- data/server/files/usr/local/ec2onrails/bin/restore_app_db.rb +58 -0
- data/server/files/usr/local/ec2onrails/bin/set_rails_env +40 -0
- data/server/files/usr/local/ec2onrails/bin/set_roles.rb +87 -0
- data/server/files/usr/local/ec2onrails/bin/setup_web_proxy.rb +113 -0
- data/server/files/usr/local/ec2onrails/bin/update_hostname +40 -0
- data/server/files/usr/local/ec2onrails/config +30 -0
- data/server/files/usr/local/ec2onrails/lib/aws_helper.rb +76 -0
- data/server/files/usr/local/ec2onrails/lib/god_helper.rb +129 -0
- data/server/files/usr/local/ec2onrails/lib/god_patch.rb +43 -0
- data/server/files/usr/local/ec2onrails/lib/mysql_helper.rb +101 -0
- data/server/files/usr/local/ec2onrails/lib/roles_helper.rb +151 -0
- data/server/files/usr/local/ec2onrails/lib/s3_helper.rb +99 -0
- data/server/files/usr/local/ec2onrails/lib/utils.rb +16 -0
- data/server/files/usr/local/ec2onrails/lib/vendor/ini.rb +268 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/every-startup/get-hostname.sh +23 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/README +5 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/create-dirs.sh +39 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/generate-default-web-cert-and-key.sh +49 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/misc.sh +27 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/prepare-mysql-data-dir.sh +24 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/setup-credentials.sh +29 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/setup-file-permissions.sh +30 -0
- data/server/rakefile.rb +249 -0
- data/setup.rb +1585 -0
- data/test/autobench.conf +60 -0
- data/test/spec/lib/s3_helper_spec.rb +134 -0
- data/test/spec/lib/s3_old.yml +3 -0
- data/test/spec/test_files/test1 +0 -0
- data/test/spec/test_files/test2 +0 -0
- data/test/test_app/Capfile +3 -0
- data/test/test_app/README +182 -0
- data/test/test_app/Rakefile +10 -0
- data/test/test_app/app/controllers/application.rb +7 -0
- data/test/test_app/app/controllers/db_fast_controller.rb +6 -0
- data/test/test_app/app/controllers/fast_controller.rb +5 -0
- data/test/test_app/app/controllers/slow_controller.rb +6 -0
- data/test/test_app/app/controllers/very_slow_controller.rb +6 -0
- data/test/test_app/app/helpers/application_helper.rb +3 -0
- data/test/test_app/app/helpers/db_fast_helper.rb +2 -0
- data/test/test_app/app/helpers/fast_helper.rb +2 -0
- data/test/test_app/app/helpers/slow_helper.rb +2 -0
- data/test/test_app/app/helpers/very_slow_helper.rb +2 -0
- data/test/test_app/config/boot.rb +109 -0
- data/test/test_app/config/database.yml +19 -0
- data/test/test_app/config/deploy.rb +21 -0
- data/test/test_app/config/environment.rb +60 -0
- data/test/test_app/config/environments/development.rb +21 -0
- data/test/test_app/config/environments/production.rb +18 -0
- data/test/test_app/config/environments/test.rb +19 -0
- data/test/test_app/config/routes.rb +27 -0
- data/test/test_app/db/schema.rb +7 -0
- data/test/test_app/doc/README_FOR_APP +2 -0
- data/test/test_app/public/404.html +30 -0
- data/test/test_app/public/500.html +30 -0
- data/test/test_app/public/dispatch.cgi +10 -0
- data/test/test_app/public/dispatch.fcgi +24 -0
- data/test/test_app/public/dispatch.rb +10 -0
- data/test/test_app/public/favicon.ico +0 -0
- data/test/test_app/public/images/rails.png +0 -0
- data/test/test_app/public/javascripts/application.js +2 -0
- data/test/test_app/public/javascripts/controls.js +963 -0
- data/test/test_app/public/javascripts/dragdrop.js +972 -0
- data/test/test_app/public/javascripts/effects.js +1120 -0
- data/test/test_app/public/javascripts/prototype.js +4225 -0
- data/test/test_app/public/robots.txt +1 -0
- data/test/test_app/script/about +3 -0
- data/test/test_app/script/breakpointer +3 -0
- data/test/test_app/script/console +3 -0
- data/test/test_app/script/destroy +3 -0
- data/test/test_app/script/generate +3 -0
- data/test/test_app/script/performance/benchmarker +3 -0
- data/test/test_app/script/performance/profiler +3 -0
- data/test/test_app/script/performance/request +3 -0
- data/test/test_app/script/plugin +3 -0
- data/test/test_app/script/process/inspector +3 -0
- data/test/test_app/script/process/reaper +3 -0
- data/test/test_app/script/process/spawner +3 -0
- data/test/test_app/script/runner +3 -0
- data/test/test_app/script/server +3 -0
- data/test/test_app/test/functional/db_fast_controller_test.rb +18 -0
- data/test/test_app/test/functional/fast_controller_test.rb +18 -0
- data/test/test_app/test/functional/slow_controller_test.rb +18 -0
- data/test/test_app/test/functional/very_slow_controller_test.rb +18 -0
- data/test/test_app/test/test_helper.rb +28 -0
- data/test/test_ec2onrails.rb +11 -0
- data/test/test_helper.rb +2 -0
- 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__)
|