¿Qué es Capistrano?
Capistrano es una herramienta que nos permite automatizar nuestros deploy, o sea subir nuestro proyecto a un servidor y también nuestras actualizaciones.
Capistrano tiene tareas y herramientas que nos permiten:
- precompilar assets
- reiniciar el server
- Migrar la base de datos
- Además podemos agregarle tareas nuevas
Antes de empezar, necesitamos tener un servidor donde podamos hacer el deploy, en este tutorial puedes aprender a construir uno con Nginx, RVM y postgreSQL. Nginx lo configuraremos junto con Puma.
Otra detalle que necesitamos es un proyecto en Rails (el que vamos a subir) y una cuenta en bitbucket o github desde esté nuestro proyecto.
Paso 1: Instalando la gema Capistrano
Dentro de tu computador, en la carpeta del proyecto, agregaremos las gemas de capistrano. Para eso abriremos el archivo gemfile y agregaremos las gemas.
group :development do gem 'capistrano', require: false gem 'capistrano-bundler', require: false gem 'capistrano-rails', require: false gem 'capistrano-rvm', github: 'capistrano/rvm', require: false gem 'capistrano-ssh-doctor', require: false end
y luego en el terminal dentro de la misma carpeta del proyecto:
bundle
Paso 2: Instalación de Capistrano
Con Capistrano, dentro de nuestra misma carpeta del proyecto crearemos los archivos para hacer el setup
cap install
Al hacerlo veremos lo siguiente:
create config/deploy.rb create config/deploy/staging.rb create config/deploy/production.rb mkdir -p lib/capistrano/tasks create Capfile Capified
Paso 2.1 Configuración del Capfile
En el archivo Capfile debemos especificar los requerimientos de nuestro setup, el que viene por defecto es genérico para distintas necesidades y aquí agregaremos que necesitamos herramientas para puma y rvm. Para lograrlo agregaremos al principio del archivo lo siguiente, debemos revisar si algún require queda duplicado y removerlo.
require 'capistrano/setup' require 'capistrano/deploy' require 'capistrano/rails' require 'capistrano/bundler' require 'capistrano/rvm' require 'capistrano/puma' require 'capistrano/ssh_doctor' require "capistrano/scm/git" install_plugin Capistrano::SCM::Git # Tambien agregaremos plugins que nos permitan configurar Puma install_plugin Capistrano::Puma # Default puma tasks install_plugin Capistrano::Puma::Workers # if you want to control the workers (in cluster mode) install_plugin Capistrano::Puma::Jungle # if you need the jungle tasks install_plugin Capistrano::Puma::Monit # if you need the monit tasks install_plugin Capistrano::Puma::Nginx # if you want to upload a nginx site template
Paso 2.2 Configuración del archivo de deployment
El archivo config/deploy.rb contiene información como de donde se obtendrá el proyecto ejemplo github, bitbucket y también información para conectarse al servidor, por lo mismo tenemos que configurarlo config/deploy.rb.
# config valid only for Capistrano 3.1 lock '~> 3.11.0' set :application, 'nombre_app' set :repo_url, 'repositorio github o bitbucket' set :scm, :git set :branch, "master" set :deploy_via, :copy set :user, 'deploy' # Default deploy_to directory is /var/www/my_app set :deploy_to, '/home/deploy/nombre_app' set :linked_files, %w{config/database.yml} set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system} namespace :deploy do desc 'Restart application' task :restart do on roles(:app), in: :sequence, wait: 5 do execute :touch, release_path.join('tmp/restart.txt') end end after :publishing, 'deploy:restart' after :finishing, 'deploy:cleanup' end namespace :deploy do desc 'Restart application' task :restart do on roles(:app), in: :sequence, wait: 5 do # Your restart mechanism here, for example: # execute :touch, release_path.join('tmp/restart.txt') end end after :publishing, :restart after :restart, :clear_cache do on roles(:web), in: :groups, limit: 3, wait: 10 do # Here we can do anything such as: # within release_path do # execute :rake, 'cache:clear' # end end end end
Advertencia: En la sección donde dice lock hay que ocupar la versión correspondiente de la gema de capistrano. Para saber la versión instalada puedes utilizar bundle show
donde dice nombre_app hay que utilizar el nombre de la aplicación.
donde dice repo_url debes poner la dirección ssh del git de tu aplicación
donde dice branch debes poner el branch que quieres ocupar para deployment, los más comunes son master, deploy y capistrano.
donde dice user: deploy es el nombre del usuario para hacer deployment, si seguiste el tutorial sobre como montar un servidor con nginx y passenger entonces tendrás a deploy como usuario.
donde dice deploy_to debemos poner el path hasta el usuario junto con el nombre de la app, por ejemplo si nuestra app se llama desafiolatam sería:
set :deploy_to, '/home/deploy/desafiolatam'
Paso 2.3 Configuración del archivo de producción
Otro archivo que nos falta modificar es el de config/deploy/production.rb, en este vamos a especificar donde está la aplicación y la base de datos.
role :app, %w{[email protected]} role :web, %w{[email protected]} role :db, %w{[email protected]}
server '127.0.0.1', user: 'deploy', roles: %w{web app}, my_property: :my_value set :stage, :production
aquí lo que hay que cambiar es deploy por el nombre del usuario de deployment (sólo si usaste uno distinto) y el ip del servidor. el resto se deja como está.
Paso 3: Generación de la clave ssh
hacemos ssh a la máquina del servidor con:
ssh deploy@ip-de-la-maquina
dentro de la máquina buscamos si tenemos una clave generada, ¿cómo lo hacemos? entramos a la carpeta del usuario.
cd
revisamos si tenemos la carpeta .ssh y dentro el archivo id_rsa.pub, sólo en caso de que no tengamos algunas de las dos anteriores.
ssh-keygen -t rsa
ahora vamos a mostrar la clave generada y la vamos a copiar
cat /home/deploy/.ssh/id_rsa.pub
el texto copiado (completo, incluyendo el email que muestra) lo vamos a pegar en bitbucket (o github).
para agregar la clave vamos a bitbucket seleccionamos el proyecto, clickeamos en settings, luego en deployment keys y luego en add key y ahí agregamos la clave ssh de la máquina.
Paso 4: Revisando ssh
dentro de la carpeta de nuestro proyecto con capistrano (en nuestra máquina).
bundle exec cap production ssh:doctor
si hay algún error es porque hicimos uno de los pasos anteriores mal, habrá que buscar el error en internet y revisar bien los pasos, uno bastante posible es que hayamos copiado mal la clave del servidor.
Paso 5: configurando puma
Nginx ocupa el mismo sistema de virtual hosts que apache
para eso ocupa dos carpetas /etc/nginx/sites-available y /etc/nginx/sites-enable
cuando uno empieza a crear uno nuevo lo pone sites-available y cuando lo quiere activar lo copia a través de un link simbólico a sites enable
ln -s ruta_completa_al_site_available ruta_destino
Nota: Editar el contenido del link simbólico o del original causa el mismo efecto.
Sin embargo nosotros estamos trabajando con el archivo default, este virtual host ya viene copiado, por lo que no tenemos que hacer nada, la explicación anterior es exclusivamente para cuando queremos poner más de una aplicación de rails en nuestro sitio.
paso 10.1 Configurando el virtual host por default
El siguiente paso consiste en editar el archivo /etc/nginx/sites-available/default
sudo vim /etc/nginx/sites-available/default
puedes comentar el contenido que existe actualmente para no perderlo, o puedes incluso hacerle una copia, pero lo importante es que dentro del archivo vaya el siguiente contenido.
server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; server_name mydomain.com; passenger_enabled on; rails_env production; root /home/deploy/nombre_proyecto/current/public; # redirect server error pages to the static page /50x.html error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
donde dice nombre_proyecto debe ir el nombre de la carpeta de tu proyecto.
donde dice mydomain.com debería el nombre de tu dominio comprado en nic chile o godaddy, sin embargo como es nuestro virtual host por default también será capaz de responder a la ip, en ese caso simplemente no ponemos la directiva server_name.
para hacer valer los cambios:
sudo service nginx restart
si hay un fallo en el archivo es posible revisar los logs de nginx con
sudo tail -n 50 /var/log/nginx/error.log
tail te muestra las últimas n lineas, 50 es el n, puedes también ocupar cat, pero a medida que crezca el log se va demorar más.
finalmente lo que tenemos que hacer es copiar nuestra app corriendo de rails a nombre_proyecto/current
ahora, ¿Por qué ocupar una carpeta llamada current, porque en la siguiente tutorial vamos a aprender a hacer deployment automatizado con Capistrano.
paso 5: cap deploy
dentro del bash en la carpeta de nuestro proyecto
cap production deploy
Advertencia fallará, pero eso es normal. Vamos a tener un error del tipo: ERROR linked file /home/deploy/nombre_app/shared/config/database.yml does not exist on 104.236.105.133
Paso 5.1 Configurando el database.yml
hay dos formas de manejar esta situación, una de ellas es crear el archivo en el computador y subirlo por scp o ftp, pero la mejor forma es crearlo directamente en la máquina remota con vim o nano (u otro editor)
vim /home/deploy/nombre_app/shared/config/database.yml
dentro del archivo tenemos que poner como mínimo los siguientes parámetros:
production: host: localhost adapter: postgresql encoding: unicode database: el_nombre_de_tu_bd pool: 5 username: el_usuario_de_tu_bd password: el_password_de_tu_bd
Paso 5.2 Instalando el runtime de javascript
Si hacemos deploy en este momento probablemente fallará en el servidor por culpa del runtime de javascript el cual probablemente no estará instalado, una de las formas más fáciles de instalar es con:
apt-get install nodejs
Paso 6: Segundo deploy
volvemos a nuestra máquina y corremos nuevamente
cap production deploy
Paso 6.1 Configurando el archivo secret.yml
Entra a la ip del server y deberías poder ver tu app.
Si a esta altura falla, lo que hay que hacer es revisar los logs de nginx, uno de los errors más comunes es haber olvidado setear dentro de tu app la clave secreta para producción dentro del archivo de tu proyecto de rails llamado config/secrets.yml
para arreglar eso vamos utilizar cualquier editor (vim, nano, etc) a e el archivo config/secret.yml
vim config/secret.yml
dentro del archivo:
production: secret_key_base: codigo_random_inventado
el código random inventando puede ser como cualquiera de los secret_key_base que tienes en tu proyecto local pero con algunas variantes introducidas por ti.
Paso 7: la tercera es la vencida
ahora si que al entrar al servidor deberíamos poder ver nuestra app, si todavía falla hay que revisar los logs, lo más importantes son el nginx y el de rails, el de nginx se encuentra en etc/nginx/error.log y los de rails se encuentran dentro de /home/deploy/nombre_app/log/production.log
Gonzalo Sánchez
Artículos relacionados
5 Comentario
Deja una respuesta
Recibe los artículos más leidos y beneficios especiales de nuestra academia
Empieza a trabajar en los roles digitales mejor pagados
Fórmate de manera práctica, e intensiva, con sesiones en vivo de forma flexible y efectiva. Te acompañamos desde que partes hasta que encuentras trabajo.
Esto me esta volviendo loco, por favor su ayuda:
El ssh:doctor funciona sin problemas y dice que puedo seguir con el deploy. Sin embargo, al hacer cap production deploy indica el siguiente mensaje.
DEBUG [2ea96c99] Command: /usr/bin/env mv /home/deploy/crm/releases/current /home/deploy/crm
DEBUG [2ea96c99] mv: cannot overwrite directory ‘/home/deploy/crm/current’ with non-directory
Parece que es el script esta intentando cambiar de lugar el archivo current a la carpeta crm, pero por algún motivo no lo deja. Parece lío entre archivos y carpetas. Mi deficiente conocimiento de linux me impide continuar.
Agradezco mucho cualquier ayuda.
Modifique el nombre de la carpeta home/deploy/crm/current a home/deploy/crm/current2 y parece funcionar.
Sera que en cada deployment hay que ir cambiando el nombre a la ultima carpeta current??
no, el nombre de la carpeta se cambia sólo si hiciste bien los pasos del tutorial anterior, parece más un problema de permisos, revisa si deploy tiene permisos para cambiar la carpeta, revisa en el archivo production.rb que el usuario de capistrano si sea deploy.
Agregando esta directiva al archivo default de sites-enabled solucionó el problema.
passenger_ruby /home/deploy/.rvm/wrappers/ruby-2.2.0/ruby;
Hola, si tienes algún momento me sería de mucha ayuda la revisión de lo siguiente:
tengo varios proyecto con capistrano pero ahora al tratar de usar la gema, me ha estado dando el error:
NameError: undefined local variable or method `strategy’ for #
he buscado documentación al respecto pero parece no existir nada pea el caso