winton-ubistrano 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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