negroku 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.
- 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:
|