capistrano-fiftyfive 0.9.0

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.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/CHANGELOG.md +5 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +164 -0
  7. data/Rakefile +1 -0
  8. data/capistrano-fiftyfive.gemspec +30 -0
  9. data/lib/capistrano/fiftyfive/compatibility.rb +17 -0
  10. data/lib/capistrano/fiftyfive/console.rb +61 -0
  11. data/lib/capistrano/fiftyfive/dsl.rb +140 -0
  12. data/lib/capistrano/fiftyfive/recipe.rb +48 -0
  13. data/lib/capistrano/fiftyfive/templates/crontab.erb +1 -0
  14. data/lib/capistrano/fiftyfive/templates/csr_config.erb +10 -0
  15. data/lib/capistrano/fiftyfive/templates/delayed_job_init.erb +36 -0
  16. data/lib/capistrano/fiftyfive/templates/logrotate.erb +9 -0
  17. data/lib/capistrano/fiftyfive/templates/maintenance.html.erb +26 -0
  18. data/lib/capistrano/fiftyfive/templates/nginx.erb +60 -0
  19. data/lib/capistrano/fiftyfive/templates/nginx_unicorn.erb +100 -0
  20. data/lib/capistrano/fiftyfive/templates/pgpass.erb +1 -0
  21. data/lib/capistrano/fiftyfive/templates/postgresql-backup-logrotate.erb +11 -0
  22. data/lib/capistrano/fiftyfive/templates/postgresql.yml.erb +8 -0
  23. data/lib/capistrano/fiftyfive/templates/rbenv_bashrc +4 -0
  24. data/lib/capistrano/fiftyfive/templates/sidekiq_init.erb +100 -0
  25. data/lib/capistrano/fiftyfive/templates/ssl_setup +43 -0
  26. data/lib/capistrano/fiftyfive/templates/unicorn.rb.erb +71 -0
  27. data/lib/capistrano/fiftyfive/templates/unicorn_init.erb +84 -0
  28. data/lib/capistrano/fiftyfive/templates/version.rb.erb +2 -0
  29. data/lib/capistrano/fiftyfive/version.rb +5 -0
  30. data/lib/capistrano/fiftyfive.rb +28 -0
  31. data/lib/capistrano/tasks/aptitude.rake +77 -0
  32. data/lib/capistrano/tasks/crontab.rake +14 -0
  33. data/lib/capistrano/tasks/defaults.rake +124 -0
  34. data/lib/capistrano/tasks/delayed_job.rake +32 -0
  35. data/lib/capistrano/tasks/dotenv.rake +53 -0
  36. data/lib/capistrano/tasks/logrotate.rake +15 -0
  37. data/lib/capistrano/tasks/maintenance.rake +28 -0
  38. data/lib/capistrano/tasks/migrate.rake +29 -0
  39. data/lib/capistrano/tasks/nginx.rake +30 -0
  40. data/lib/capistrano/tasks/postgresql.rake +103 -0
  41. data/lib/capistrano/tasks/rake.rake +20 -0
  42. data/lib/capistrano/tasks/rbenv.rake +92 -0
  43. data/lib/capistrano/tasks/seed.rake +16 -0
  44. data/lib/capistrano/tasks/sidekiq.rake +38 -0
  45. data/lib/capistrano/tasks/ssl.rake +52 -0
  46. data/lib/capistrano/tasks/ufw.rake +32 -0
  47. data/lib/capistrano/tasks/unicorn.rake +41 -0
  48. data/lib/capistrano/tasks/user.rake +29 -0
  49. data/lib/capistrano/tasks/version.rake +31 -0
  50. data/lib/sshkit/formatter/abbreviated.rb +148 -0
  51. metadata +165 -0
