Skip to content

Instantly share code, notes, and snippets.

@vhyza
Forked from karmi/.gitignore
Created June 11, 2014 15:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vhyza/b01dba5a208c5428bd49 to your computer and use it in GitHub Desktop.
Save vhyza/b01dba5a208c5428bd49 to your computer and use it in GitHub Desktop.
# Clones, configures and launches a Ruby web application under common Nginx
#
# Usage
# -----
#
# $ export HOST=user@example.com
# $ export SSH_KEY=~/.ssh/yourkey.pem
#
# $ scp -i $SSH_KEY install-app.rb $HOST:/tmp
#
# $ time ssh -t -i $SSH_KEY $HOST "sudo NAME=music PORT=3000 REPO=https://karmiq@bitbucket.org/karmiq/music.git ENV=development chef-apply /tmp/install-app.rb"
#
config = {}
config[:name] = ENV['NAME']
config[:port] = ENV['PORT']
config[:repo] = ENV['REPO']
config[:env] = ENV.fetch('ENV', 'development')
STDERR.puts '', " CONFIGURATION ".center(80, '-')
[ :name, :port, :repo, :env ].each do |var|
STDERR.puts "#{var}: ".capitalize.ljust(15) + "#{config[var]}"
end
STDERR.puts '-'*80, '', ''
[ :name, :port, :repo, :env ].each do |var|
Chef::Log.fatal "Undefined configuration for: #{var}" unless config[var]
end
user = 'application'
path = '/usr/local/var/applications'
app_start_command = <<-COMMAND
cd #{path}/#{config[:name]} && \
RAILS_RELATIVE_URL_ROOT=/#{config[:name]} bundle exec thin \
--port #{config[:port]} \
--chdir #{path}/#{config[:name]} \
--rackup #{path}/#{config[:name]}/config.ru \
--prefix /#{config[:name]} \
--environment #{config[:env]} \
--pid #{path}/#{config[:name]}/tmp/#{config[:name]}.pid \
--user application \
--group applications \
--tag #{config[:name]} \
--daemonize \
start
COMMAND
user "#{user}" do
shell "/bin/bash"
home "#{path}"
comment "Ruby Applications"
end
group "applications" do
members "#{user}"
end
directory "#{path}/" do
owner "#{user}"
group "applications"
recursive true
end
git "#{path}/#{config[:name]}" do
repository config[:repo]
user "#{user}"
group "applications"
action :sync
end
directory "#{path}/#{config[:name]}/tmp" do
owner "#{user}"
group "applications"
end
directory "#{path}/#{config[:name]}/log" do
owner "#{user}"
group "applications"
end
bash "repair permissions" do
code "chown -R #{user}:applications #{path}"
end
file "/etc/init.d/app-#{config[:name]}" do
content "#{app_start_command}"
owner "#{user}"
group "applications"
mode "0755"
end
bash "install Bundler" do
code "gem install bundler"
not_if "gem list | grep bundler"
end
bash "install application Rubygems" do
code "sudo su - #{user} -c 'BUNDLE_GEMFILE=#{path}/#{config[:name]}/Gemfile bundle install'"
end
bash "start the application immediately" do
code "bash /etc/init.d/app-#{config[:name]}"
not_if "ps aux | grep -v grep | grep #{config[:name]}"
end
ruby_block "add Nginx 'location' directive for #{config[:name]}" do
@file = ::File.new("/etc/nginx/conf.d/applications.conf")
@content = @file.read
block do
tempfile = ::Tempfile.new('applications.conf')
new_content = @content.gsub(/server {([\w\W]+)?}/i) do |match|
"server {" + $1 + " location /#{config[:name]} {\n proxy_pass http://localhost:#{config[:port]};\n }\n" + "}\n"
end.to_s
tempfile.write new_content
diff = Chef::Util::Diff.new.udiff @file.path, tempfile.path
Chef::Log.debug diff
FileUtils.mv tempfile.path, @file.path
end
notifies :run, "execute[nginx-reload]"
not_if { @content.include? "location /#{config[:name]}" }
end
execute "monit-reload" do
command "service monit reload"
action :nothing
end
execute "nginx-reload" do
command "service nginx reload"
action :nothing
end
# Install a basic Elasticsearch/Ruby/Rails/Nginx/etc stack to a server
#
# First, install Chef:
#
# $ export HOST=user@example.com
# $ export SSH_KEY=~/.ssh/yourkey.pem
#
# $ ssh -i $SSH_KEY $HOST "sudo apt-get update"
# $ ssh -i $SSH_KEY $HOST "curl -# -L http://www.opscode.com/chef/install.sh | sudo bash -s --"
#
# Then, upload and run the script:
#
# $ scp -i $SSH_KEY install-base.rb $HOST:/tmp
# $ time ssh -t -i $SSH_KEY $HOST "sudo chef-apply /tmp/install-base.rb"
#
STDOUT.sync = true
STDERR.sync = true
# ----- Packages and Tools --
bash("apt update") { code "apt-get update" }
%w| build-essential
make
bison
zlib1g-dev
libopenssl-ruby1.9.1
libcurl4-openssl-dev
libssl-dev
libyaml-dev
libxml2-dev libxslt1-dev
libreadline-dev
libncurses5-dev
file
sqlite3 libsqlite3-dev
ruby1.9.3
curl
vim
git
htop |.each { |name| package name }
# ----- Elasticsearch -------
package "openjdk-7-jre-headless"
remote_file "/tmp/elasticsearch-1.2.1.deb" do
source "https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.2.1.deb"
checksum "60ae2764782369aea2428e634eda092830832cd9"
action :create_if_missing
end
dpkg_package "elasticsearch-1.2.1.deb" do
package_name "elasticsearch"
source "/tmp/elasticsearch-1.2.1.deb"
end
bash "set ES_HEAP_SIZE" do
code "echo 'ES_HEAP_SIZE=256m' >> /etc/default/elasticsearch"
not_if "grep '^ES_HEAP_SIZE=256m' /etc/default/elasticsearch"
end
bash "configure Elasticsearch" do
code "echo 'cluster.name: ruby-elasticsearch' >> /etc/elasticsearch/elasticsearch.yml"
not_if "grep '^cluster.name: ruby-elasticsearch' /etc/elasticsearch/elasticsearch.yml"
end
service "elasticsearch" do
action [ :enable, :start ]
end
# ----- Redis ---------------
package "redis-server"
# ----- Nginx ---------------
package "nginx"
file "/etc/nginx/conf.d/applications.conf" do
content <<-CONTENT.gsub(/^ /, '')
server {
listen 80;
location / {
root /usr/local/var/applications;
}
}
CONTENT
notifies :run, "execute[nginx-reload]"
end
# ----- Node.js (for Rails assets)
package "nodejs"
# ----- The Application -----
bash "install Bundler" do
code "gem install bundler"
not_if "gem list | grep bundler"
end
# ----- Monit -----
package 'monit'
file "/etc/monit/monitrc" do
content <<-CONTENT.gsub(/^ /, '')
set daemon 60
set logfile /var/log/monit.log
set httpd port 2812 and
use address localhost
allow localhost
check process redis with pidfile /var/run/redis/redis-server.pid
start program = "/usr/sbin/service redis-server start" with timeout 60 seconds
stop program = "/usr/sbin/service redis-server stop"
if cpu > 90% for 15 cycles then alert
if totalmem > 90% for 15 cycles then alert
group redis
check process elasticsearch with pidfile /var/run/elasticsearch.pid
start program = "/usr/sbin/service elasticsearch start" with timeout 60 seconds
stop program = "/usr/sbin/service elasticsearch stop"
if cpu > 90% for 15 cycles then alert
if totalmem > 90% for 15 cycles then alert
group elasticsearch
check process nginx with pidfile /run/nginx.pid
start program = "/usr/sbin/service nginx start" with timeout 60 seconds
stop program = "/usr/sbin/service nginx stop"
if cpu > 90% for 15 cycles then alert
if totalmem > 90% for 15 cycles then alert
group nginx
CONTENT
notifies :run, "execute[monit-reload]"
end
execute "monit-reload" do
command "service monit reload"
action :nothing
end
execute "nginx-reload" do
command "service nginx reload"
action :nothing
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment