linux:rails_deploy

Entre na máquina via ssh

$ ssh usuario@app_name.ifce.edu.br

Obs: Caso a chave ssh do servidor tenha sido alterada, por algum motivo específico, remova o arquivo known_hosts:

rm ~/.ssh/known_hosts

É recomendado criar um usuário na máquina com o mesmo nome da aplicação, caso o mesmo ainda não exista. Não é interessante utilizar um usuário genérico para configurar o deploy. Nesse tutorial iremos utilizar o usuário como exemplo: minha_app. Troque esse nome pelo nome da sua aplicação ou qualquer outro nome que achar mais conveniente.

Crie o usuário

sudo adduser minha_app

Digite a senha e as informações necessárias até finalizar o processo

Adicione o usuário ao arquivo sudoers:

sudo visudo

No final do arquivo adicione:

minha_app ALL=(ALL) NOPASSWD:ALL

Digite Ctrl + O para salvar e depois Ctrl + X para fechar o arquivo

Logue com esse novo usuário

su minha_app

Dê ssh para alguma máquina a fim de criar o diretório ~/.ssh

ssh usuario@app_name.ifce.edu.br

Dê um Ctrl+C ao ser solicitado pela senha.

Adicione sua chave ao arquivo ~/.ssh/authorized_keys

Na sua máquina local pegue a sua chave ssh se existir com o comando (Cuidado para não copiar os espaços):

cat ~/.ssh/id_rsa.pub

No servidor adicione a chave ao arquivo:

vim ~/.ssh/authorized_keys

Cole conteúdo da chave nesse arquivo

Salve e teste

Instalando o Curl

$ sudo apt-get update
$ sudo apt-get install curl

Obs: caso tenha algum problema ao baixar o rvm, verifique os seus servidores DNS no arquivo: /etc/resolv.conf. Sugestão: adicione os servidores de DNS do google: 8.8.8.8 e 8.8.4.4

$ curl -L get.rvm.io | bash -s stable

Caso ocorra o seguinte erro, rode o comando sugerido pelo próprio erro:

GPG signature verification failed for '/home/app_name/.rvm/archives/rvm-1.27.0.tgz' - 'https://github.com/rvm/rvm/releases/download/1.27.0/1.27.0.tar.gz.asc'! try downloading the signatures:

Rode:

command curl -sSL https://rvm.io/mpapis.asc | gpg --import -

E depois rode novamente os comandos abaixo para finalizar a instalação do rvm:

$ curl -L get.rvm.io | bash -s stable

Agora é preciso instalar os requisitos para instalar o ruby e instalar também a gem bundles para gerenciar as outras gems do projeto:

$ source ~/.rvm/scripts/rvm
$ rvm requirements
$ rvm install 2.0.0 (Utilize a versão que vc estiver trabalhando no projeto atual)
$ rvm use 2.0.0 --default
$ rvm rubygems current
$ gem install bundler
$ sudo apt-get install libpq-dev imagemagick git-core

Crie o usuário do postgresql da forma que você preferir

Crie o Banco de Dados do Sistema no Postgresql

$ sudo apt-get install nginx
$ nginx -h
$ cat /etc/init.d/nginx
$ /etc/init.d/nginx -h
$ sudo service nginx start
$ sudo service nginx status (Ele deve estar rodando agora!)

Crie o arquivo nginx.conf no diretório config do seu projeto rails:

upstream unicorn {
  server unix:/tmp/unicorn.app_name.sock fail_timeout=0;
}

server {
  listen 80 default_server deferred;
  root /opt/apps/app_name/current/public; (Escolha o diretório em vermelho com carinho de acordo com a partição que está montada no sistema. Sugestão: rode df -h)

  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 120;
}

Adicione a gem do Unicorn ao projeto. Adicione a seguinte linha no arquivo Gemfile:

gem 'unicorn'

Crie a configuração do unicorn em config/unicorn.rb

root = "/opt/apps/app_name/current"
working_directory root

pid "#{root}/tmp/pids/unicorn.pid"

stderr_path "#{root}/log/unicorn.log"
stdout_path "#{root}/log/unicorn.log"

worker_processes Integer(ENV['WEB_CONCURRENCY'])
timeout 30
preload_app true

listen '/tmp/unicorn.app_name.sock', backlog: 64

before_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
    Process.kill 'QUIT', Process.pid
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end