@@ -0,0 +1,100 @@
1
+ # Based on https://github.com/defunkt/unicorn/blob/master/examples/nginx.conf
2
+
3
+ upstream unicorn_<%= application_basename %> {
4
+ # fail_timeout=0 means we always retry an upstream even if it failed
5
+ # to return a good HTTP response (in case the Unicorn master nukes a
6
+ # single worker for timing out).
7
+ server unix:/tmp/unicorn.<%= application_basename %>.sock fail_timeout=0;
8
+ }
9
+
10
+ <% [80, 443].each do |port| %>
11
+
12
+ <% fetch(:fiftyfive_nginx_redirect_hosts).each do |orig, desired| %>
13
+ server {
14
+ listen <%= port %>;
15
+ server_name <%= orig %>;
16
+ return 301 <%= fetch(:fiftyfive_nginx_force_https) ? "https" : "$scheme" %>://<%= desired %>$request_uri;
17
+ }
18
+ <% end %>
19
+
20
+ server {
21
+ listen <%= port %> <%= "spdy" if port == 443 %> default deferred; # for Linux
22
+
23
+ <% if port == 80 && fetch(:fiftyfive_nginx_force_https) %>
24
+ rewrite ^(.*) https://$http_host$1 permanent;
25
+ <% else %>
26
+
27
+ client_max_body_size 4G;
28
+ server_name _;
29
+
30
+ # ~2 seconds is often enough for most folks to parse HTML/CSS and
31
+ # retrieve needed images/icons/frames, connections are cheap in
32
+ # nginx so increasing this is generally safe...
33
+ keepalive_timeout 5;
34
+
35
+ # path for static files
36
+ root <%= current_path %>/public;
37
+
38
+ # Capistrano `deploy:web:disable` support
39
+ if (-f $document_root/system/maintenance.html) {
40
+ return 503;
41
+ }
42
+ error_page 503 @maintenance;
43
+ location @maintenance {
44
+ rewrite ^(.*)$ /system/maintenance.html last;
45
+ break;
46
+ }
47
+
48
+ <% if port == 443 %>
49
+ ssl on;
50
+ ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:RSA+3DES:!ADH:!AECDH:!MD5;
51
+ ssl_prefer_server_ciphers on;
52
+ ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
53
+ ssl_certificate /etc/ssl/<%= application_basename %>.crt;
54
+ ssl_certificate_key /etc/ssl/<%= application_basename %>.key;
55
+
56
+ <% if fetch(:fiftyfive_nginx_force_https) %>
57
+ add_header Strict-Transport-Security "max-age=631138519";
58
+ <% end %>
59
+ <% end %>
60
+
61
+ # Far-future expires and gzip for fingerprinted assets
62
+ location ^~ /<%= fetch(:assets_prefix, "assets") %>/ {
63
+ gzip_static on;
64
+ expires max;
65
+ add_header Cache-Control public;
66
+ }
67
+
68
+ include /etc/nginx/<%= application_basename%>-locations/*;
69
+
70
+ # Prefer to serve static files directly from nginx to avoid unnecessary
71
+ # data copies from the application server.
72
+ try_files $uri/index.html $uri @unicorn;
73
+
74
+ location @unicorn {
75
+ # an HTTP header important enough to have its own Wikipedia entry:
76
+ # http://en.wikipedia.org/wiki/X-Forwarded-For
77
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
78
+
79
+ # this helps Rack set the proper URL scheme for doing HTTPS redirects:
80
+ proxy_set_header X-Forwarded-Proto $scheme;
81
+
82
+ # pass the Host: header from the client right along so redirects
83
+ # can be set properly within the Rack application
84
+ proxy_set_header Host $http_host;
85
+
86
+ # we don't want nginx trying to do something clever with
87
+ # redirects, we set the Host: header above already.
88
+ proxy_redirect off;
89
+
90
+ proxy_pass http://unicorn_<%= application_basename %>;
91
+ }
92
+
93
+ # Rails error pages
94
+ error_page 500 502 503 504 /500.html;
95
+ location = /500.html {
96
+ root <%= current_path %>/public;
97
+ }
98
+ <% end %>
99
+ }
100
+ <% end %>
@@ -0,0 +1 @@
1
+ <%= fetch(:fiftyfive_postgresql_host) %>:5432:<%= fetch(:fiftyfive_postgresql_database) %>:<%= fetch(:fiftyfive_postgresql_user) %>:<%= fetch(:fiftyfive_postgresql_password).gsub(/([\\:])/, '\\\\\1') %>
@@ -0,0 +1,11 @@
1
+ <%= fetch(:fiftyfive_postgresql_backup_path) %> {
2
+ daily
3
+ nomissingok
4
+ rotate 30
5
+ ifempty
6
+ create 600 <%= user %>
7
+ dateext
8
+ postrotate
9
+ /usr/bin/sudo -u <%= user %> PGPASSFILE=<%= fetch(:fiftyfive_postgresql_pgpass_path) %> /usr/bin/pg_dump -Fc -Z9 -O -x <%= fetch(:fiftyfive_postgresql_dump_options) %> -h <%= fetch(:fiftyfive_postgresql_host) %> -U <%= fetch(:fiftyfive_postgresql_user) %> -f <%= fetch(:fiftyfive_postgresql_backup_path) %> <%= fetch(:fiftyfive_postgresql_database) %>
10
+ endscript
11
+ }
@@ -0,0 +1,8 @@
1
+ <%= fetch(:rails_env) %>:
2
+ adapter: postgresql
3
+ encoding: unicode
4
+ database: <%= fetch(:fiftyfive_postgresql_database) %>
5
+ pool: <%= fetch(:fiftyfive_postgresql_pool_size) %>
6
+ username: <%= fetch(:fiftyfive_postgresql_user) %>
7
+ password: <%= fetch(:fiftyfive_postgresql_password) %>
8
+ host: <%= fetch(:fiftyfive_postgresql_host) %>
@@ -0,0 +1,4 @@
1
+ if [ -d $HOME/.rbenv ]; then
2
+ export PATH="$HOME/.rbenv/bin:$PATH"
3
+ eval "$(rbenv init -)"
4
+ fi
@@ -0,0 +1,100 @@
1
+ #!/bin/sh
2
+ ### BEGIN INIT INFO
3
+ # Provides: sidekiq
4
+ # Required-Start: $remote_fs $syslog
5
+ # Required-Stop: $remote_fs $syslog
6
+ # Default-Start: 2 3 4 5
7
+ # Default-Stop: 0 1 6
8
+ # Short-Description: Manage sidekiq worker
9
+ # Description: Start, stop, restart sidekiq worker.
10
+ ### END INIT INFO
11
+
12
+ APP_DIR="<%= current_path %>"
13
+ LOG_FILE="$APP_DIR/log/sidekiq.log"
14
+ PID_FILE="$APP_DIR/tmp/pids/sidekiq.pid"
15
+ SIDEKIQ="sidekiq"
16
+ SIDEKIQCTL="sidekiqctl"
17
+ APP_ENV="<%= fetch(:rails_env) %>"
18
+ BUNDLE="bundle"
19
+ AS_USER=<%= fetch(:fiftyfive_sidekiq_user, user) %>
20
+ CONCURRENCY=<%= fetch(:fiftyfive_sidekiq_concurrency) %>
21
+
22
+ START_CMD="cd $APP_DIR; $BUNDLE exec $SIDEKIQ -d -e $APP_ENV -P $PID_FILE --concurrency $CONCURRENCY -L $LOG_FILE"
23
+ CTL_CMD="cd $APP_DIR; $BUNDLE exec $SIDEKIQCTL"
24
+ RETVAL=0
25
+
26
+
27
+ run () {
28
+ if [ "$(id -un)" = "$AS_USER" ]; then
29
+ eval $1
30
+ else
31
+ su -c "$1" - $AS_USER
32
+ fi
33
+ }
34
+
35
+ start() {
36
+
37
+ status
38
+ if [ $? -eq 1 ]; then
39
+
40
+ [ -d $APP_DIR ] || (echo "$APP_DIR not found!.. Exiting"; exit 6)
41
+ echo "Starting $SIDEKIQ message processor .. "
42
+ run "$START_CMD"
43
+ RETVAL=$?
44
+ #Sleeping for 8 seconds for process to be precisely visible in process table - See status ()
45
+ sleep 8
46
+ return $RETVAL
47
+ else
48
+ echo "$SIDEKIQ message processor is already running .. "
49
+ fi
50
+
51
+
52
+ }
53
+
54
+ stop() {
55
+
56
+ status
57
+ if [ $? -eq 0 ]; then
58
+
59
+ echo "Stopping $SIDEKIQ message processor .."
60
+ run "$CTL_CMD stop $PID_FILE"
61
+ RETVAL=$?
62
+ return $RETVAL
63
+
64
+ else
65
+ echo "$SIDEKIQ message processor is already stopped .. "
66
+ fi
67
+
68
+ }
69
+
70
+ status() {
71
+
72
+ ps -ef | egrep 'sidekiq [0-9]+.[0-9]+.[0-9]+' | grep -v grep
73
+ return $?
74
+ }
75
+
76
+
77
+ case "$1" in
78
+ start)
79
+ start
80
+ ;;
81
+ stop)
82
+ stop
83
+ ;;
84
+ status)
85
+ status
86
+
87
+ if [ $? -eq 0 ]; then
88
+ echo "$SIDEKIQ message processor is running .."
89
+ RETVAL=0
90
+ else
91
+ echo "$SIDEKIQ message processor is stopped .."
92
+ RETVAL=1
93
+ fi
94
+ ;;
95
+ *)
96
+ echo "Usage: $0 {start|stop|status}"
97
+ exit 0
98
+ ;;
99
+ esac
100
+ exit $RETVAL
@@ -0,0 +1,43 @@
1
+ #!/bin/bash
2
+
3
+ # Usage:
4
+ #
5
+ # ssl_setup [--self] <name> <csr_config>
6
+ #
7
+ # This script is used to generate key and CSR for use HTTPS in Nginx.
8
+ #
9
+ # --self Generate self-signed certificate in addition to key and CSR.
10
+ # name Output files will be named as <name>.key and <name>.csr.
11
+ # csr_config Path to file that specifies CSR information. See below.
12
+ #
13
+ # CSR configuration format:
14
+ #
15
+ # [ req ]
16
+ # distinguished_name="req_distinguished_name"
17
+ # prompt="no"
18
+ #
19
+ # [ req_distinguished_name ]
20
+ # C="US"
21
+ # ST="California"
22
+ # L="Albany"
23
+ # O="55 Minutes Inc."
24
+ # CN="www.55minutes.com"
25
+
26
+ if [[ $1 == --self ]]; then
27
+ SELF_SIGN=1
28
+ shift
29
+ fi
30
+
31
+ KEY_NAME=$1
32
+ CSR_CONFIG=$2
33
+
34
+ openssl req -config $CSR_CONFIG -new -newkey rsa:2048 -nodes -keyout ${KEY_NAME}.key -out ${KEY_NAME}.csr
35
+ chmod 600 ${KEY_NAME}.key ${KEY_NAME}.csr
36
+ echo "Created ${KEY_NAME}.key"
37
+ echo "Created ${KEY_NAME}.csr"
38
+
39
+ if [[ -n $SELF_SIGN ]]; then
40
+ openssl x509 -req -days 365 -in ${KEY_NAME}.csr -signkey ${KEY_NAME}.key -out ${KEY_NAME}.crt
41
+ chmod 600 ${KEY_NAME}.crt
42
+ echo "Created ${KEY_NAME}.crt (self-signed)"
43
+ fi
@@ -0,0 +1,71 @@
1
+ # Use at least one worker per core if you're on a dedicated server,
2
+ # more will usually help for _short_ waits on databases/caches.
3
+ worker_processes <%= fetch(:fiftyfive_unicorn_workers) %>
4
+
5
+ # Help ensure your application will always spawn in the symlinked
6
+ # "current" directory that Capistrano sets up.
7
+ working_directory "<%= current_path %>"
8
+
9
+ # listen on both a Unix domain socket
10
+ # we use a shorter backlog for quicker failover when busy
11
+ listen "/tmp/unicorn.<%= application_basename %>.sock", :backlog => 64
12
+
13
+ # nuke workers after <%= fetch(:fiftyfive_unicorn_timeout) %> seconds (default is 60)
14
+ timeout <%= fetch(:fiftyfive_unicorn_timeout) %>
15
+
16
+ pid "<%= fetch(:fiftyfive_unicorn_pid) %>"
17
+
18
+ # By default, the Unicorn logger will write to stderr.
19
+ # Additionally, some applications/frameworks log to stderr or stdout,
20
+ # so prevent them from going to /dev/null when daemonized here:
21
+ stderr_path "<%= fetch(:fiftyfive_unicorn_log) %>"
22
+ stdout_path "<%= fetch(:fiftyfive_unicorn_log) %>"
23
+
24
+ preload_app true
25
+
26
+ # combine Ruby 2.0.0dev or REE with "preload_app true" for memory savings
27
+ # http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
28
+ if GC.respond_to?(:copy_on_write_friendly=)
29
+ GC.copy_on_write_friendly = true
30
+ end
31
+
32
+ before_exec do |server|
33
+ # Ensure unicorn picks up our newest Gemfile
34
+ ENV['BUNDLE_GEMFILE'] = "<%= current_path %>/Gemfile"
35
+ end
36
+
37
+ before_fork do |server, worker|
38
+
39
+ # the following is highly recomended for Rails + "preload_app true"
40
+ # as there's no need for the master process to hold a connection
41
+ if defined? ActiveRecord::Base
42
+ ActiveRecord::Base.connection.disconnect!
43
+ end
44
+
45
+ # This allows a new master process to incrementally
46
+ # phase out the old master process with SIGTTOU to avoid a
47
+ # thundering herd (especially in the "preload_app false" case)
48
+ # when doing a transparent upgrade. The last worker spawned
49
+ # will then kill off the old master process with a SIGQUIT.
50
+ old_pid = "#{server.config[:pid]}.oldbin"
51
+ if File.exists?(old_pid) && server.pid != old_pid
52
+ begin
53
+ sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
54
+ Process.kill(sig, File.read(old_pid).to_i)
55
+ rescue Errno::ENOENT, Errno::ESRCH
56
+ end
57
+ end
58
+
59
+ # Throttle the master from forking too quickly by sleeping. Due
60
+ # to the implementation of standard Unix signal handlers, this
61
+ # helps (but does not completely) prevent identical, repeated signals
62
+ # from being lost when the receiving process is busy.
63
+ sleep 1
64
+ end
65
+
66
+ after_fork do |server, worker|
67
+ # the following is *required* for Rails + "preload_app true"
68
+ if defined?(ActiveRecord::Base)
69
+ ActiveRecord::Base.establish_connection
70
+ end
71
+ end
@@ -0,0 +1,84 @@
1
+ #!/bin/sh
2
+ ### BEGIN INIT INFO
3
+ # Provides: unicorn
4
+ # Required-Start: $remote_fs $syslog
5
+ # Required-Stop: $remote_fs $syslog
6
+ # Default-Start: 2 3 4 5
7
+ # Default-Stop: 0 1 6
8
+ # Short-Description: Manage unicorn server
9
+ # Description: Start, stop, restart unicorn server for a specific application.
10
+ ### END INIT INFO
11
+ set -e
12
+
13
+ # Feel free to change any of the following variables for your app:
14
+ TIMEOUT=${TIMEOUT-60}
15
+ APP_ROOT=<%= current_path %>
16
+ PID=<%= fetch(:fiftyfive_unicorn_pid) %>
17
+ CMD="cd <%= current_path %>; bundle exec unicorn -D -c <%= fetch(:fiftyfive_unicorn_config) %> -E <%= fetch(:rails_env) %>"
18
+ AS_USER=<%= unicorn_user %>
19
+ set -u
20
+
21
+ OLD_PIN="$PID.oldbin"
22
+
23
+ sig () {
24
+ test -s "$PID" && kill -$1 `cat $PID`
25
+ }
26
+
27
+ oldsig () {
28
+ test -s $OLD_PIN && kill -$1 `cat $OLD_PIN`
29
+ }
30
+
31
+ run () {
32
+ if [ "$(id -un)" = "$AS_USER" ]; then
33
+ eval $1
34
+ else
35
+ su -c "$1" - $AS_USER
36
+ fi
37
+ }
38
+
39
+ case "$1" in
40
+ start)
41
+ sig 0 && echo >&2 "Already running" && exit 0
42
+ run "$CMD"
43
+ ;;
44
+ stop)
45
+ sig QUIT && exit 0
46
+ echo >&2 "Not running"
47
+ ;;
48
+ force-stop)
49
+ sig TERM && exit 0
50
+ echo >&2 "Not running"
51
+ ;;
52
+ restart|reload)
53
+ sig USR2 && echo reloaded OK && exit 0
54
+ echo >&2 "Couldn't reload, starting '$CMD' instead"
55
+ run "$CMD"
56
+ ;;
57
+ upgrade)
58
+ if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
59
+ then
60
+ n=$TIMEOUT
61
+ while test -s $OLD_PIN && test $n -ge 0
62
+ do
63
+ printf '.' && sleep 1 && n=$(( $n - 1 ))
64
+ done
65
+ echo
66
+
67
+ if test $n -lt 0 && test -s $OLD_PIN
68
+ then
69
+ echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds"
70
+ exit 1
71
+ fi
72
+ exit 0
73
+ fi
74
+ echo >&2 "Couldn't upgrade, starting '$CMD' instead"
75
+ run "$CMD"
76
+ ;;
77
+ reopen-logs)
78
+ sig USR1
79
+ ;;
80
+ *)
81
+ echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
82
+ exit 1
83
+ ;;
84
+ esac
@@ -0,0 +1,2 @@
1
+ Rails.application.config.version = "<%= git_version[:tag] %>"
2
+ Rails.application.config.version_date = Date.parse("<%= git_version[:date] %>")
@@ -0,0 +1,5 @@
1
+ module Capistrano
2
+ module Fiftyfive
3
+ VERSION = "0.9.0"
4
+ end
5
+ end
@@ -0,0 +1,28 @@
1
+ require "monitor"
2
+ require "capistrano/fiftyfive/version"
3
+ require "capistrano/fiftyfive/compatibility"
4
+ require "capistrano/fiftyfive/dsl"
5
+ require "capistrano/fiftyfive/recipe"
6
+ require "capistrano/fiftyfive/console"
7
+ require "sshkit/formatter/abbreviated"
8
+ include Capistrano::Fiftyfive::DSL
9
+
10
+ load File.expand_path("../tasks/defaults.rake", __FILE__)
11
+ load File.expand_path("../tasks/user.rake", __FILE__)
12
+ load File.expand_path("../tasks/aptitude.rake", __FILE__)
13
+ load File.expand_path("../tasks/ufw.rake", __FILE__)
14
+ load File.expand_path("../tasks/ssl.rake", __FILE__)
15
+ load File.expand_path("../tasks/dotenv.rake", __FILE__)
16
+ load File.expand_path("../tasks/postgresql.rake", __FILE__)
17
+ load File.expand_path("../tasks/nginx.rake", __FILE__)
18
+ load File.expand_path("../tasks/unicorn.rake", __FILE__)
19
+ load File.expand_path("../tasks/delayed_job.rake", __FILE__)
20
+ load File.expand_path("../tasks/crontab.rake", __FILE__)
21
+ load File.expand_path("../tasks/logrotate.rake", __FILE__)
22
+ load File.expand_path("../tasks/rbenv.rake", __FILE__)
23
+ load File.expand_path("../tasks/maintenance.rake", __FILE__)
24
+ load File.expand_path("../tasks/migrate.rake", __FILE__)
25
+ load File.expand_path("../tasks/seed.rake", __FILE__)
26
+ load File.expand_path("../tasks/version.rake", __FILE__)
27
+ load File.expand_path("../tasks/rake.rake", __FILE__)
28
+ load File.expand_path("../tasks/sidekiq.rake", __FILE__)
@@ -0,0 +1,77 @@
1
+ fiftyfive_recipe :aptitude do
2
+ during :provision, %w(upgrade install)
3
+ end
4
+
5
+ namespace :fiftyfive do
6
+ namespace :aptitude do
7
+
8
+ desc "Run `aptitude update` and then run `aptitude safe-upgrade`"
9
+ task :upgrade do
10
+ privileged_on roles(:all) do |host|
11
+ _update
12
+ _safe_upgrade
13
+ end
14
+ end
15
+
16
+
17
+ desc "Run `aptitude install` for packages required by the roles of "\
18
+ "each server."
19
+ task :install do
20
+ privileged_on roles(:all) do |host|
21
+ packages_to_install = []
22
+ repos_to_add = []
23
+
24
+ _each_package(host) do |pkg, repo|
25
+ unless _already_installed?(pkg)
26
+ repos_to_add << repo unless repo.nil?
27
+ packages_to_install << pkg
28
+ end
29
+ end
30
+
31
+ repos_to_add.uniq.each { |repo| _add_repository(repo) }
32
+ _update
33
+ packages_to_install.uniq.each { |pkg| _install(pkg) }
34
+ end
35
+ end
36
+
37
+ def _already_installed?(pkg)
38
+ test(:dpkg, "-s", pkg, "2>/dev/null", "|", :grep, "-q 'ok installed'")
39
+ end
40
+
41
+ def _add_repository(repo)
42
+ unless _already_installed?("python-software-properties")
43
+ _install("python-software-properties")
44
+ end
45
+ execute :"apt-add-repository", "-y", repo
46
+ end
47
+
48
+ def _install(pkg)
49
+ with :debian_frontend => "noninteractive" do
50
+ execute :aptitude, "-y -q install", pkg
51
+ end
52
+ end
53
+
54
+ def _update
55
+ with :debian_frontend => "noninteractive" do
56
+ execute :aptitude, "-q -q -y update"
57
+ end
58
+ end
59
+
60
+ def _safe_upgrade
61
+ with :debian_frontend => "noninteractive" do
62
+ execute :aptitude, "-q -q -y safe-upgrade"
63
+ end
64
+ end
65
+
66
+ def _each_package(host)
67
+ return to_enum(:_each_package, host) unless block_given?
68
+
69
+ fetch(:fiftyfive_aptitude_packages).each do |package_spec, *role_list|
70
+ next unless roles(*role_list.flatten).include?(host)
71
+
72
+ pkg, repo = package_spec.split("@")
73
+ yield(pkg, repo)
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,14 @@
1
+ fiftyfive_recipe :crontab do
2
+ during :provision, "fiftyfive:crontab"
3
+ end
4
+
5
+ namespace :fiftyfive do
6
+ desc "Install crontab using crontab.erb template"
7
+ task :crontab do
8
+ on roles(:cron) do
9
+ tmp_file = "/tmp/crontab"
10
+ template "crontab.erb", tmp_file
11
+ execute "crontab #{tmp_file} && rm #{tmp_file}"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,124 @@
1
+ namespace :load do
2
+ task :defaults do
3
+
4
+ set :fiftyfive_recipes, %w(
5
+ aptitude
6
+ crontab
7
+ dotenv
8
+ logrotate
9
+ migrate
10
+ nginx
11
+ postgresql
12
+ rbenv
13
+ seed
14
+ ssl
15
+ ufw
16
+ unicorn
17
+ user
18
+ version
19
+ )
20
+
21
+ set :fiftyfive_privileged_user, "root"
22
+
23
+ set :fiftyfive_aptitude_packages,
24
+ "curl" => :all,
25
+ "debian-goodies" => :all,
26
+ "git-core" => :all,
27
+ "libpq-dev@ppa:pitti/postgresql" => :all,
28
+ "nginx@ppa:nginx/stable" => :web,
29
+ "nodejs@ppa:chris-lea/node.js" => :all,
30
+ "postgresql-client@ppa:pitti/postgresql" => :all,
31
+ "postgresql@ppa:pitti/postgresql" => :db,
32
+ "ufw" => :all
33
+
34
+ set :fiftyfive_delayed_job_args, "-n 2"
35
+ set :fiftyfive_delayed_job_script, "bin/delayed_job"
36
+
37
+ set :fiftyfive_dotenv_keys, %w(rails_secret_key_base postmark_api_key)
38
+ set :fiftyfive_dotenv_monitor, Monitor.new
39
+ set :fiftyfive_dotenv_filename, -> { ".env.#{fetch(:rails_env)}" }
40
+
41
+ set :fiftyfive_log_file, "log/capistrano.log"
42
+
43
+ set :fiftyfive_nginx_force_https, false
44
+ set :fiftyfive_nginx_redirect_hosts, {}
45
+
46
+ ask_secretly :fiftyfive_postgresql_password
47
+ set :fiftyfive_postgresql_max_connections, 25
48
+ set :fiftyfive_postgresql_pool_size, 5
49
+ set :fiftyfive_postgresql_host, "localhost"
50
+ set :fiftyfive_postgresql_database,
51
+ -> { "#{application_basename}_#{fetch(:rails_env)}" }
52
+ set :fiftyfive_postgresql_user, -> { application_basename }
53
+ set :fiftyfive_postgresql_pgpass_path,
54
+ proc{ "#{shared_path}/config/pgpass" }
55
+ set :fiftyfive_postgresql_backup_path, -> {
56
+ "#{shared_path}/backups/postgresql-dump.dmp"
57
+ }
58
+ set :fiftyfive_postgresql_backup_exclude_tables, []
59
+ set :fiftyfive_postgresql_dump_options, -> {
60
+ options = fetch(:fiftyfive_postgresql_backup_exclude_tables).map do |t|
61
+ "-T #{t.shellescape}"
62
+ end
63
+ options.join(" ")
64
+ }
65
+
66
+ set :fiftyfive_rbenv_ruby_version, -> { IO.read(".ruby-version").strip }
67
+ set :fiftyfive_rbenv_vars, -> {
68
+ {
69
+ "RAILS_ENV" => fetch(:rails_env),
70
+ "PGPASSFILE" => fetch(:fiftyfive_postgresql_pgpass_path)
71
+ }
72
+ }
73
+
74
+ set :fiftyfive_sidekiq_concurrency, 25
75
+ set :fiftyfive_sidekiq_role, :sidekiq
76
+
77
+ set :fiftyfive_ssl_csr_country, "US"
78
+ set :fiftyfive_ssl_csr_state, "California"
79
+ set :fiftyfive_ssl_csr_city, "Albany"
80
+ set :fiftyfive_ssl_csr_org, "55 Minutes, Inc."
81
+ set :fiftyfive_ssl_csr_name, "example.55minutes.com"
82
+
83
+ # WARNING: misconfiguring firewall rules could lock you out of the server!
84
+ set :fiftyfive_ufw_rules,
85
+ "allow ssh" => :all,
86
+ "allow http" => :web,
87
+ "allow https" => :web
88
+
89
+ set :fiftyfive_unicorn_workers, 2
90
+ set :fiftyfive_unicorn_timeout, 30
91
+ set :fiftyfive_unicorn_config, proc{ "#{current_path}/config/unicorn.rb" }
92
+ set :fiftyfive_unicorn_log, proc{ "#{current_path}/log/unicorn.log" }
93
+ set :fiftyfive_unicorn_pid, proc{ "#{current_path}/tmp/pids/unicorn.pid" }
94
+
95
+ set :bundle_binstubs, false
96
+ set :bundle_flags, '--deployment -j4'
97
+ set :deploy_to, -> { "/home/deployer/apps/#{fetch(:application)}" }
98
+ set :format, :abbreviated
99
+ set :keep_releases, 10
100
+ set :linked_dirs, -> {
101
+ ["public/#{fetch(:assets_prefix, 'assets')}"] +
102
+ %w(
103
+ log
104
+ tmp/pids
105
+ tmp/cache
106
+ tmp/sockets
107
+ public/system
108
+ )
109
+ }
110
+ set :linked_files, -> {
111
+ [fetch(:fiftyfive_dotenv_filename)] +
112
+ %w(
113
+ config/database.yml
114
+ config/unicorn.rb
115
+ )
116
+ }
117
+ set :log_level, :debug
118
+ set :migration_role, :app
119
+ set :rails_env, -> { fetch(:stage) }
120
+ set :ssh_options, :compression => false, :keepalive => true
121
+
122
+ SSHKit.config.command_map[:rake] = "bundle exec rake"
123
+ end
124
+ end