capistrano-atlas 0.0.1
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 +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +215 -0
- data/Rakefile +5 -0
- data/capistrano-atlas.gemspec +32 -0
- data/lib/capistrano/atlas.rb +27 -0
- data/lib/capistrano/atlas/compatibility.rb +37 -0
- data/lib/capistrano/atlas/dsl.rb +157 -0
- data/lib/capistrano/atlas/recipe.rb +49 -0
- data/lib/capistrano/atlas/templates/crontab.erb +1 -0
- data/lib/capistrano/atlas/templates/csr_config.erb +10 -0
- data/lib/capistrano/atlas/templates/logrotate.erb +9 -0
- data/lib/capistrano/atlas/templates/maintenance.html.erb +26 -0
- data/lib/capistrano/atlas/templates/nginx.erb +64 -0
- data/lib/capistrano/atlas/templates/nginx_site.erb +97 -0
- data/lib/capistrano/atlas/templates/pgpass.erb +1 -0
- data/lib/capistrano/atlas/templates/postgresql-backup-logrotate.erb +11 -0
- data/lib/capistrano/atlas/templates/puma.rb.erb +22 -0
- data/lib/capistrano/atlas/templates/puma_init.erb +43 -0
- data/lib/capistrano/atlas/templates/rbenv_bashrc +4 -0
- data/lib/capistrano/atlas/templates/sidekiq_init.erb +100 -0
- data/lib/capistrano/atlas/templates/ssl_setup +43 -0
- data/lib/capistrano/atlas/templates/version.rb.erb +3 -0
- data/lib/capistrano/atlas/version.rb +5 -0
- data/lib/capistrano/tasks/aptitude.rake +111 -0
- data/lib/capistrano/tasks/bundler.rake +31 -0
- data/lib/capistrano/tasks/crontab.rake +14 -0
- data/lib/capistrano/tasks/defaults.rake +137 -0
- data/lib/capistrano/tasks/dotenv.rake +57 -0
- data/lib/capistrano/tasks/logrotate.rake +16 -0
- data/lib/capistrano/tasks/maintenance.rake +28 -0
- data/lib/capistrano/tasks/migrate.rake +29 -0
- data/lib/capistrano/tasks/nginx.rake +25 -0
- data/lib/capistrano/tasks/postgresql.rake +149 -0
- data/lib/capistrano/tasks/provision.rake +18 -0
- data/lib/capistrano/tasks/puma.rake +67 -0
- data/lib/capistrano/tasks/rake.rake +20 -0
- data/lib/capistrano/tasks/rbenv.rake +104 -0
- data/lib/capistrano/tasks/seed.rake +16 -0
- data/lib/capistrano/tasks/sidekiq.rake +42 -0
- data/lib/capistrano/tasks/ssl.rake +57 -0
- data/lib/capistrano/tasks/ufw.rake +32 -0
- data/lib/capistrano/tasks/user.rake +32 -0
- data/lib/capistrano/tasks/version.rake +34 -0
- metadata +161 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
module Capistrano
|
2
|
+
module Atlas
|
3
|
+
class Recipe
|
4
|
+
attr_reader :name
|
5
|
+
|
6
|
+
def initialize(name)
|
7
|
+
@name = name.to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
def enabled?
|
11
|
+
fetch(:atlas_recipes, []).map(&:to_s).include?(name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def prior_to(task_to_extend, *recipe_tasks)
|
15
|
+
inject_tasks(:before, task_to_extend, *recipe_tasks)
|
16
|
+
end
|
17
|
+
|
18
|
+
def during(task_to_extend, *recipe_tasks)
|
19
|
+
inject_tasks(:after, task_to_extend, *recipe_tasks)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def inject_tasks(method, task_to_extend, *recipe_tasks)
|
25
|
+
create_task_unless_exists(task_to_extend)
|
26
|
+
|
27
|
+
recipe_tasks.flatten.each do |task|
|
28
|
+
qualified_task = apply_namespace(task)
|
29
|
+
create_task_unless_exists("#{qualified_task}:if_enabled") do
|
30
|
+
invoke qualified_task if enabled?
|
31
|
+
end
|
32
|
+
send(method, task_to_extend, "#{qualified_task}:if_enabled")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def apply_namespace(task_name)
|
37
|
+
return task_name if task_name.include?(":")
|
38
|
+
|
39
|
+
"atlas:#{name}:#{task_name}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_task_unless_exists(task_name, &block)
|
43
|
+
unless Rake::Task.task_defined?(task_name)
|
44
|
+
Rake::Task.define_task(task_name, &block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# Sample crontab (empty)
|
@@ -0,0 +1,10 @@
|
|
1
|
+
[ req ]
|
2
|
+
distinguished_name="req_distinguished_name"
|
3
|
+
prompt="no"
|
4
|
+
|
5
|
+
[ req_distinguished_name ]
|
6
|
+
C="<%= fetch(:atlas_ssl_csr_country) %>"
|
7
|
+
ST="<%= fetch(:atlas_ssl_csr_state) %>"
|
8
|
+
L="<%= fetch(:atlas_ssl_csr_city) %>"
|
9
|
+
O="<%= fetch(:atlas_ssl_csr_org) %>"
|
10
|
+
CN="<%= fetch(:atlas_ssl_csr_name) %>"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<title>Maintenance</title>
|
6
|
+
<style type="text/css">
|
7
|
+
body {
|
8
|
+
width: 500px;
|
9
|
+
margin: 100px auto;
|
10
|
+
font: 300 120% "OpenSans", "Helvetica Neue", "Helvetica", Arial, Verdana, sans-serif;
|
11
|
+
}
|
12
|
+
|
13
|
+
h1 {
|
14
|
+
font-weight: 300;
|
15
|
+
}
|
16
|
+
</style>
|
17
|
+
</head>
|
18
|
+
<body>
|
19
|
+
<h1>Maintenance</h1>
|
20
|
+
|
21
|
+
<p>Our systems are currently down for <%= reason ? reason : "maintenance" %><br>
|
22
|
+
as of <%= Time.now.strftime("%H:%M %Z") %>.</p>
|
23
|
+
|
24
|
+
<p>We’ll be back <%= deadline ? deadline : "shortly" %>.</p>
|
25
|
+
</body>
|
26
|
+
</html>
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Based on https://github.com/defunkt/unicorn/blob/master/examples/nginx.conf
|
2
|
+
|
3
|
+
user www-data;
|
4
|
+
pid /run/nginx.pid;
|
5
|
+
error_log /var/log/nginx/error.log;
|
6
|
+
|
7
|
+
# you generally only need one nginx worker unless you're serving
|
8
|
+
# large amounts of static files which require blocking disk reads
|
9
|
+
worker_processes 1;
|
10
|
+
|
11
|
+
events {
|
12
|
+
worker_connections 1024; # increase if you have lots of clients
|
13
|
+
accept_mutex off; # "on" if nginx worker_processes > 1
|
14
|
+
use epoll; # for Linux 2.6+
|
15
|
+
}
|
16
|
+
|
17
|
+
http {
|
18
|
+
# ensure nginx is able to load lots of third-party modules
|
19
|
+
types_hash_max_size 2048;
|
20
|
+
server_names_hash_bucket_size 64;
|
21
|
+
|
22
|
+
# nginx will find this file in the config directory set at nginx build time
|
23
|
+
include mime.types;
|
24
|
+
|
25
|
+
# fallback in case we can't determine a type
|
26
|
+
default_type application/octet-stream;
|
27
|
+
|
28
|
+
# click tracking!
|
29
|
+
access_log /var/log/nginx/access.log combined;
|
30
|
+
|
31
|
+
# you generally want to serve static files with nginx since neither
|
32
|
+
# Unicorn nor Rainbows! is optimized for it at the moment
|
33
|
+
sendfile on;
|
34
|
+
|
35
|
+
# configure reverse proxy cache
|
36
|
+
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=default:8m max_size=1000m inactive=30d;
|
37
|
+
proxy_temp_path /var/cache/nginx/tmp;
|
38
|
+
|
39
|
+
tcp_nopush on; # off may be better for *some* Comet/long-poll stuff
|
40
|
+
tcp_nodelay off; # on may be better for some Comet/long-poll stuff
|
41
|
+
|
42
|
+
# we haven't checked to see if Rack::Deflate on the app server is
|
43
|
+
# faster or not than doing compression via nginx. It's easier
|
44
|
+
# to configure it all in one place here for static files and also
|
45
|
+
# to disable gzip for clients who don't get gzip/deflate right.
|
46
|
+
# There are other gzip settings that may be needed used to deal with
|
47
|
+
# bad clients out there, see http://wiki.nginx.org/NginxHttpGzipModule
|
48
|
+
gzip on;
|
49
|
+
gzip_http_version 1.0;
|
50
|
+
gzip_proxied any;
|
51
|
+
gzip_min_length 500;
|
52
|
+
gzip_disable "MSIE [1-6]\.";
|
53
|
+
gzip_types text/plain text/xml text/css
|
54
|
+
text/comma-separated-values
|
55
|
+
text/javascript application/x-javascript
|
56
|
+
application/atom+xml;
|
57
|
+
|
58
|
+
|
59
|
+
# Allow SSL session resumption
|
60
|
+
ssl_session_cache shared:SSL:10m;
|
61
|
+
|
62
|
+
include /etc/nginx/conf.d/*.conf;
|
63
|
+
include /etc/nginx/sites-enabled/*;
|
64
|
+
}
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# Based on https://github.com/defunkt/unicorn/blob/master/examples/nginx.conf
|
2
|
+
|
3
|
+
upstream <%= fetch(:atlas_server_name) %>_<%= application_basename %> {
|
4
|
+
server unix:/tmp/<%= fetch(:atlas_server_name) %>.<%= application_basename %>.sock fail_timeout=0;
|
5
|
+
}
|
6
|
+
|
7
|
+
<% [80, 443].each do |port| %>
|
8
|
+
|
9
|
+
<% fetch(:atlas_nginx_redirect_hosts).each do |orig, desired| %>
|
10
|
+
server {
|
11
|
+
listen <%= port %>;
|
12
|
+
server_name <%= orig %>;
|
13
|
+
return 301 <%= fetch(:atlas_nginx_force_https) ? "https" : "$scheme" %>://<%= desired %>$request_uri;
|
14
|
+
}
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
server {
|
18
|
+
listen <%= port %> <%= "spdy" if port == 443 %> default deferred; # for Linux
|
19
|
+
|
20
|
+
<% if port == 80 && fetch(:atlas_nginx_force_https) %>
|
21
|
+
rewrite ^(.*) https://$http_host$1 permanent;
|
22
|
+
<% else %>
|
23
|
+
|
24
|
+
client_max_body_size 4G;
|
25
|
+
server_name _;
|
26
|
+
|
27
|
+
# ~2 seconds is often enough for most folks to parse HTML/CSS and
|
28
|
+
# retrieve needed images/icons/frames, connections are cheap in
|
29
|
+
# nginx so increasing this is generally safe...
|
30
|
+
keepalive_timeout 5;
|
31
|
+
|
32
|
+
# path for static files
|
33
|
+
root <%= current_path %>/public;
|
34
|
+
|
35
|
+
# Capistrano `deploy:web:disable` support
|
36
|
+
if (-f $document_root/system/maintenance.html) {
|
37
|
+
return 503;
|
38
|
+
}
|
39
|
+
error_page 503 @maintenance;
|
40
|
+
location @maintenance {
|
41
|
+
rewrite ^(.*)$ /system/maintenance.html last;
|
42
|
+
break;
|
43
|
+
}
|
44
|
+
|
45
|
+
<% if port == 443 %>
|
46
|
+
ssl on;
|
47
|
+
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:RSA+3DES:!ADH:!AECDH:!MD5;
|
48
|
+
ssl_prefer_server_ciphers on;
|
49
|
+
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
50
|
+
ssl_certificate /etc/ssl/<%= application_basename %>.crt;
|
51
|
+
ssl_certificate_key /etc/ssl/<%= application_basename %>.key;
|
52
|
+
|
53
|
+
<% if fetch(:atlas_nginx_force_https) %>
|
54
|
+
add_header Strict-Transport-Security "max-age=631138519";
|
55
|
+
<% end %>
|
56
|
+
<% end %>
|
57
|
+
|
58
|
+
# Far-future expires and gzip for fingerprinted assets
|
59
|
+
location ^~ /<%= fetch(:assets_prefix, "assets") %>/ {
|
60
|
+
gzip_static on;
|
61
|
+
expires max;
|
62
|
+
add_header Cache-Control public;
|
63
|
+
}
|
64
|
+
|
65
|
+
include /etc/nginx/<%= application_basename%>-locations/*;
|
66
|
+
|
67
|
+
# Prefer to serve static files directly from nginx to avoid unnecessary
|
68
|
+
# data copies from the application server.
|
69
|
+
try_files $uri/index.html $uri @<%= fetch(:atlas_server_name) %>;
|
70
|
+
|
71
|
+
location @<%= fetch(:atlas_server_name) %> {
|
72
|
+
# an HTTP header important enough to have its own Wikipedia entry:
|
73
|
+
# http://en.wikipedia.org/wiki/X-Forwarded-For
|
74
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
75
|
+
|
76
|
+
# this helps Rack set the proper URL scheme for doing HTTPS redirects:
|
77
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
78
|
+
|
79
|
+
# pass the Host: header from the client right along so redirects
|
80
|
+
# can be set properly within the Rack application
|
81
|
+
proxy_set_header Host $http_host;
|
82
|
+
|
83
|
+
# we don't want nginx trying to do something clever with
|
84
|
+
# redirects, we set the Host: header above already.
|
85
|
+
proxy_redirect off;
|
86
|
+
|
87
|
+
proxy_pass http://<%= fetch(:atlas_server_name) %>_<%= application_basename %>;
|
88
|
+
}
|
89
|
+
|
90
|
+
# Rails error pages
|
91
|
+
error_page 500 502 503 504 /500.html;
|
92
|
+
location = /500.html {
|
93
|
+
root <%= current_path %>/public;
|
94
|
+
}
|
95
|
+
<% end %>
|
96
|
+
}
|
97
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= fetch(:atlas_postgresql_host) %>:5432:<%= fetch(:atlas_postgresql_database) %>:<%= fetch(:atlas_postgresql_user) %>:<%= fetch(:atlas_postgresql_password).gsub(/([\\:])/, '\\\\\1') %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%= fetch(:atlas_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(:atlas_postgresql_pgpass_path) %> /usr/bin/pg_dump -Fc -Z9 -O -x <%= fetch(:atlas_postgresql_dump_options) %> -h <%= fetch(:atlas_postgresql_host) %> -U <%= fetch(:atlas_postgresql_user) %> -f <%= fetch(:atlas_postgresql_backup_path) %> <%= fetch(:atlas_postgresql_database) %>
|
10
|
+
endscript
|
11
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env puma
|
2
|
+
|
3
|
+
directory "<%= current_path %>"
|
4
|
+
environment "<%= fetch(:rails_env) %>"
|
5
|
+
|
6
|
+
daemonize
|
7
|
+
pidfile "<%= fetch(:atlas_puma_pid) %>"
|
8
|
+
state_path "<%= current_path %>/tmp/pids/puma.state"
|
9
|
+
stdout_redirect "<%= fetch(:atlas_puma_stdout_log) %>",
|
10
|
+
"<%= fetch(:atlas_puma_stderr_log) %>",
|
11
|
+
true
|
12
|
+
|
13
|
+
threads <%= fetch(:atlas_puma_threads) %>
|
14
|
+
|
15
|
+
<% if fetch(:atlas_puma_workers, 0) > 1 %>
|
16
|
+
workers <%= fetch(:atlas_puma_workers) %>
|
17
|
+
worker_timeout <%= fetch(:atlas_puma_timeout) %>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
bind "unix:/tmp/puma.<%= application_basename %>.sock"
|
21
|
+
prune_bundler
|
22
|
+
tag "<%= application_basename %>"
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
### BEGIN INIT INFO
|
3
|
+
# Provides: puma
|
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 puma server
|
9
|
+
# Description: Start, stop, restart puma server for a specific application.
|
10
|
+
### END INIT INFO
|
11
|
+
set -e
|
12
|
+
|
13
|
+
APP_ROOT=<%= current_path %>
|
14
|
+
PUMACTL_CMD="cd <%= current_path %>; bundle exec pumactl -F <%= fetch(:atlas_puma_config) %>"
|
15
|
+
AS_USER=<%= puma_user %>
|
16
|
+
set -u
|
17
|
+
|
18
|
+
pumactl () {
|
19
|
+
if [ "$(id -un)" = "$AS_USER" ]; then
|
20
|
+
eval $PUMACTL_CMD $1
|
21
|
+
else
|
22
|
+
su -c "$PUMACTL_CMD $1" - $AS_USER
|
23
|
+
fi
|
24
|
+
}
|
25
|
+
|
26
|
+
case "$1" in
|
27
|
+
start)
|
28
|
+
pumactl "start"
|
29
|
+
;;
|
30
|
+
stop)
|
31
|
+
pumactl "stop"
|
32
|
+
;;
|
33
|
+
restart|reload)
|
34
|
+
pumactl "phased-restart"
|
35
|
+
;;
|
36
|
+
status)
|
37
|
+
pumactl "status"
|
38
|
+
;;
|
39
|
+
*)
|
40
|
+
echo >&2 "Usage: $0 <start|stop|restart|status>"
|
41
|
+
exit 1
|
42
|
+
;;
|
43
|
+
esac
|
@@ -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(:atlas_sidekiq_user, user) %>
|
20
|
+
CONCURRENCY=<%= fetch(:atlas_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
|