/
README
182 lines (143 loc) · 6.56 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
The rubber plugin enables relatively complex multi-instance deployments to
Amazon's Elastic Compute Cloud (EC2).
If you just want a simple single instance setup for your rails app, you might
be better off using something like ec2onrails (which I borrowed heavily from).
The main difference between the two is that rubber was built from the
ground-up to support deploying to multiple instances, and has a very flexible
mechanism for configuring said instances at a host, role or global level.
That is, you can define a set of configuration files for a role, thereby making
it easy to create as many instance for that role as you desire (e.g. scaling up
the quantity of instances you need to host your app servers)
REQUIREMENTS:
* An EC2 account with keypair (both public and private keys) and port 22 access
to the default security group (ec2-authorize default -p 22)
See the EC2 docs for more details:
http://docs.amazonwebservices.com/AWSEC2/2007-08-29/GettingStartedGuide/?ref=get-started
* amazon-ec2: gem install amazon-ec2
* Capistrano: gem install capistrano
INSTALLATION:
First, Rubber needs to be installed as a rails plugin. Then run its
vulcanize generator to add a basic set of configuration files to your
project.
Edit config/rubber/rubber.yml to add your settings. You can edit or
add to the config files in RAILS_ROOT/config/rubber/<common|role|host> to
setup instances globally or for specific roles and/or hosts.
You will also need to customize config/deploy.rb for your needs
You probably don't want to do this, but running "rake rubber:config" in a
development env will tranform config files for the global scope along with
the config file for all roles, and config files for the current machine
(if any), but not config files specific to other hosts. This helps one to
test out config file transformations before committing and deploying to your
instances. Currently this needs to run via sudo as it typically writes to
files that only root can modify (e.g./etc/my/my.cnf) - I need a better
solution here, maybe writing them to a "Fake root" in /tmp.
See RUNNING below for a walkthrough on installing rubber for a demo rails app.
CONFIGURATION:
Config files are just ERB templates. There are some special variables that
need to be set at the top of the config template file that control what
happens when the template is transformed:
@path The output path to write the transformed config file to
@read_cmd The command to use for reading the original config file from
e.g. "crontab -l"
@write_cmd The command to use for piping the transformed config file to
e.g. "crontab -"
@post The command to run after generating the config file ONLY if it
has changed
@owner The owner the output file should have, e.g. "root"
@group The group the output file should have, e.g. "system"
@perms The permissions the output file should have, e.g. 644
@additive Sets transformation to be additive, only replaces between given
delimiters, e.g. @additive = ["## start", "## end"]
Of the above, the only variables that are required are @path or both
@read_cmd and @write_cmd
In addition, within the config templates you have access to the rubber
configuration objects rubber_env (rubber.yml) and rubber_instances
(instance*.yml). This makes it possible to write config files in such a way
that adding more instances gets handled automatically - e.g. the proxy
destinations in the nginx.conf need to get updated when we add more app server
instances.
Configuration files that exist in config/rubber/common will be transformed for
all hosts.
Configuration files that exist in config/rubber/role/<role_name> will only be
transformed on the hosts that are members of role_name.
Configuration files that exist in config/rubber/host/<host_name> will only be
transformed on the hosts with a hostname of host_name.
RUNNING:
Once rubber is installed and configured for your project, the workflow
is as follows:
Create instance(s)
Bootstrap instance(s)
cap deploy(:cold)
Rinse, Repeat
Since bootstrap runs for all roles/hosts, not just the newly created ones, I
tried to make it safe for repeat executions on existing instances. However,
you should probably verify that this is the case for your setup before
trusting it on a production system.
Note that if you change a config file template, you need to check it in before
rubber:config will be able to see the change on remote hosts. However,
changing rubber.yml or instance*.yml do not need to be checked in for their
changes to be seen remotely because they are pushed by the rubber:config
recipe.
For example, you can follow these steps to create a demo app on a single
instance:
Create a simple rails project:
rails rubbertest
cd rubbertest
./script/generate scaffold post title:string body:text
Install rubber:
./script/plugin install http://rubber.rubyforge.org/svn/trunk
./script/generate vulcanize minimal_mysql
Configure rubber:
<edit config/rubber/rubber.yml>
For demo, you need real values for these:
aws_access_key
aws_secret_access_key
ec2_key_name
ec2_key_file
You should go through the rest for a real app.
Create, bootstrap, then deploy to instance:
ALIAS=www ROLES=web,app,db:primary=true cap rubber:create
cap rubber:bootstrap
cap deploy:setup
cap deploy:cold
or for a more complex production setup
ALIAS=web01 ROLES=web cap rubber:create
ALIAS=app01 ROLES=app cap rubber:create
ALIAS=app02 ROLES=app cap rubber:create
ALIAS=db01 ROLES=db:primary=true cap rubber:create
ALIAS=db02 ROLES=db cap rubber:create
cap rubber:bootstrap
cap deploy:setup
cap deploy:cold
To add another app server:
ALIAS=app03 ROLES=app cap rubber:create
cap rubber:bootstrap
cap deploy
EXTEND:
To add some custom install steps in your deploy.rb:
after "rubber:install_packages", "custom_install"
task :custom_install do
# Setup ssh access to svn from all hosts
svn_pvt_key = <<-DATA
-----BEGIN DSA PRIVATE KEY-----
XXXX
-----END DSA PRIVATE KEY-----
DATA
svn_pvt_key.gsub!(/^ */, '')
svn_pub_key = "ssh-dss YYY foo@bar.com"
put(svn_pvt_key, "/root/.ssh/id_dsa", :mode => 0600)
put(svn_pub_key, "/root/.ssh/id_dsa.pub", :mode => 0600)
# Get host key for src machine to prevent ssh from failing
# during cap deploy
run "ssh -o 'StrictHostKeyChecking=no' mobicious@src.foo.com echo"
custom_install_app
end
task :custom_install_app, :roles => :app do
# add the rails user for running app server with
run "adduser --system --group rails"
end
If anyone has any configuration templates similar to what is provided in
generators/vulcanize/templates, please contribute them to
the project.
Enjoy!
Matt Conway