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