negroku 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +29 -0
- data/bin/negroku +9 -0
- data/lib/negroku/cli.rb +147 -0
- data/lib/negroku/config.rb +36 -0
- data/lib/negroku/deploy.rb +30 -0
- data/lib/negroku/helpers.rb +69 -0
- data/lib/negroku/tasks/base.rb +51 -0
- data/lib/negroku/tasks/log.rb +33 -0
- data/lib/negroku/tasks/nginx.rb +54 -0
- data/lib/negroku/tasks/rbenv.rb +12 -0
- data/lib/negroku/tasks/templates/nginx.erb +90 -0
- data/lib/negroku/tasks/templates/unicorn.erb +51 -0
- data/lib/negroku/tasks/unicorn.rb +55 -0
- data/lib/negroku/templates/deploy.rb.erb +18 -0
- data/lib/negroku/version.rb +3 -0
- data/lib/negroku.rb +7 -0
- metadata +143 -0
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Negroku
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'negroku'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install negroku
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/bin/negroku
ADDED
data/lib/negroku/cli.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'rainbow'
|
3
|
+
require 'highline/import'
|
4
|
+
|
5
|
+
class App < Thor
|
6
|
+
|
7
|
+
say "\n\n#############################################".bright()
|
8
|
+
say "## NEGROKU ##".bright()
|
9
|
+
say "#############################################\n".bright()
|
10
|
+
|
11
|
+
desc "create", "Create application. Intialize the capfile, also create the deploy.rb file in the config folder"
|
12
|
+
method_option :local_recipes, :type => :boolean, :aliases => "-l"
|
13
|
+
method_option :path, :type => :string, :aliases => "-p"
|
14
|
+
def create(name=nil)
|
15
|
+
say "We're about to create your application deploy setup\n".foreground(:green)
|
16
|
+
|
17
|
+
# Hash to hold the app info
|
18
|
+
data = {}
|
19
|
+
|
20
|
+
# Get the name
|
21
|
+
if name.nil?
|
22
|
+
data[:application_name] = ask "Give your application a name:".bright()
|
23
|
+
else
|
24
|
+
data[:application_name] = name
|
25
|
+
end
|
26
|
+
|
27
|
+
# The application code repository
|
28
|
+
config = YAML.load_file(CONFIG_FILE) || {}
|
29
|
+
choose do |menu|
|
30
|
+
|
31
|
+
say "\nREPOSITORIES".foreground(:yellow)
|
32
|
+
menu.prompt = "Please choose your repository?".bright()
|
33
|
+
|
34
|
+
config["repo"].each do |val|
|
35
|
+
menu.choice(val) do |command|
|
36
|
+
say("Using #{command}/#{data[:application_name]}.git")
|
37
|
+
data[:repo] = command;
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
menu.choice(:other) {
|
42
|
+
data[:repo] = ask "Type the url and username e.g. git@github.com:username".bright()
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
# The application target deploy server
|
47
|
+
choose do |menu|
|
48
|
+
|
49
|
+
say "\nTARGET SERVERS".foreground(:yellow)
|
50
|
+
menu.prompt = "Please choose your deployment server?".bright()
|
51
|
+
|
52
|
+
config["target"].each do |val|
|
53
|
+
menu.choice(val) do |command|
|
54
|
+
say("Using #{command}")
|
55
|
+
data[:target_server] = command;
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
menu.choice(:other) {
|
60
|
+
data[:target_server] = ask "Type the hostname or ip of the server to deploy to".bright()
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
init(".", data)
|
65
|
+
end
|
66
|
+
|
67
|
+
desc "deploy", "Deploy the application"
|
68
|
+
def deploy
|
69
|
+
put "I will deploy"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Repo < Thor
|
74
|
+
|
75
|
+
desc "add", "add new default repositories"
|
76
|
+
def add(url=nil)
|
77
|
+
if url.nil?
|
78
|
+
url = ask("Type the url and username e.g. git@github.com:username")
|
79
|
+
end
|
80
|
+
saveConfig("add", "repo", url)
|
81
|
+
end
|
82
|
+
|
83
|
+
desc "remove", "remove some repo"
|
84
|
+
def remove
|
85
|
+
puts "I will remove a repo"
|
86
|
+
end
|
87
|
+
|
88
|
+
desc "list", "show the repost"
|
89
|
+
def list
|
90
|
+
puts "I will list the target servers"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class Target < Thor
|
95
|
+
desc "add", "add new default target server"
|
96
|
+
def add(host=nil)
|
97
|
+
if host.nil?
|
98
|
+
host = ask("Type the host or ip for the target machine")
|
99
|
+
end
|
100
|
+
saveConfig("add", "target", host)
|
101
|
+
end
|
102
|
+
|
103
|
+
desc "remove", "remove some target"
|
104
|
+
def remove
|
105
|
+
puts "I will remove a target"
|
106
|
+
end
|
107
|
+
|
108
|
+
desc "list", "show the targets"
|
109
|
+
def list
|
110
|
+
puts "I will list the target servers"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class Hosts < Thor
|
115
|
+
desc "add", "add new default target server"
|
116
|
+
def add(host=nil)
|
117
|
+
if host.nil?
|
118
|
+
host = ask("Type the host or ip for the target machine")
|
119
|
+
end
|
120
|
+
saveConfig("add", "target", host)
|
121
|
+
end
|
122
|
+
|
123
|
+
desc "remove", "remove some target"
|
124
|
+
def remove
|
125
|
+
puts "I will remove a target"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class Konfig < Thor
|
130
|
+
namespace "config"
|
131
|
+
|
132
|
+
desc "show", "Show the current configuration file"
|
133
|
+
|
134
|
+
def show
|
135
|
+
showConfig
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
module Negroku
|
140
|
+
class CLI < Thor
|
141
|
+
register(App, 'app', 'app [COMMAND]', 'Application')
|
142
|
+
register(Repo, 'repo', 'repo [COMMAND]', 'Repositories')
|
143
|
+
register(Target, 'target', 'target [COMMAND]', 'Target servers')
|
144
|
+
register(Hosts, 'host', 'host [COMMAND]', 'Hosts')
|
145
|
+
register(Konfig, 'config', 'config [COMMAND]', 'Configuration')
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
# the yaml file where we'll write the settings
|
4
|
+
CONFIG_FILE = File.join(ENV['HOME'], ".negroku", "config.yaml")
|
5
|
+
|
6
|
+
def saveConfig(action, type, data)
|
7
|
+
# create the ~/.negroku folder
|
8
|
+
unless File.directory?(File.join(ENV['HOME'], ".negroku"))
|
9
|
+
puts "[Negroku] => Creating config file in #{ENV['HOME']}/.negroku"
|
10
|
+
%x(mkdir #{File.join(ENV['HOME'], ".negroku")})
|
11
|
+
end
|
12
|
+
|
13
|
+
# create an empty config.yaml file
|
14
|
+
unless File.exist?(CONFIG_FILE)
|
15
|
+
%x(touch #{CONFIG_FILE})
|
16
|
+
end
|
17
|
+
|
18
|
+
# Load the yaml file
|
19
|
+
config = YAML.load_file(CONFIG_FILE) || {}
|
20
|
+
|
21
|
+
# If I need to add some multiple values
|
22
|
+
if action == "add"
|
23
|
+
newData = config[type] || []
|
24
|
+
newData.push(data)
|
25
|
+
newData.uniq!
|
26
|
+
config = config.merge({ type => newData })
|
27
|
+
elsif action == "remove"
|
28
|
+
#..
|
29
|
+
elsif action == "replace"
|
30
|
+
#..
|
31
|
+
end
|
32
|
+
|
33
|
+
File.open(CONFIG_FILE, 'w') do |f|
|
34
|
+
f.write config.to_yaml
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
##
|
2
|
+
# Load Deployer Helpers
|
3
|
+
require File.join(File.dirname(__FILE__), 'helpers')
|
4
|
+
|
5
|
+
set :scm, 'git'
|
6
|
+
set :deploy_via, :remote_cache
|
7
|
+
set :use_sudo, false
|
8
|
+
|
9
|
+
##
|
10
|
+
# Default Configuration
|
11
|
+
set :remote, 'origin' unless respond_to?(:remote)
|
12
|
+
set :branch, 'master' unless respond_to?(:branch)
|
13
|
+
|
14
|
+
## Default path
|
15
|
+
set :default_environment, {
|
16
|
+
'PATH' => "$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"
|
17
|
+
}
|
18
|
+
|
19
|
+
# Run on Linux: `$ ssh-add` or on OSX: `$ ssh-add -K` for "forward_agent".
|
20
|
+
ssh_options[:forward_agent] = true
|
21
|
+
ssh_options[:port] = 22
|
22
|
+
default_run_options[:pty] = true
|
23
|
+
|
24
|
+
##
|
25
|
+
# Load Deployment Tasks
|
26
|
+
load_tasks('base')
|
27
|
+
load_tasks('log')
|
28
|
+
load_tasks('rbenv')
|
29
|
+
load_tasks('nginx')
|
30
|
+
load_tasks('unicorn')
|
@@ -0,0 +1,69 @@
|
|
1
|
+
def init(target=".", data)
|
2
|
+
puts target
|
3
|
+
# Create the cap file if not found
|
4
|
+
if Dir.entries(target).include?("Capfile")
|
5
|
+
puts "[Negroku] => Found Capfile!"
|
6
|
+
else
|
7
|
+
puts "[Negroku] => Capifying!"
|
8
|
+
`capify #{File.expand_path(target)}`
|
9
|
+
end
|
10
|
+
path = File.expand_path(target)
|
11
|
+
capfile = File.expand_path(File.join(target, "Capfile"))
|
12
|
+
|
13
|
+
# Find or create config folder
|
14
|
+
unless File.directory?(File.join(path, "config"))
|
15
|
+
puts "[Negroku] => Could not find the \"config\" folder. Creating it now!"
|
16
|
+
%x(mkdir #{File.join(path, 'config')})
|
17
|
+
end
|
18
|
+
|
19
|
+
# replace and rename older deploy.rb
|
20
|
+
if File.exist?(File.join(path, "config", "deploy.rb"))
|
21
|
+
puts "[Negroku] => Backing up deploy.rb"
|
22
|
+
old_versions = Dir.entries(File.join(path, 'config')).map {|entree| entree if entree =~ /deploy\.old\.(\d+)\.rb$/}.compact!
|
23
|
+
if old_versions.empty?
|
24
|
+
%x(mv #{File.join(path, 'config', 'deploy.rb')} #{File.join(path, 'config', 'deploy.old.1.rb')})
|
25
|
+
else
|
26
|
+
version = old_versions.last.match('^deploy\.old\.(\d+)\.rb$')[1].to_i + 1
|
27
|
+
%x(mv #{File.join(path, 'config', 'deploy.rb')} #{File.join(path, 'config', "deploy.old.#{version}.rb")})
|
28
|
+
end
|
29
|
+
else
|
30
|
+
puts "[Negroku] => Could not find deploy.rb. Creating a new one!"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Create the new deploy
|
34
|
+
puts "[Negroku] => Writing new deploy.rb."
|
35
|
+
erb = File.read(File.join(File.dirname(__FILE__), 'templates', 'deploy.rb.erb'))
|
36
|
+
File.open(File.join(path, 'config', 'deploy.rb'), 'w') do |f|
|
37
|
+
f.write ERB.new(erb).result(binding)
|
38
|
+
end
|
39
|
+
|
40
|
+
# checks for both require "negroku" and require "negroku/initializer"
|
41
|
+
unless File.open(File.join('Capfile'), 'r').read.include?('require "negroku"')
|
42
|
+
puts "[Negroku] => Adding Negroku Loader inside #{path}/Capfile."
|
43
|
+
File.open(File.join(path, 'Capfile'), "a") do |cfile|
|
44
|
+
cfile << <<-capfile
|
45
|
+
\n
|
46
|
+
require "negroku"
|
47
|
+
load negroku
|
48
|
+
capfile
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def showConfig()
|
54
|
+
# Load the yaml file
|
55
|
+
config = YAML.load_file(CONFIG_FILE) || {}
|
56
|
+
puts config
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Helper Method that assists in loading in tasks from the tasks folder
|
61
|
+
def load_tasks(tasks)
|
62
|
+
load File.join(File.dirname(__FILE__), 'tasks', "#{tasks}.rb")
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Returns the RAILS_ENV=production string to reduce overhead
|
67
|
+
def env
|
68
|
+
"RAILS_ENV=production"
|
69
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Wrapper method for quickly loading, rendering ERB templates
|
2
|
+
# and uploading them to the server.
|
3
|
+
def template(from, to)
|
4
|
+
erb = File.read(File.expand_path("../templates/#{from}", __FILE__))
|
5
|
+
put ERB.new(erb).result(binding), to
|
6
|
+
end
|
7
|
+
|
8
|
+
# Wrapper method to set default values for recipes.
|
9
|
+
def set_default(name, *args, &block)
|
10
|
+
set(name, *args, &block) unless exists?(name)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Review and modify the tasks below on a per-app/language/framework basis.
|
14
|
+
namespace :deploy do
|
15
|
+
after "deploy:update_code", "deploy:post"
|
16
|
+
desc "Performs the post-deploy tasks."
|
17
|
+
task :post do
|
18
|
+
symlinks
|
19
|
+
migrate
|
20
|
+
assets
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "Performs an Active Record migration."
|
24
|
+
task :migrate do
|
25
|
+
run "cd '#{release_path}' && #{env} rake db:migrate"
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Precompiles assets from Rails' asset pipeline."
|
29
|
+
task :assets do
|
30
|
+
run "cd '#{release_path}' && #{env} rake assets:precompile"
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Sets up additional symlinks after deploy."
|
34
|
+
task :symlinks do
|
35
|
+
# Exmaple:
|
36
|
+
# run "ln -nfs '#{shared_path}/db/production.sqlite3' '#{release_path}/db/production.sqlite3'"
|
37
|
+
end
|
38
|
+
|
39
|
+
after "deploy:setup", "deploy:setup_shared"
|
40
|
+
desc "Sets up additional folders/files after deploy:setup."
|
41
|
+
task :setup_shared do
|
42
|
+
run "mkdir -p '#{shared_path}/config'"
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Restarts the app server."
|
46
|
+
task :restart do
|
47
|
+
# Example:
|
48
|
+
# restart_torquebox_app
|
49
|
+
# restart_upstart_app
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Conventient tasks for remotely tail'ing log files.
|
2
|
+
# Available logs that can be streamed out of the box:
|
3
|
+
#
|
4
|
+
# * production.log (your application's production log)
|
5
|
+
# * torquebox.log (your torquebox log)
|
6
|
+
# * <application>-nginx-access.log (the nginx access log specific to <application> only.)
|
7
|
+
# * <application>-nginx-error.log (the nginx error log specific to <application> only.)
|
8
|
+
|
9
|
+
namespace :log do
|
10
|
+
desc "Stream (tail) the application's production log."
|
11
|
+
task :app do
|
12
|
+
trap("INT") { puts 'Exit'; exit 0; }
|
13
|
+
stream "tail -f '#{shared_path}/log/production.log'"
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Stream (tail) the nginx access log."
|
17
|
+
task :nginx_access do
|
18
|
+
trap("INT") { puts 'Exit'; exit 0; }
|
19
|
+
stream "tail -f '/home/#{fetch(:user)}/log/#{fetch(:application)}-nginx-access.log'"
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Stream (tail) the nginx error log."
|
23
|
+
task :nginx_error do
|
24
|
+
trap("INT") { puts 'Exit'; exit 0; }
|
25
|
+
stream "tail -f '/home/#{fetch(:user)}/log/#{fetch(:application)}-nginx-error.log'"
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Stream (tail) the unicorn error log."
|
29
|
+
task :unicorn_error do
|
30
|
+
trap("INT") { puts 'Exit'; exit 0; }
|
31
|
+
stream "tail -f '#{fetch(:current_path)}/log/unicorn-error.log'"
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Define the domains in an Array, these will be embedded in the uploaded nginx configuration file.
|
2
|
+
# Define either the app_server_port or app_server_socket when enabling app_server, else leave it blank.
|
3
|
+
# Places the SSL certs in /home/<user>/ssl/<application>.key and /home/<user>/ssl/<application>.crt when
|
4
|
+
# setting use_ssl to true.
|
5
|
+
# Define the `static_dir`, in Rails this would be `public`.
|
6
|
+
# Feel free to further modify the template to your needs as it doesn't cover every use-case of course,
|
7
|
+
# but tries to get all the common requirements out of the way to lessen research time (if any).
|
8
|
+
|
9
|
+
set_default :domains, ["empty.platan.us"]
|
10
|
+
set_default :static_dir, "public"
|
11
|
+
|
12
|
+
set_default :app_server, true
|
13
|
+
#set_default :app_server_port, 8080
|
14
|
+
set_default :app_server_socket, "/home/#{fetch(:user)}/tmp/platanus.#{fetch(:application)}.sock"
|
15
|
+
|
16
|
+
# set_default :use_ssl, true
|
17
|
+
# set_default :ssl_key, "/path/to/local/ssh.key"
|
18
|
+
# set_default :ssl_crt, "/path/to/local/ssh.crt"
|
19
|
+
|
20
|
+
namespace :nginx do
|
21
|
+
# after "deploy:install", "nginx:install"
|
22
|
+
# desc "Install latest stable release of nginx."
|
23
|
+
# task :install, roles: :web do
|
24
|
+
# run "#{sudo} add-apt-repository ppa:nginx/stable"
|
25
|
+
# run "#{sudo} apt-get -y update"
|
26
|
+
# run "#{sudo} apt-get -y install nginx"
|
27
|
+
# end
|
28
|
+
|
29
|
+
after "deploy:setup", "nginx:upload_ssl_certificates"
|
30
|
+
desc "Upload SSL certificates for this application."
|
31
|
+
task :upload_ssl_certificates, roles: :web do
|
32
|
+
if fetch(:use_ssl, nil)
|
33
|
+
run "mkdir -p /home/#{fetch(:user)}/ssl"
|
34
|
+
upload ssl_key, "/home/#{fetch(:user)}/ssl/#{fetch(:application)}.key"
|
35
|
+
upload ssl_crt, "/home/#{fetch(:user)}/ssl/#{fetch(:application)}.crt"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
after "deploy:setup", "nginx:setup"
|
40
|
+
desc "Setup nginx configuration for this application."
|
41
|
+
task :setup, roles: :web do
|
42
|
+
template "nginx.erb", "/tmp/nginx.conf"
|
43
|
+
run "#{sudo} mv /tmp/nginx.conf /opt/nginx/sites-enabled/#{fetch(:application)}"
|
44
|
+
run "mkdir -p /home/#{fetch(:user)}/log"
|
45
|
+
reload
|
46
|
+
end
|
47
|
+
|
48
|
+
%w[start stop restart reload].each do |command|
|
49
|
+
desc "#{command} Nginx."
|
50
|
+
task command, roles: :web do
|
51
|
+
run "#{sudo} service nginx #{command}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# RBEnv
|
2
|
+
#------------------------------------------------------------------------------
|
3
|
+
#
|
4
|
+
set_default :ruby_version, "1.9.3-p125"
|
5
|
+
|
6
|
+
namespace :rbenv do
|
7
|
+
desc "Upload rbenv vars"
|
8
|
+
task :upload, :roles => :app do
|
9
|
+
puts ".rbenv-vars #{shared_path}/config"
|
10
|
+
upload ".rbenv-vars"
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# Define App Server Upstream
|
2
|
+
<% if fetch(:app_server, nil) %>
|
3
|
+
upstream <%= fetch(:application) %>-app-server {
|
4
|
+
<% if fetch(:app_server_port, nil) %>
|
5
|
+
server 127.0.0.1:<%= fetch(:app_server_port) %> fail_timeout=0;
|
6
|
+
<% elsif fetch(:app_server_socket, nil) %>
|
7
|
+
server unix:<%= fetch(:app_server_socket) %> fail_timeout=0;
|
8
|
+
<% end %>
|
9
|
+
}
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
# HTTP Server
|
13
|
+
server {
|
14
|
+
listen 80 deferred;
|
15
|
+
server_name <%= fetch(:domains, ["platan.us", "www.platan.us"]).join(" ") %>;
|
16
|
+
root <%= fetch(:deploy_to) %>/current/<%= fetch(:static_dir) %>;
|
17
|
+
|
18
|
+
access_log /home/<%= fetch(:user) %>/log/<%= fetch(:application) %>-nginx-access.log;
|
19
|
+
error_log /home/<%= fetch(:user) %>/log/<%= fetch(:application) %>-nginx-error.log;
|
20
|
+
|
21
|
+
error_page 404 /404.html;
|
22
|
+
location /404.html { root <%= fetch(:deploy_to) %>/current/<%= fetch(:static_dir) %>; }
|
23
|
+
|
24
|
+
error_page 500 /500.html;
|
25
|
+
location /500.html { root <%= fetch(:deploy_to) %>/current/<%= fetch(:static_dir) %>; }
|
26
|
+
|
27
|
+
client_max_body_size 4G;
|
28
|
+
keepalive_timeout 10;
|
29
|
+
|
30
|
+
<% if fetch(:app_server, nil) %>
|
31
|
+
location ^~ /assets/ {
|
32
|
+
gzip_static on;
|
33
|
+
expires max;
|
34
|
+
add_header Cache-Control public;
|
35
|
+
}
|
36
|
+
|
37
|
+
try_files $uri/index.html $uri @<%= fetch(:application) %>-app-server;
|
38
|
+
location @<%= fetch(:application) %>-app-server {
|
39
|
+
proxy_set_header X-Real-IP $remote_addr;
|
40
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
41
|
+
proxy_set_header X-FORWARDED_PROTO http;
|
42
|
+
proxy_set_header Host $http_host;
|
43
|
+
proxy_redirect off;
|
44
|
+
proxy_pass http://<%= fetch(:application) %>-app-server;
|
45
|
+
}
|
46
|
+
<% end %>
|
47
|
+
}
|
48
|
+
|
49
|
+
<% if fetch(:use_ssl, nil) %>
|
50
|
+
# HTTPS Server
|
51
|
+
server {
|
52
|
+
listen 443 deferred;
|
53
|
+
server_name <%= fetch(:domains, ["platan.us", "www.platan.us"]).join(" ") %>;
|
54
|
+
root <%= fetch(:deploy_to) %>/current/<%= fetch(:static_dir) %>;
|
55
|
+
|
56
|
+
ssl on;
|
57
|
+
ssl_certificate /home/<%= fetch(:user) %>/ssl/<%= fetch(:application) %>.crt;
|
58
|
+
ssl_certificate_key /home/<%= fetch(:user) %>/ssl/<%= fetch(:application) %>.key;
|
59
|
+
|
60
|
+
access_log /home/<%= fetch(:user) %>/log/<%= fetch(:application) %>-nginx-access.log;
|
61
|
+
error_log /home/<%= fetch(:user) %>/log/<%= fetch(:application) %>-nginx-error.log;
|
62
|
+
|
63
|
+
error_page 404 /404.html;
|
64
|
+
location /404.html { root <%= fetch(:deploy_to) %>/current/<%= fetch(:static_dir) %>; }
|
65
|
+
|
66
|
+
error_page 500 /500.html;
|
67
|
+
location /500.html { root <%= fetch(:deploy_to) %>/current/<%= fetch(:static_dir) %>; }
|
68
|
+
|
69
|
+
client_max_body_size 4G;
|
70
|
+
keepalive_timeout 10;
|
71
|
+
|
72
|
+
<% if fetch(:app_server, nil) %>
|
73
|
+
location ^~ /assets/ {
|
74
|
+
gzip_static on;
|
75
|
+
expires max;
|
76
|
+
add_header Cache-Control public;
|
77
|
+
}
|
78
|
+
|
79
|
+
try_files $uri/index.html $uri @<%= fetch(:application) %>-app-server;
|
80
|
+
location @<%= fetch(:application) %>-app-server {
|
81
|
+
proxy_set_header X-Real-IP $remote_addr;
|
82
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
83
|
+
proxy_set_header X-FORWARDED_PROTO https;
|
84
|
+
proxy_set_header Host $http_host;
|
85
|
+
proxy_redirect off;
|
86
|
+
proxy_pass http://<%= fetch(:application) %>-app-server;
|
87
|
+
}
|
88
|
+
<% end %>
|
89
|
+
}
|
90
|
+
<% end %>
|
@@ -0,0 +1,51 @@
|
|
1
|
+
##############################################
|
2
|
+
# Platan.us Sample Unicorn Configuration File
|
3
|
+
##############################################
|
4
|
+
|
5
|
+
# Load rails into the master before forking workers
|
6
|
+
# for super-fast worker spawn times
|
7
|
+
preload_app <%= fetch(:unicorn_preload) %>
|
8
|
+
|
9
|
+
working_directory "<%= fetch(:current_path) %>"
|
10
|
+
pid "<%= fetch(:unicorn_pid) %>"
|
11
|
+
stderr_path "<%= fetch(:current_path) %>/log/unicorn-error.log"
|
12
|
+
stdout_path "<%= fetch(:current_path) %>/log/unicorn-out.log"
|
13
|
+
|
14
|
+
listen "<%= fetch(:app_server_socket) %>"
|
15
|
+
|
16
|
+
worker_processes <%= fetch(:unicorn_workers) %>
|
17
|
+
timeout <%= fetch(:unicorn_workers_timeout) %>
|
18
|
+
|
19
|
+
before_fork do |server, worker|
|
20
|
+
##
|
21
|
+
# When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
|
22
|
+
# immediately start loading up a new version of itself (loaded with a new
|
23
|
+
# version of our app). When this new Unicorn is completely loaded
|
24
|
+
# it will begin spawning workers. The first worker spawned will check to
|
25
|
+
# see if an .oldbin pidfile exists. If so, this means we've just booted up
|
26
|
+
# a new Unicorn and need to tell the old one that it can now die. To do so
|
27
|
+
# we send it a QUIT.
|
28
|
+
#
|
29
|
+
# Using this method we get 0 downtime deploys.
|
30
|
+
|
31
|
+
defined?(ActiveRecord::Base) && ActiveRecord::Base.connection.disconnect!
|
32
|
+
|
33
|
+
old_pid = "<%= fetch(:unicorn_pid) %>.oldbin"
|
34
|
+
if File.exists?(old_pid) && server.pid != old_pid
|
35
|
+
begin
|
36
|
+
Process.kill("QUIT", File.read(old_pid).to_i)
|
37
|
+
rescue Errno::ENOENT, Errno::ESRCH
|
38
|
+
# someone else did our job for us
|
39
|
+
puts "Old master already dead"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
after_fork do |server, worker|
|
45
|
+
##
|
46
|
+
# Unicorn master loads the app then forks off workers - because of the way
|
47
|
+
# Unix forking works, we need to make sure we aren't using any of the parent's
|
48
|
+
# sockets, e.g. db connection
|
49
|
+
|
50
|
+
ActiveRecord::Base.establish_connection
|
51
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Number of workers (Rule of thumb is 2 per CPU)
|
2
|
+
# Just be aware that every worker needs to cache all classes and thus eat some
|
3
|
+
# of your RAM.
|
4
|
+
set_default :unicorn_workers, 2
|
5
|
+
|
6
|
+
# Workers timeout in the amount of seconds below, when the master kills it and
|
7
|
+
# forks another one.
|
8
|
+
set_default :unicorn_workers_timeout, 30
|
9
|
+
|
10
|
+
# Workers are started with this user
|
11
|
+
# By default we get the user/group set in capistrano.
|
12
|
+
set_default :unicorn_user, user
|
13
|
+
|
14
|
+
# The wrapped bin to start unicorn
|
15
|
+
set_default :unicorn_bin, 'bin/unicorn'
|
16
|
+
set_default :unicorn_socket, fetch(:app_server_socket)
|
17
|
+
|
18
|
+
# Defines where the unicorn pid will live.
|
19
|
+
set_default :unicorn_pid, File.join(current_path, "tmp", "pids", "unicorn.pid")
|
20
|
+
|
21
|
+
# Preload app for fast worker spawn
|
22
|
+
set_default :unicorn_preload, true
|
23
|
+
|
24
|
+
# Unicorn
|
25
|
+
#------------------------------------------------------------------------------
|
26
|
+
namespace :unicorn do
|
27
|
+
desc "Starts unicorn directly"
|
28
|
+
task :start, :roles => :app do
|
29
|
+
run "cd #{current_path} && #{unicorn_bin} -c #{shared_path}/config/unicorn.rb -E #{rails_env} -D"
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Stops unicorn directly"
|
33
|
+
task :stop, :roles => :app do
|
34
|
+
run "kill -QUIT `cat #{unicorn_pid}`"
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Restarts unicorn directly"
|
38
|
+
task :restart, :roles => :app do
|
39
|
+
run "kill -USR2 `cat #{unicorn_pid}`"
|
40
|
+
end
|
41
|
+
|
42
|
+
after "deploy:setup", "unicorn:setup"
|
43
|
+
desc "Setup unicorn configuration for this application."
|
44
|
+
task :setup, roles: :app do
|
45
|
+
template "unicorn.erb", "/tmp/unicorn.rb"
|
46
|
+
run "#{sudo} mv /tmp/unicorn.rb #{shared_path}/config/"
|
47
|
+
end
|
48
|
+
|
49
|
+
after "deploy", "unicorn:restart"
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
# after 'deploy:setup' do
|
54
|
+
# unicorn.setup if Capistrano::CLI.ui.agree("Create unicorn configuration file? [Yn]")
|
55
|
+
# end if is_using_unicorn
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Servers and their roles.
|
2
|
+
server "<%= data[:target_server] %>", :web, :app, :db, primary: true
|
3
|
+
|
4
|
+
# Server-side information.
|
5
|
+
set :application, "<%= data[:application_name] %>"
|
6
|
+
set :user, "deploy"
|
7
|
+
set :deploy_to, "/home/#{user}/applications/#{application}"
|
8
|
+
|
9
|
+
# Repository (if any) configuration.
|
10
|
+
set :deploy_via, :remote_cache
|
11
|
+
set :repository, "<%= data[:repo] %>/#{application}.git"
|
12
|
+
set :branch, "production" # Optional, defaults to master
|
13
|
+
# set :remote, "negroku" # Optional, defaults to origin
|
14
|
+
# set :git_enable_submodules, 1
|
15
|
+
|
16
|
+
# Use the bundler capistrano task to deploy to the shared folder
|
17
|
+
require "bundler/capistrano"
|
18
|
+
set :bundle_flags, "--deployment --binstubs"
|
data/lib/negroku.rb
ADDED
metadata
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: negroku
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Juan Ignacio Donoso
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: capistrano
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.5.13
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 2.5.13
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rainbow
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.1.4
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.1.4
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: highline
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.6.15
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.6.15
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: thor
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.17.0
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.17.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: parseconfig
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 1.0.2
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.0.2
|
94
|
+
description: ! '["To deploy application"]'
|
95
|
+
email:
|
96
|
+
- jidonoso@gmail.com
|
97
|
+
executables:
|
98
|
+
- negroku
|
99
|
+
extensions: []
|
100
|
+
extra_rdoc_files: []
|
101
|
+
files:
|
102
|
+
- bin/negroku
|
103
|
+
- lib/negroku/cli.rb
|
104
|
+
- lib/negroku/config.rb
|
105
|
+
- lib/negroku/deploy.rb
|
106
|
+
- lib/negroku/helpers.rb
|
107
|
+
- lib/negroku/tasks/base.rb
|
108
|
+
- lib/negroku/tasks/log.rb
|
109
|
+
- lib/negroku/tasks/nginx.rb
|
110
|
+
- lib/negroku/tasks/rbenv.rb
|
111
|
+
- lib/negroku/tasks/templates/nginx.erb
|
112
|
+
- lib/negroku/tasks/templates/unicorn.erb
|
113
|
+
- lib/negroku/tasks/unicorn.rb
|
114
|
+
- lib/negroku/templates/deploy.rb.erb
|
115
|
+
- lib/negroku/version.rb
|
116
|
+
- lib/negroku.rb
|
117
|
+
- README.md
|
118
|
+
homepage: ''
|
119
|
+
licenses: []
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
none: false
|
126
|
+
requirements:
|
127
|
+
- - ! '>='
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
none: false
|
132
|
+
requirements:
|
133
|
+
- - ! '>='
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
requirements: []
|
137
|
+
rubyforge_project:
|
138
|
+
rubygems_version: 1.8.23
|
139
|
+
signing_key:
|
140
|
+
specification_version: 3
|
141
|
+
summary: ! '["Capistrano Wrapper"]'
|
142
|
+
test_files: []
|
143
|
+
has_rdoc:
|