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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +164 -0
- data/Rakefile +1 -0
- data/capistrano-fiftyfive.gemspec +30 -0
- data/lib/capistrano/fiftyfive/compatibility.rb +17 -0
- data/lib/capistrano/fiftyfive/console.rb +61 -0
- data/lib/capistrano/fiftyfive/dsl.rb +140 -0
- data/lib/capistrano/fiftyfive/recipe.rb +48 -0
- data/lib/capistrano/fiftyfive/templates/crontab.erb +1 -0
- data/lib/capistrano/fiftyfive/templates/csr_config.erb +10 -0
- data/lib/capistrano/fiftyfive/templates/delayed_job_init.erb +36 -0
- data/lib/capistrano/fiftyfive/templates/logrotate.erb +9 -0
- data/lib/capistrano/fiftyfive/templates/maintenance.html.erb +26 -0
- data/lib/capistrano/fiftyfive/templates/nginx.erb +60 -0
- data/lib/capistrano/fiftyfive/templates/nginx_unicorn.erb +100 -0
- data/lib/capistrano/fiftyfive/templates/pgpass.erb +1 -0
- data/lib/capistrano/fiftyfive/templates/postgresql-backup-logrotate.erb +11 -0
- data/lib/capistrano/fiftyfive/templates/postgresql.yml.erb +8 -0
- data/lib/capistrano/fiftyfive/templates/rbenv_bashrc +4 -0
- data/lib/capistrano/fiftyfive/templates/sidekiq_init.erb +100 -0
- data/lib/capistrano/fiftyfive/templates/ssl_setup +43 -0
- data/lib/capistrano/fiftyfive/templates/unicorn.rb.erb +71 -0
- data/lib/capistrano/fiftyfive/templates/unicorn_init.erb +84 -0
- data/lib/capistrano/fiftyfive/templates/version.rb.erb +2 -0
- data/lib/capistrano/fiftyfive/version.rb +5 -0
- data/lib/capistrano/fiftyfive.rb +28 -0
- data/lib/capistrano/tasks/aptitude.rake +77 -0
- data/lib/capistrano/tasks/crontab.rake +14 -0
- data/lib/capistrano/tasks/defaults.rake +124 -0
- data/lib/capistrano/tasks/delayed_job.rake +32 -0
- data/lib/capistrano/tasks/dotenv.rake +53 -0
- data/lib/capistrano/tasks/logrotate.rake +15 -0
- data/lib/capistrano/tasks/maintenance.rake +28 -0
- data/lib/capistrano/tasks/migrate.rake +29 -0
- data/lib/capistrano/tasks/nginx.rake +30 -0
- data/lib/capistrano/tasks/postgresql.rake +103 -0
- data/lib/capistrano/tasks/rake.rake +20 -0
- data/lib/capistrano/tasks/rbenv.rake +92 -0
- data/lib/capistrano/tasks/seed.rake +16 -0
- data/lib/capistrano/tasks/sidekiq.rake +38 -0
- data/lib/capistrano/tasks/ssl.rake +52 -0
- data/lib/capistrano/tasks/ufw.rake +32 -0
- data/lib/capistrano/tasks/unicorn.rake +41 -0
- data/lib/capistrano/tasks/user.rake +29 -0
- data/lib/capistrano/tasks/version.rake +31 -0
- data/lib/sshkit/formatter/abbreviated.rb +148 -0
- 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,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,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
|