# Force the bundler gemfile environment variable to
# reference the capistrano "current" symlink
before_exec do |_|
  ENV['BUNDLE_GEMFILE'] = File.join(root, 'Gemfile')
end

Crie o arquivo config/unicorn_init.sh.erb

#!/bin/sh
set -e

# when to timeout a request, a lower value limits the risk that
# a long running process will block all connections
TIMEOUT=${TIMEOUT-60}

# the path to the app, dynamically populate from the capistrano
# definition
APP_ROOT=/opt/apps/<%= application %>/current

# where we're going to store unicorns pid file, must match what is
# specified in unicorn.rb.erb
PID=$APP_ROOT/tmp/pids/unicorn.pid
CMD="cd $APP_ROOT; bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E <%= rails_env %>"
AS_USER=deploy
set -u

OLD_PIN="$PID.oldbin"

sig () {
  test -s "$PID" && kill -$1 `cat $PID`
}

oldsig () {
  test -s $OLD_PIN && kill -$1 `cat $OLD_PIN`
}

workersig () {
  workerpid="$APP_ROOT/tmp/pids/unicorn.$2.pid"
  
  test -s "$workerpid" && kill -$1 `cat $workerpid`
}

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"
  ;;
kill_worker)
  workersig QUIT $2 && exit 0
  echo >&2 "Worker not running"
  ;;
restart|reload)
  sig USR2 && 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 <start|stop|restart|upgrade|force-stop|reopen-logs>"
  exit 1
  ;;
esac

Adicione a gem do capistrano ao projeto:

$ vim Gemfile

group :development do
  gem 'capistrano-rails'
  gem 'capistrano-rvm'
  gem 'capistrano3-unicorn'
end

Instale a gem do Capistrano

$ bundle exec cap install

Atualize o arquivo do Capistrano: Capfile, na raiz do projeto:

require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rvm'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'
load 'deploy'
load 'config/deploy' # remove this line to skip loading any of the default tasks

# Load custom tasks from `lib/capistrano/tasks' if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

Atualize o arquivo de Deploy em: config/deploy.rb

set :stages, %w(production staging)
set :default_stage, "staging"
require 'capistrano/ext/multistage'

set :whenever_command, "bundle exec whenever"
set :whenever_environment, defer { stage }
# require "whenever/capistrano"

set :application, "app_name"
set :user, "caio"
set :port, 22

set :deploy_via, :remote_cache
set :use_sudo, false
set :keep_releases, 1

set :scm, "git"
set :repository, "git@gitlab.ifce.edu.br:dgti/app_name.git"
set(:deploy_to) { "/home/#{user}/web/#{rails_env}" }

default_run_options[:pty] = true
ssh_options[:forward_agent] = true

# simple method to create a file from an erb template. Used
# to generate dynamic configuration files.
def template(from, to)
    erb = File.read(from)
    put ERB.new(erb).result(binding), to
end

Crie os arquivos do seu(s) ambiente(s) no diretório config/deploy Observar exemplo dos arquivos de outros sistemas.

==== Gere e Adicione a chave ssh do servidor no repositório git remoto (no caso o gitlab do ifce) Entre no diretório do ssh: ====

cd ~/.ssh && ls

Verifique se o arquivo id_rsa.pub já existe. Caso não existe você deve criá-lo com o seguinte comando:

ssh-keygen -t rsa -C "app_name@ifce.edu.br"

Apenas fique apertando Enter nos prompts que serão exibidos. Não precisa digitar nada. Agora você precisa copiar o conteúdo da chave pública: id_rsa.pub para o repositório git (no caso o gitlab do ifce)

Vá no Projeto > Settings > Deploy Keys e crie uma nova, colando o conteúdo da chave no campo Key.
$ cap production deploy:check
cap staging deploy:setup

* Adicione a configuração do ambiente correspondente (production ou staging) ao arquivo:

/opt/apps/app_name/shared/config/database.yml

* Dê permissões para o arquivo de inicialização do unicorn

chmod +x /opt/apps/app_name/shared/config/unicorn_init.sh

* Remova o site padrão do nginx

sudo rm /etc/nginx/sites-enabled/default

* Reinicie o nginx

sudo service nginx restart

* Deploy

$ cap production deploy
  • linux/rails_deploy.txt
  • Última modificação: 2021/08/25 10:33
  • (edição externa)