diff --git a/Capfile b/Capfile index 8a7ed3b..52d0898 100644 --- a/Capfile +++ b/Capfile @@ -4,10 +4,12 @@ require 'capistrano/setup' # Includes default deployment tasks require 'capistrano/deploy' -require 'capistrano/rvm' -require 'capistrano/bundler' -require 'capistrano/rails/assets' -require 'capistrano/rails/migrations' +if !ARGV.any? { |task| task =~ /provision/ } + require 'capistrano/rvm' + require 'capistrano/bundler' + require 'capistrano/rails/assets' + require 'capistrano/rails/migrations' +end # Loads custom tasks from `lib/capistrano/tasks' if you have any defined. Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r } diff --git a/Vagrantfile b/Vagrantfile index 30afdb6..8901515 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -55,7 +55,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| # View the documentation for the provider you're using for more # information on available options. - config.vm.provision :shell, :path => "script/setup.sh" + #config.vm.provision :shell, :path => "script/setup.sh" # Enable provisioning with Puppet stand alone. Puppet manifests # are contained in a directory path relative to this Vagrantfile. diff --git a/config/config.example.yml b/config/config.example.yml index 93c3c60..92c4ed3 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -1,5 +1,5 @@ default: &default - name: Campo + title: Campo host: localhost admin_emails: diff --git a/config/database.example.yml b/config/database.example.yml index cf431bd..30afc3f 100644 --- a/config/database.example.yml +++ b/config/database.example.yml @@ -20,7 +20,7 @@ default: &default # For details on connection pooling, see rails configuration guide # http://guides.rubyonrails.org/configuring.html#database-pooling pool: 5 - username: campo + username: password: development: diff --git a/config/deploy.rb b/config/deploy.rb index 1d0bb77..a9e3d18 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -3,17 +3,136 @@ lock '3.1.0' set :application, 'campo' set :repo_url, 'git@github.com:chloerei/campo.git' -set :deploy_to, '/var/www/campo' +set :deploy_to, -> { "/var/www/#{fetch(:application)}" } +set :rails_env, 'production' set :linked_files, %w{config/database.yml config/config.yml config/secrets.yml} set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/uploads} +task :provision => %w(provision:update provision:postgresql provision:elasticsearch provision:rvm provision:server provision:unicorn_campo provision:nginx_conf) + +task :foo do + puts fetch(:application) +end + +namespace :provision do + desc "Update apt-get" + task :update do + on roles(:all) do |host| + host.user = 'root' + execute(*%W(apt-get update)) + end + end + + desc "Install postgresql" + task :postgresql do + on roles(:all) do |host| + host.user = 'root' + + execute('apt-get install -y postgresql libpq-dev') + as user: 'postgres' do + execute(*%W(createuser -d -R -S deploy)) + execute(*%w(createdb campo_production -O deploy)) + end + end + end + + desc "Install elasticsearch" + task :elasticsearch do + on roles(:all) do |host| + host.user = 'root' + + execute('apt-get install -y openjdk-7-jre-headless') + execute('wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.0.1.deb -O elasticsearch-1.0.1.deb -q') + execute('dpkg -i elasticsearch-1.0.1.deb') + execute('update-rc.d elasticsearch defaults') + execute('service elasticsearch start') + end + end + + desc "Install rvm" + task :rvm do + on roles(:all) do |host| + deploy_user = host.user + host.user = 'root' + + execute('apt-get -y install curl') + as user: deploy_user do + execute(*%W(curl -sSL https://get.rvm.io | bash -s stable)) + end + execute("su - #{deploy_user} -c 'rvm use --default --install 2.1.1'") + end + end + + desc "Install redis nginx memcache git nodejs and upload conf" + task :server do + on roles(:all) do |host| + host.user = 'root' + + execute('apt-get install -y redis-server memcached nginx git-core nodejs') + end + end + + desc "Install unicorn init script" + task :unicorn_init_script do + on roles(:all) do |host| + deploy_user = host.user + host.user = 'root' + + unicorn_template_path = File.expand_path('config/unicorn_init.sh.erb') + unicorn_config_binding = OpenStruct.new({ + user: deploy_user, + deploy_to: fetch(:deploy_to) + }).instance_eval { binding } + unicorn_config = ERB.new(File.new(unicorn_template_path).read).result(unicorn_config_binding) + upload! StringIO.new(unicorn_config), "/etc/init.d/unicorn_#{fetch(:application)}" + execute("chmod +x /etc/init.d/unicorn_#{fetch(:application)}") + execute("update-rc.d unicorn_#{fetch(:application)} defaults") + end + end + + desc "Install nginx conf" + task :nginx_conf do + on roles(:all) do |host| + host.user = 'root' + + config_binding = OpenStruct.new({ + deploy_to: fetch(:deploy_to) + }).instance_eval { binding } + config = ERB.new(File.new('config/nginx.conf.erb').read).result(config_binding) + upload! StringIO.new(config), "/etc/nginx/sites-enabled/#{fetch(:application)}.conf" + exec('service nginx reload') + end + end + + desc "Prepare deploy to" + task :deploy_to do + on roles(:all) do |host| + deploy_user = host.user + host.user = 'root' + + execute('mkdir -p /var/www/campo') + execute("chown #{deploy_user}:#{deploy_user} #{fetch(:deploy_to)}") + end + end +end + namespace :deploy do + desc "Setup base config" + task :setup do + on roles(:app) do + upload! File.new('config/database.example.yml'), "#{deploy_to}/shared/config/database.yml" + upload! File.new('config/secrets.example.yml'), "#{deploy_to}/shared/config/secrets.yml" + upload! File.new('config/config.example.yml'), "#{deploy_to}/shared/config/config.yml" + info "Now edit the config files in #{shared_path}." + end + end + desc 'Restart application' task :restart do on roles(:app), in: :sequence, wait: 5 do - execute '/etc/init.d/unicorn_campo', :restart + execute "/etc/init.d/unicorn_#{fetch(:application)}", :restart end end diff --git a/config/deploy/vagrant.rb b/config/deploy/vagrant.rb index f76fbad..b95696c 100644 --- a/config/deploy/vagrant.rb +++ b/config/deploy/vagrant.rb @@ -5,5 +5,3 @@ server '192.168.33.10', { keys: %w(~/.vagrant.d/insecure_private_key) } } - -set :rails_env, 'production' diff --git a/config/nginx.conf b/config/nginx.conf.erb similarity index 93% rename from config/nginx.conf rename to config/nginx.conf.erb index 63fbd58..5eca022 100644 --- a/config/nginx.conf +++ b/config/nginx.conf.erb @@ -5,7 +5,7 @@ upstream unicorn { server { listen 80 default deferred; # server_name example.com; - root /var/www/campo/current/public/; + root <%= deploy_to %>/current/public/; location ^~ /(assets|uploads)/ { gzip_static on; diff --git a/config/unicorn_init.sh.erb b/config/unicorn_init.sh.erb new file mode 100644 index 0000000..7da58a4 --- /dev/null +++ b/config/unicorn_init.sh.erb @@ -0,0 +1,74 @@ +#!/bin/bash +set -e +set -u + +APP_ROOT=<%= deploy_to %>/current +USER=<%= user %> + +TIMEOUT=${TIMEOUT-60} +PID=$APP_ROOT/tmp/pids/unicorn.pid +CMD="cd $APP_ROOT; bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E production" +OLD_PIN="$PID.oldbin" + +sig () { + test -s "$PID" && kill -$1 `cat $PID` +} + +oldsig () { + test -s $OLD_PIN && kill -$1 `cat $OLD_PIN` +} + +run () { + if [ "$(id -un)" = "$USER" ]; then + eval $1 + else + su -c "$1" - $USER + fi +} + +case "$1" in +start) + sig 0 && echo >&2 "Already running" && exit 0 + run "$CMD" + ;; +stop) + sig QUIT && exit 0 + echo >&2 "Not running" + ;; +force-stop) + sig TERM && exit 0 + echo >&2 "Not running" + ;; +restart|reload) + sig HUP && echo reloaded OK && exit 0 + echo >&2 "Couldn't reload, starting '$CMD' instead" + run "$CMD" + ;; +upgrade) + if sig USR2 && sleep 2 && sig 0 && oldsig QUIT + then + n=$TIMEOUT + while test -s $OLD_PIN && test $n -ge 0 + do + printf '.' && sleep 1 && n=$(( $n - 1 )) + done + echo + + if test $n -lt 0 && test -s $OLD_PIN + then + echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds" + exit 1 + fi + exit 0 + fi + echo >&2 "Couldn't upgrade, starting '$CMD' instead" + run "$CMD" + ;; +reopen-logs) + sig USR1 + ;; +*) + echo >&2 "Usage: $0 " + exit 1 + ;; +esac diff --git a/script/unicorn.sh b/script/unicorn.sh deleted file mode 100644 index 4c8d728..0000000 --- a/script/unicorn.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/sh -set -e - -# Feel free to change any of the following variables for your app: -TIMEOUT=${TIMEOUT-60} -APP_ROOT=/var/www/campo/current -PID=$APP_ROOT/tmp/pids/unicorn.pid -USER=deploy -CMD="cd $APP_ROOT ; RAILS_ENV=production bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb" -action="$1" -set -u - -old_pid="$PID.oldbin" - -sig () { - test -s "$PID" && kill -$1 `cat $PID` -} - -oldsig () { - test -s $old_pid && kill -$1 `cat $old_pid` -} - -run () { - if [ "$(id -un)" = "$AS_USER" ]; then - eval $1 - else - su -c "$1" - $USER - fi -} - -case $action in - start) - sig 0 && echo >&2 "Already running" && exit 0 - run "$CMD" - ;; - stop) - sig QUIT && exit 0 - echo >&2 "Not running" - ;; - force-stop) - sig TERM && exit 0 - echo >&2 "Not running" - ;; - restart|reload) - sig HUP && echo reloaded OK && exit 0 - echo >&2 "Couldn't reload, starting '$CMD' instead" - run "$CMD" - ;; - upgrade) - if sig USR2 && sleep 2 && sig 0 && oldsig QUIT - then - n=$TIMEOUT - while test -s $old_pid && test $n -ge 0 - do - printf '.' && sleep 1 && n=$(( $n - 1 )) - done - echo - - if test $n -lt 0 && test -s $old_pid - then - echo >&2 "$old_pid still exists after $TIMEOUT seconds" - exit 1 - fi - exit 0 - fi - echo >&2 "Couldn't upgrade, starting '$CMD' instead" - run "$CMD" - ;; - reopen-logs) - sig USR1 - ;; - *) - echo >&2 "Usage: $0 " - exit 1 - ;; -esac