Primero accedemos vía SSH a nuestro servidor, si aún no a has configurado y asegurado el acceso SSH a tu VPS puedes visitar un post donde explico como hacerlo. Si ya tienes todo listo entonces procedemos.
Configuraciones en el Servidor
ssh -p numero-de-puerto nombre-de-usuario@123.123.123.123Si no lo hemos hecho aún, actualizamos los paquetes e instalamos curl
sudo apt-get update sudo apt-get install curlInstalamos la última versión estable de la RVM (Ruby Version Manager)
curl -L get.rvm.io | bash -s stableCargamos la RVM
source ~/.rvm/scripts/rvmInstalamos las dependencias de la RVM
rvm requirementsInstalamos Ruby 2.0.0 (o bien podemos instalar la 2.1.0)
rvm install 2.0.0Usamos la version 2.0.0 por defecto en RVM
rvm use 2.0.0 --defaultIntalamos la última versión de rubygems en caso que RVM no la tenga aún
rvm rubygems currentInstalamos la gema de Rails, junto a Git, Bundler y NodeJS (necesario para las compilaciones de assets)
gem install rails --no-ri --no-rdoc sudo apt-get install git-core gem install bundler**En caso que necesitemos instalar una versión especifica de Rails y no la más reciente (lo cual es lo recomendado) podemos hacerlo indicando que versión queremos.
gem install rails -v 3.2.14Instalamos nuestro motor de base de datos, yo uso y recomiendo PostgreSQL, así que los siguientes pasos serán para instalarlo y configurarlo con Rails.
sudo apt-get install postgresql postgresql-server-dev-9.1 gem install pg -- --with-pg-config=/usr/bin/pg_configCreamos un nuevo usuario en postgres (cambiar los campos correspondientes)
sudo -u postgres psql create user nuevo-usuario with password 'contrasenia'; alter role nuevo-usuario superuser createrole createdb replication; create database nombre_del_proyecto_production owner nuevo-usuario;Instalamos Nginx
sudo apt-get install nginx nginx -h cat /etc/init.d/nginx /etc/init.d/nginx -h sudo service nginx start cd /etc/nginx
Configuración Local
Comenzamos agregando Unicorn al Gemfilegem 'unicorn'Ahora creamos los siguientes archivos en el directorio /config * unicorn.rb * unicorn_init.sh * nginx.conf
Una vez creada, asignamos permisos de ejecución a unicorn_init.sh
chmod +x config/unicorn_init.shAgregamos la configuración de Nginx el archivo que hemos creado en el directorio /conf llamado nginx.conf (cambia nombre_de_proyecto y nombre_de_usuario con tus datos, el nombre del proyecto correspondería al nombre que le hayas asignado a tu aplicación de rails y el nombre de usuario es con el que accedes al servidor y por ende tiene asignado un directorio en la carpeta /home/nombre_de_usuario...)
upstream unicorn { server unix:/tmp/unicorn.nombre_de_proyecto.sock fail_timeout=0; } server { listen 80 default_server deferred; # server_name example.com; root /home/nombre_de_usuario/apps/nombre_de_proyecto/current/public; location ^~ /assets/ { gzip_static on; expires max; add_header Cache-Control public; } try_files $uri/index.html $uri @unicorn; location @unicorn { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://unicorn; } error_page 500 502 503 504 /500.html; client_max_body_size 20M; keepalive_timeout 10; }Ahora editamos el archivo conf/unicorn.rb (recuerda cambiar nombre_de_proyecto y nombre_de_usuario conforme a tus datos). También puedes editar el número de workers que deseas que tenga tu aplicación, de momento solo he incluido dos.
root = "/home/nombre_de_usuario/apps/nombre_de_proyecto/current" working_directory root pid "#{root}/tmp/pids/unicorn.pid" stderr_path "#{root}/log/unicorn.log" stdout_path "#{root}/log/unicorn.log" listen "/tmp/unicorn.nombre_de_protecto.sock" worker_processes 2 timeout 30 # Force the bundler gemfile environment variable to # reference the capistrano "current" symlink before_exec do |_| ENV["BUNDLE_GEMFILE"] = File.join(root, 'Gemfile') endEditamos el archivo config/unicorn_init.sh (nuevamente recuerda cambiar el nombre_de_usuario y nombre_de_proyecto)
#!/bin/sh ### BEGIN INIT INFO # Provides: unicorn # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Manage unicorn server # Description: Start, stop, restart unicorn server for a specific application. ### END INIT INFO set -e # Feel free to change any of the following variables for your app: TIMEOUT=${TIMEOUT-60} APP_ROOT=/home/nombre_de_usuario/apps/nombre_de_proyecto/current PID=$APP_ROOT/tmp/pids/unicorn.pid CMD="cd $APP_ROOT; bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E production" AS_USER=nombre_de_usuario set -u 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)" = "$AS_USER" ]; then eval $1 else su -c "$1" - $AS_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
Configuración de Capistrano
Agregamos Capistrano y Capistrano RVM al Gemfilegem 'capistrano' gem 'rvm-capistrano'Despues de haber ejecutado bundle install para instalar las gemas correspondientes ejecutamos el siguiente comando en el directorio principal de nuestra aplicación
capify .Editamos (creamos en caso que no lo tengamos) el archivo deploy.rb en el directorio /config y agregamos la siguiente receta(recuerda sustituir los valores correspondientes conforme a los tu configuración):
require "bundler/capistrano" require "rvm/capistrano" server "123.123.123.123", :web, :app, :db, primary: true set :application, "nombre_del_proyecto" set :user, "nombre de usuario" set :port, 22 #sustituye con el puerto que usas set :deploy_to, "/home/#{user}/apps/#{application}" set :deploy_via, :remote_cache set :use_sudo, false set :scm, "git" set :repository, "git@github.com:username/#{application}.git" #o simplemente copia y pega la url del repositorio en el servicio que uses set :branch, "master" default_run_options[:pty] = true ssh_options[:forward_agent] = true after "deploy", "deploy:cleanup" # keep only the last 5 releases namespace :deploy do %w[start stop restart].each do |command| desc "#{command} unicorn server" task command, roles: :app, except: {no_release: true} do run "/etc/init.d/unicorn_#{application} #{command}" end end task :setup_config, roles: :app do sudo "ln -nfs #{current_path}/config/nginx.conf /etc/nginx/sites-enabled/#{application}" sudo "ln -nfs #{current_path}/config/unicorn_init.sh /etc/init.d/unicorn_#{application}" run "mkdir -p #{shared_path}/config" put File.read("config/database.example.yml"), "#{shared_path}/config/database.yml" puts "Now edit the config files in #{shared_path}." end after "deploy:setup", "deploy:setup_config" task :symlink_config, roles: :app do run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml" end after "deploy:finalize_update", "deploy:symlink_config" desc "Make sure local git is in sync with remote." task :check_revision, roles: :web do unless `git rev-parse HEAD` == `git rev-parse origin/master` puts "WARNING: HEAD is not the same as origin/master" puts "Run `git push` to sync changes." exit end end before "deploy", "deploy:check_revision" endAhora edita el archivo Capfile creado en el directorio principal de tu aplicación y verifica que esté de la siguiente manera:
load 'deploy' load 'deploy/assets' load 'config/deploy'
Despliegue
cap deploy:setupEdita en el servidor /home/nombre-de-usuario/apps/nombre-de-proyecto/shared/config/database.yml conforme a los datos de conexión en el servidor remoto, en mi caso usando PostgreSQL para el entorno de producción quedaría de la siguiente manera.
production: adapter: postgresql encoding: unicode host: localhost database: nombre_de_bd_production pool: 5 username: nombre_usuario_en_postgres password: 'ontrasenia'Luego de haber ejecutado las configuración inicial y asumiendo que todo esta bien...
cap deploy:coldLuego del deploy:cold
sudo rm /etc/nginx/sites-enabled/default sudo service nginx restart sudo update-rc.d -f unicorn_nombre_del_proyecto defaultsPor último para cada cambio nuevo que hagamos, hacemos push desde nuestro repositorio local y luego el deploy usando capistrano
git push origin master cap deployEso es todo, si tienes dudas, puedes contactarme o dejar tus comentarios.