capistrano-fiftyfive 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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