winton-ubistrano 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,271 @@
1
+ require 'erb'
2
+
3
+ Capistrano::Configuration.instance(:must_exist).load do
4
+
5
+ # Install
6
+
7
+ def gem_install(name, options='')
8
+ sudo_puts "gem install #{name} #{options} --no-rdoc --no-ri -q"
9
+ end
10
+
11
+ def install_source(source)
12
+ path, source = unpack_source source
13
+ yield path
14
+ sudo "rm -Rf #{source}"
15
+ end
16
+
17
+ def make_install(path)
18
+ ";cd #{path} && ./configure && make && sudo make install"
19
+ end
20
+
21
+ def unpack_source(source)
22
+ url = sources[source]
23
+ name = File.basename url
24
+ src = "/home/#{user}/sources"
25
+ base = nil
26
+ [ 'tar.gz', 'tgz' ].each do |ext|
27
+ base = name[0..((ext.length + 2) * -1)] if name.include?(ext)
28
+ end
29
+ run_each [
30
+ "mkdir -p #{src}",
31
+ "cd #{src} && wget --quiet #{url}",
32
+ "tar -xzvf #{src}/#{name} -C #{src}"
33
+ ]
34
+ [ "#{src}/#{base}", src ]
35
+ end
36
+
37
+
38
+ # Files
39
+
40
+ def add_line(file, *lines)
41
+ lines.each do |line|
42
+ sudo_each "echo \"#{line}\" | sudo tee -a #{file}"
43
+ end
44
+ end
45
+
46
+ def change_line(file, from, to)
47
+ sudo_each "sed -i 's/#{from}/#{to}/' #{file}"
48
+ end
49
+
50
+ def remove_line(file, *lines)
51
+ lines.each do |line|
52
+ change_line file, line, ''
53
+ end
54
+ end
55
+
56
+ def get_ssh_key(key)
57
+ key.gsub!('.pub', '')
58
+ key = File.expand_path("~/.ssh/#{key}")
59
+ key = Dir[key + '.pub', key].first
60
+ if key
61
+ keys = File.open(key).collect { |line| line.strip.empty? ? nil : line.strip }.compact
62
+ keys.join("\n")
63
+ else
64
+ nil
65
+ end
66
+ end
67
+
68
+ def upload_from_erb(destination, bind=nil, options={})
69
+ # options[ :chown => owner of file (default: deploy user),
70
+ # :chmod => 0644 etc
71
+ # :folder => 'postfix' etc,
72
+ # :name => name of template if differs from destination ]
73
+ if destination.respond_to?(:uniq)
74
+ destination.each { |d| upload_from_erb d, bind, options }
75
+ else
76
+ template = File.basename destination
77
+ template = template[1..-1] if template[0..0] == '.'
78
+ folder = options[:folder] ? options[:folder] + '/' : ''
79
+ template = File.expand_path("../../templates/#{folder}#{options[:name]||template}.erb", File.dirname(__FILE__))
80
+ template = File.read template
81
+ sudo "touch #{destination}"
82
+ sudo "chown #{user} #{destination}"
83
+ put ERB.new(template).result(bind || binding), destination
84
+ sudo("chown #{options[:chown]} #{destination}") if options[:chown]
85
+ sudo("chmod #{options[:chmod]} #{destination}") if options[:chmod]
86
+ end
87
+ end
88
+
89
+
90
+ # MySQL
91
+
92
+ def mysql_run(sql)
93
+ if sql.respond_to?(:uniq)
94
+ sql.each { |s| mysql_run s }
95
+ else
96
+ run "echo \"#{sql}\" | #{mysql_call}"
97
+ end
98
+ end
99
+
100
+ def mysql_call
101
+ @mysql_root_password = @mysql_root_password || ask("Password for mysql root:")
102
+ "mysql -u root --password=#{@mysql_root_password}"
103
+ end
104
+
105
+
106
+ # Questions
107
+
108
+ def ask(question, default='')
109
+ question = "\n" + question.join("\n") if question.respond_to?(:uniq)
110
+ answer = Capistrano::CLI.ui.ask(space(question)).strip
111
+ answer.empty? ? default : answer
112
+ end
113
+
114
+ def yes(question)
115
+ question = "\n" + question.join("\n") if question.respond_to?(:uniq)
116
+ question += ' (y/n)'
117
+ ask(question).downcase.include? 'y'
118
+ end
119
+
120
+ def space(str)
121
+ "\n#{'=' * 80}\n#{str}"
122
+ end
123
+
124
+
125
+ # Runners
126
+
127
+ def run_each(*args, &block)
128
+ cmd = args[0]
129
+ sudo = args[1]
130
+ if cmd.respond_to?(:uniq)
131
+ cmd.each { |c| run_each c, sudo, &block }
132
+ elsif sudo
133
+ puts space("sudo #{cmd}")
134
+ sudo(cmd) { |ch, st, data| block.call(data) if block }
135
+ else
136
+ puts space(cmd)
137
+ run(cmd) { |ch, st, data| block.call(data) if block }
138
+ end
139
+ end
140
+
141
+ def sudo_each(cmds, &block)
142
+ run_each cmds, true, &block
143
+ end
144
+
145
+ def run_puts(cmds, &block)
146
+ run_each(cmds) { |data| puts data }
147
+ end
148
+
149
+ def sudo_puts(cmds, &block)
150
+ sudo_each(cmds) { |data| puts data }
151
+ end
152
+
153
+
154
+ # Messages
155
+
156
+ def msg(type)
157
+ case type
158
+ when :about_templates
159
+ "Let's set up an Ubuntu server! (Tested with 8.04 LTS Hardy)
160
+
161
+ With each task, Ubistrano will describe what it is doing, and wait for a yes/no."
162
+ when :add_user
163
+ "Please ssh into your server (use -i only for EC2):
164
+ ssh root@#{host} -i ~/.ssh/id_rsa-#{application}
165
+
166
+ Add your deploy user:
167
+ adduser #{user}
168
+
169
+ Continue?"
170
+ when :aptitude_default
171
+ "Do you want me to run aptitude update, upgrade, and install build-essential?
172
+ If not, instructions for doing it manually will be displayed."
173
+ when :aptitude_instructions
174
+ "Please run these manually:
175
+ sudo aptitude update
176
+ sudo aptitude upgrade
177
+ sudo aptitude build-essential
178
+
179
+ Continue?"
180
+ when :create_keys
181
+ "May I generate an rsa ssh key pair in your ~/.ssh folder?"
182
+ when :create_server_keys
183
+ "May I generate an rsa ssh key pair on the server?
184
+ The public key will be displayed for adding to your GitHub account."
185
+ when :ec2_finished
186
+ "All finished! Run the following commands:
187
+ sudo chmod 600 ~/.ssh/id_rsa-#{application}
188
+ cap ubuntu"
189
+ when :god
190
+ "May I install God?"
191
+ when :god_apache
192
+ "Would you like God to monitor apache?
193
+ See #{File.expand_path '../../', File.dirname(__FILE__)}/templates/ubuntu/apache.god.erb"
194
+ when :god_mysql
195
+ "Would you like God to monitor mysql?
196
+ See #{File.expand_path '../../', File.dirname(__FILE__)}/templates/ubuntu/mysql.god.erb"
197
+ when :god_sshd
198
+ "Would you like God to monitor sshd?
199
+ See #{File.expand_path '../../', File.dirname(__FILE__)}/templates/ubuntu/sshd.god.erb"
200
+ when :iptables
201
+ "May I update your server's iptables, limiting access to SSH, HTTP, HTTPS, and ping only?
202
+ See #{File.expand_path '../../', File.dirname(__FILE__)}/templates/ubuntu/iptables.rules.erb"
203
+ when :logrotate
204
+ "May I add a logrotate entry for this application?
205
+ See #{File.expand_path '../../', File.dirname(__FILE__)}/templates/log/rotate.conf.erb"
206
+ when :mysqltuner
207
+ "Would you like to install MySQLTuner and receive instructions for running it?"
208
+ when :mysqltuner_instructions
209
+ "Please ssh to your server and run `sudo mysqltuner`.
210
+ Continue?"
211
+ when :passenger
212
+ "Please run `sudo passenger-install-apache2-module` manually.
213
+ The apache config file is found at /etc/apache2/apache2.conf.
214
+ Reload apache?"
215
+ when :run_ubuntu_install
216
+ "Client and server configuration complete.
217
+
218
+ Please run the second half of the install:
219
+ cap ubuntu:install
220
+ "
221
+ when :secure_mysql
222
+ "It is highly recommended you run mysql_secure_installation manually.
223
+ See http://dev.mysql.com/doc/refman/5.1/en/mysql-secure-installation.html
224
+ Continue?"
225
+ when :sinatra_install
226
+ "Would you like to run install.rb (from your app) if it exists?"
227
+ when :sshd_config
228
+ "May I update your server's sshd_config with the following settings?
229
+ Port #{port}
230
+ PermitRootLogin no
231
+ X11Forwarding no
232
+ UsePAM no
233
+ UseDNS no
234
+ "
235
+ when :ssh_config
236
+ "May I update your server's ssh_config with the following settings?
237
+ StrictHostKeyChecking no
238
+ "
239
+ when :ubuntu_restart
240
+ "Its probably a good idea to restart the server now.
241
+ OK?"
242
+ when :ubuntu_restart_2
243
+ "Please wait a little while for your server to restart.
244
+
245
+ Continue?"
246
+ when :ubuntu_finished
247
+ "That's it! Glad you made it.
248
+
249
+ Use `cap deploy:first` to set up your PHP, Rails, or Sinatra app.
250
+ Use `cap deploy` for all subsequent deploys.
251
+
252
+ "
253
+ when :upload_keys
254
+ "Would you like to upload a ssh key to the deploy user's authorized_keys?"
255
+ when :upload_keys_2
256
+ "Please enter a key in ~/.ssh to copy to the the deploy user's authorized_keys."
257
+ when :visudo
258
+ "Please ssh into your server (use -i only for EC2):
259
+ ssh root@#{host} -i ~/.ssh/id_rsa-#{application}
260
+
261
+ Edit your sudoers file:
262
+ visudo
263
+
264
+ Add the following line:
265
+ deploy ALL=NOPASSWD: ALL
266
+
267
+ Continue?"
268
+ end
269
+ end
270
+
271
+ end
@@ -0,0 +1,20 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :log do
4
+ desc "Add logrotate entry for this application"
5
+ task :rotate, :roles => :app do
6
+ if yes(msg(:iptables))
7
+ upload_from_erb '/etc/rotate.conf', binding, :folder => 'log'
8
+ sudo_each [
9
+ 'cp -f /etc/logrotate.conf /etc/logrotate2.conf',
10
+ 'chmod 777 /etc/logrotate2.conf',
11
+ 'cat /etc/rotate.conf >> /etc/logrotate2.conf',
12
+ 'cp -f /etc/logrotate2.conf /etc/logrotate.conf',
13
+ 'rm -f /etc/logrotate2.conf',
14
+ 'rm -f /etc/rotate.conf'
15
+ ]
16
+ end
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,94 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :mysql do
4
+ namespace :create do
5
+ desc "Create database and user"
6
+ task :default, :roles => :db do
7
+ mysql.create.db
8
+ mysql.create.user
9
+ end
10
+
11
+ desc "Create database"
12
+ task :db, :roles => :db do
13
+ mysql_run "CREATE DATABASE #{db_table}"
14
+ end
15
+
16
+ desc "Create database user"
17
+ task :user, :roles => :db do
18
+ mysql_run [
19
+ "CREATE USER '#{db_user}'@'localhost' IDENTIFIED BY '#{db_pass}'",
20
+ "GRANT ALL PRIVILEGES ON *.* TO '#{db_user}'@'localhost'"
21
+ ]
22
+ end
23
+ end
24
+
25
+ namespace :update do
26
+ desc 'Update mysql root password'
27
+ task :root_password, :roles => :db do
28
+ old_pass = ask "Current root password? (default: none)"
29
+ new_pass = ask "New root password? (default: none)"
30
+ sudo "mysqladmin -u root #{old_pass.empty? ? '' : "--password=#{old_pass} "}password #{new_pass}"
31
+ end
32
+ end
33
+
34
+ namespace :destroy do
35
+ desc "Destroy database and user"
36
+ task :default, :roles => :db do
37
+ mysql.destroy.db
38
+ mysql.destroy.user
39
+ end
40
+
41
+ desc "Destroy database"
42
+ task :db, :roles => :db do
43
+ mysql_run "DROP DATABASE #{db_table}"
44
+ end
45
+
46
+ desc "Destroy database user"
47
+ task :user, :roles => :db do
48
+ mysql_run [
49
+ "REVOKE ALL PRIVILEGES, GRANT OPTION FROM '#{db_user}'@'localhost'",
50
+ "DROP USER '#{db_user}'@'localhost'"
51
+ ]
52
+ end
53
+ end
54
+
55
+ namespace :backup do
56
+ desc "Upload local backup to remote"
57
+ task :local_to_server, :roles => :db do
58
+ from = File.expand_path("~/db_backups/#{stage}/#{application}/#{backup_name}.bz2")
59
+ if File.exists?(from)
60
+ run_each "mkdir -p #{shared_path}/db_backups"
61
+ upload from, "#{shared_path}/db_backups/#{backup_name}.bz2"
62
+ else
63
+ puts "Does not exist: #{from}"
64
+ end
65
+ end
66
+
67
+ desc "Restore remote database from backup"
68
+ task :restore, :roles => :db do
69
+ run_each "bunzip2 < #{shared_path}/db_backups/#{backup_name}.bz2 | mysql -u #{db_user} --password=#{db_pass} #{db_table}"
70
+ end
71
+
72
+ desc "Backup database to local"
73
+ task :to_local, :roles => :db do
74
+ to_server
75
+ system "mkdir -p ~/db_backups/#{stage}/#{application}"
76
+ get "#{shared_path}/db_backups/#{backup_name}.bz2", File.expand_path("~/db_backups/#{stage}/#{application}/#{backup_name}.bz2")
77
+ end
78
+
79
+ desc "Backup database to remote"
80
+ task :to_server, :roles => :db do
81
+ run_each [
82
+ "mkdir -p #{shared_path}/db_backups",
83
+ "mysqldump --add-drop-table -u #{db_user} -p#{db_pass} #{db_table}_production | bzip2 -c > #{shared_path}/db_backups/#{backup_name}.bz2"
84
+ ]
85
+ end
86
+
87
+ def backup_name
88
+ now = Time.now
89
+ [ now.year, now.month, now.day ].join('-') + '.sql'
90
+ end
91
+ end
92
+ end
93
+
94
+ end
@@ -0,0 +1,76 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :rails do
4
+ namespace :config do
5
+ desc "Creates database.yml in the shared config"
6
+ task :default, :roles => :app do
7
+ run "mkdir -p #{shared_path}/config"
8
+ Dir[File.expand_path('../../templates/rails/*', File.dirname(__FILE__))].each do |f|
9
+ upload_from_erb "#{shared_path}/config/#{File.basename(f, '.erb')}", binding, :folder => 'rails'
10
+ end
11
+ end
12
+
13
+ desc "Set up app with app_helpers"
14
+ task :app_helpers do
15
+ run "cd #{release_path} && script/plugin install git://github.com/winton/app_helpers.git"
16
+ run "cd #{release_path} && rake RAILS_ENV=production quiet=true app_helpers"
17
+ end
18
+
19
+ desc "Configure attachment_fu"
20
+ task :attachment_fu, :roles => :app do
21
+ run_each [
22
+ "mkdir -p #{shared_path}/media",
23
+ "ln -sf #{shared_path}/media #{release_path}/public/media"
24
+ ]
25
+ sudo_each [
26
+ "mkdir -p #{release_path}/tmp/attachment_fu",
27
+ "chown -R #{user} #{release_path}/tmp/attachment_fu"
28
+ ]
29
+ end
30
+
31
+ desc "Configure asset_packager"
32
+ task :asset_packager do
33
+ run "source ~/.bash_profile && cd #{release_path} && rake RAILS_ENV=production asset:packager:build_all"
34
+ end
35
+
36
+ desc "Configure rails_widget"
37
+ task :rails_widget, :roles => :app do
38
+ run "cd #{release_path} && rake RAILS_ENV=production widget:production"
39
+ end
40
+
41
+ desc "Copies yml files in the shared config folder into our app config"
42
+ task :to_app, :roles => :app do
43
+ run "cp -Rf #{shared_path}/config/* #{release_path}/config"
44
+ end
45
+
46
+ namespace :thinking_sphinx do
47
+ desc "Configures thinking_sphinx"
48
+ task :default, :roles => :app do
49
+ sudo ";cd #{release_path} && rake RAILS_ENV=production ts:config"
50
+ end
51
+
52
+ desc "Stop thinking_sphinx"
53
+ task :stop, :roles => :app do
54
+ sudo ";cd #{release_path} && rake RAILS_ENV=production ts:stop"
55
+ end
56
+
57
+ desc "Start thinking_sphinx"
58
+ task :start, :roles => :app do
59
+ sudo ";cd #{release_path} && rake RAILS_ENV=production ts:start"
60
+ end
61
+
62
+ desc "Restart thinking_sphinx"
63
+ task :restart, :roles => :app do
64
+ rails.config.thinking_sphinx.stop
65
+ rails.config.thinking_sphinx.start
66
+ end
67
+ end
68
+ end
69
+
70
+ desc "Intialize Git submodules"
71
+ task :setup_git, :roles => :app do
72
+ run "cd #{release_path}; git submodule init; git submodule update"
73
+ end
74
+ end
75
+
76
+ end
@@ -0,0 +1,25 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :sinatra do
4
+ desc "Runs install.rb if exists"
5
+ task :install do
6
+ if yes(msg(:sinatra_install))
7
+ run_puts "if [ -e #{current_path}/install.rb ]; then sudo ruby #{current_path}/install.rb; fi"
8
+ end
9
+ end
10
+
11
+ namespace :config do
12
+ desc "Creates config.ru in shared config"
13
+ task :default do
14
+ run "mkdir -p #{shared_path}/config"
15
+ upload_from_erb "#{shared_path}/config/config.ru", binding, :folder => 'sinatra'
16
+ end
17
+
18
+ desc "Copies files in the shared config folder into our app"
19
+ task :to_app, :roles => :app do
20
+ run "cp -Rf #{shared_path}/config/* #{release_path}"
21
+ end
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,56 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ namespace :ssh do
4
+ desc 'Generate ssh keys and upload to server'
5
+ task :default do
6
+ ssh.keys.create.local
7
+ ssh.keys.upload
8
+ ssh.keys.create.remote
9
+ end
10
+
11
+ namespace :keys do
12
+ namespace :create do
13
+ desc "Creates an rsa ssh key pair (local)"
14
+ task :local do
15
+ system('ssh-keygen -t rsa') if yes(msg(:create_keys))
16
+ end
17
+
18
+ desc "Creates an rsa ssh key pair (remote)"
19
+ task :remote do
20
+ if yes(msg(:create_server_keys))
21
+ pass = ask "Enter a password for this key:"
22
+ sudo_each [
23
+ "ssh-keygen -t rsa -N '#{pass}' -q -f /home/#{user}/.ssh/id_rsa",
24
+ "chmod 0700 /home/#{user}/.ssh",
25
+ "chown -R #{user} /home/#{user}/.ssh"
26
+ ]
27
+ sudo_puts "tail -1 /home/#{user}/.ssh/id_rsa.pub"
28
+ end
29
+ end
30
+ end
31
+
32
+ desc "Uploads local ssh public keys into remote authorized_keys"
33
+ task :upload do
34
+ if yes(msg(:upload_keys))
35
+ key = ask msg(:upload_keys_2)
36
+ key = get_ssh_key key
37
+ if key.nil?
38
+ ssh.setup if yes("No keys found. Generate ssh keys now?")
39
+ else
40
+ sudo_each [
41
+ "mkdir -p /home/#{user}/.ssh",
42
+ "touch /home/#{user}/.ssh/authorized_keys"
43
+ ]
44
+ add_line "/home/#{user}/.ssh/authorized_keys", key
45
+ sudo_each [
46
+ "chmod 0700 /home/#{user}/.ssh",
47
+ "chmod 0600 /home/#{user}/.ssh/authorized_keys",
48
+ "chown -R #{user} /home/#{user}/.ssh"
49
+ ]
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,29 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ desc 'Set the target stage to staging'
4
+ task :staging do
5
+ set :stage, :staging
6
+ end
7
+
8
+ desc 'Set the target stage to test'
9
+ task :testing do
10
+ set :stage, :test
11
+ end
12
+
13
+ # None of this works in a namespace
14
+ desc 'Set up stage-dependent properties'
15
+ task :setup_stage do
16
+ set :base_dir, "#{ubistrano[:base_dir]}/#{stage}"
17
+ set :deploy_to, "#{base_dir}/#{application}"
18
+ set :db_table, "#{application}#{stage == :staging ? "_#{stage}" : ''}"
19
+
20
+ ubistrano[stage].each do |key, value|
21
+ set key, value
22
+ end
23
+
24
+ role :app, host, :primary => true
25
+ role :web, host, :primary => true
26
+ role :db, host, :primary => true
27
+ end
28
+
29
+ end