linux:rails_with_puma_deploy

Diferenças

Aqui você vê as diferenças entre duas revisões dessa página.

Link para esta página de comparações

linux:rails_with_puma_deploy [2017/06/13 12:51]
1891982 [Adicionando configuração de deploy na aplicação]
linux:rails_with_puma_deploy [2021/08/25 10:33]
Linha 1: Linha 1:
-===== Publicando aplicação rails em produção usando Ubuntu + Rails 5 + Nginx + Puma + PostgreSQL + Capistrano 3 ===== 
- 
-Puma é um servidor HTTP 1.1 de aplicações Ruby/Rack, simples, rápido, que utiliza threads e altamente concorrente. Puma é indicado para uso tanto em ambientes de desenvolvimento quanto de produção. Atualmente é preferível fazer deploy de aplicações Rails utilizando o Puma devido a sua performance superior. 
- 
-Entre na máquina via ssh 
-<code> 
-$ ssh usuario@app_name.ifce.edu.br 
-</code> 
-Obs: Caso a chave ssh do servidor tenha sido alterada, por algum motivo específico, remova o arquivo known_hosts: 
- 
-<code> 
-rm ~/.ssh/known_hosts 
-</code> 
- 
-==== Criando usuário da aplicação ==== 
- 
-É 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 
- 
-<code> 
-sudo adduser minha_app 
-</code> 
- 
-Digite a senha e as informações necessárias até finalizar o processo 
- 
-Adicione o usuário ao arquivo sudoers: 
- 
-<code> 
-sudo visudo 
-</code> 
- 
-No final do arquivo adicione: 
- 
-<code> 
-minha_app ALL=(ALL) NOPASSWD:ALL 
-</code> 
- 
-Digite Ctrl + O para salvar e depois Ctrl + X para fechar o arquivo 
- 
-Logue com esse novo usuário 
- 
-<code> 
-su minha_app 
-</code> 
- 
-Troque o dono do diretório de deploy que utilizaremos: /mnt 
- 
-<code> 
-sudo chown -R minha_app:minha_app mnt/ 
-</code> 
- 
-==== Adicione sua chave ssh ao servidor para se logar sem senha: ==== 
- 
-Dê ssh para alguma máquina a fim de criar o diretório ~/.ssh 
- 
-<code> 
-ssh usuario@app_name.ifce.edu.br 
-</code> 
- 
-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): 
- 
-<code> 
-cat ~/.ssh/id_rsa.pub 
-</code> 
- 
-No servidor adicione a chave ao arquivo: 
- 
-<code> 
-vim ~/.ssh/authorized_keys 
-</code> 
- 
-Cole conteúdo da chave nesse arquivo 
- 
-Salve e teste 
- 
-==== Instalando o RVM ==== 
- 
-**Corrigindo possíveis problemas de dns na máquina** 
- 
-Edite o arquivo /etc/network/interfaces e adicione o conteúdo abaixo após a linha # dns-* options are implemented by the resolvconf package, if installed 
- 
-<code> 
-dns-nameservers 8.8.8.8 
-dns-nameservers 8.8.4.4 
-dns-nameservers 200.17.33.7 
-dns-search ifce.edu.br 
-</code> 
- 
-Reinicie a máquina: 
- 
-<code> 
-sudo reboot 
-</code> 
- 
- 
- 
-**Instalando o Curl** 
- 
-<code> 
-$ sudo apt-get update 
-$ sudo apt-get install curl 
-</code> 
- 
-<fc #ff0000> 
-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 
-</fc> 
- 
-<code> 
-$ curl -L get.rvm.io | bash -s stable 
-</code> 
- 
- 
-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:  
- 
-<code> 
-command curl -sSL https://rvm.io/mpapis.asc | gpg --import - 
-</code> 
- 
-E depois rode novamente os comandos abaixo para finalizar a instalação do rvm: 
- 
-<code> 
-$ curl -L get.rvm.io | bash -s stable 
-</code> 
- 
-Agora é preciso instalar os requisitos para instalar o ruby e instalar também a gem bundles para gerenciar as outras gems do projeto: 
- 
-<code> 
-$ 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 
-</code> 
- 
-==== Instale a lib de dependência do PostgreSQL, Imagemagick e Git ==== 
- 
- 
-<code> 
-$ sudo apt-get install libpq-dev imagemagick git-core 
-</code> 
- 
-Crie o usuário do postgresql da forma que você preferir 
- 
-Crie o Banco de Dados do Sistema no Postgresql 
- 
- 
-==== Instalando e configurando o Nginx ==== 
- 
-<code> 
-$ sudo apt-get install nginx 
-$ sudo service nginx start 
-$ sudo service nginx status (Ele deve estar rodando agora!) 
-</code> 
- 
-==== Adicionando configuração de deploy na aplicação ==== 
- 
-Adicione o código abaixo no Gemfile da sua aplicação: 
- 
-<code> 
-# Javascript runtime 
-gem 'therubyracer' 
- 
-group :development do 
-    gem 'capistrano',         require: false 
-    gem 'capistrano-rvm',     require: false 
-    gem 'capistrano-rails',   require: false 
-    gem 'capistrano-bundler', require: false 
-    gem 'capistrano3-puma',   require: false 
-end 
- 
-gem 'puma' 
-</code> 
- 
-Instale as novas gems: 
- 
-<code> 
-bundle install 
-</code> 
- 
-Crie os arquivos do capistrano na sua aplicação usando o comando abaixo: 
- 
-<code> 
-cap install 
-</code> 
- 
-Substitua o conteúdo do arquivo Capfile pelo código abaixo: 
- 
-<code> 
-# Load DSL and set up stages 
-require "capistrano/setup" 
- 
-# Include default deployment tasks 
-require "capistrano/deploy" 
- 
-require "capistrano/scm/git" 
-install_plugin Capistrano::SCM::Git 
- 
-# Adittional plugins 
-require 'capistrano/rails' 
-require "capistrano/bundler" 
-require "capistrano/rvm" 
-require "capistrano/puma" 
-install_plugin Capistrano::Puma  # Default puma tasks 
-install_plugin Capistrano::Puma::Workers  # if you want to control the workers (in cluster mode) 
-require "capistrano/rails/assets" 
-require "capistrano/rails/migrations" 
-require 'capistrano/sidekiq' 
-require 'capistrano/sidekiq/monit' 
- 
- 
-# Load custom tasks from `lib/capistrano/tasks` if you have any defined 
-Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r } 
-</code> 
- 
- 
-Substitua o conteúdo do arquivo config/deploy.rb, substituindo app_name pelo nome da sua aplicação, pelo código abaixo: 
- 
- 
-<code> 
-# Change these 
-server 'app_name.ifce.edu.br', port: 22, roles: [:web, :app, :db], primary: true 
- 
-set :repo_url,        'git@gitlab.ifce.edu.br:dgti/app_name.git' 
-set :application,     'app_name' 
-set :user,            'app_name' 
-set :puma_threads,    [4, 16] 
-set :puma_workers,    4 
- 
-# Don't change these unless you know what you're doing 
-set :pty,             true 
-set :use_sudo,        false 
-set :stage,           :production 
-set :deploy_via,      :remote_cache 
-set :deploy_to,       "/mnt/apps/#{fetch(:application)}" 
-set :puma_bind,       "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock" 
-set :puma_state,      "#{shared_path}/tmp/pids/puma.state" 
-set :puma_pid,        "#{shared_path}/tmp/pids/puma.pid" 
-set :puma_access_log, "#{release_path}/log/puma.error.log" 
-set :puma_error_log,  "#{release_path}/log/puma.access.log" 
-set :ssh_options,     { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/id_rsa.pub) } 
-set :puma_preload_app, true 
-set :puma_worker_timeout, nil 
-set :puma_init_active_record, true  # Change to false when not using ActiveRecord 
-set :keep_releases, 1 
-set :linked_dirs, %w{log uploads} 
- 
-namespace :deploy do 
-  desc "Make sure local git is in sync with remote." 
-  task :check_revision do 
-    on roles(:app) 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 
-  end 
- 
-  desc 'Initial Deploy' 
-  task :initial do 
-    on roles(:app) do 
-      before 'deploy:restart', 'puma:start' 
-      invoke 'deploy' 
-      sudo "ln -nfs #{release_path}/config/puma_init.sh /etc/init.d/puma_#{fetch(:application)}" 
-      sudo "ln -nfs #{release_path}/config/puma.rb.example #{shared_path}/puma.rb" 
-    end 
-  end 
- 
-  desc 'Creating symlink for config file' 
-  task :config_symlink do 
-    on roles(:app) do 
-      sudo "ln -nfs #{release_path}/config/puma_init.sh /etc/init.d/puma_#{fetch(:application)}" 
-      sudo "chmod +x /etc/init.d/puma_#{fetch(:application)}" 
-      execute "ln -nfs #{release_path}/config/puma.rb.example #{shared_path}/puma.rb" 
-      execute "ln -sf #{shared_path}/config/database.yml #{release_path}/config/database.yml" 
-      execute "ln -sf #{shared_path}/config/secrets.yml #{release_path}/config/secrets.yml" 
-      execute "ln -sf #{shared_path}/puma.rb #{release_path}/config/puma.rb" 
-    end 
-  end 
- 
-  desc 'Creating permissions and running db:seed' 
-  task :populate_db do 
-    on roles(:app) do 
-      execute "cd #{release_path} && ~/.rvm/bin/rvm default do bundle exec rake permissions:create RAILS_ENV=#{fetch(:stage)}" 
-      execute "cd #{release_path} && ~/.rvm/bin/rvm default do bundle exec rake db:seed RAILS_ENV=#{fetch(:stage)}" 
-    end 
-  end 
- 
-  desc "Instalando crontab" 
-  task :install_crontab do 
-    on roles(:app) do 
-      run "cd #{release_path} && bundle exec whenever --update-crontab #{fetch(:application)}" 
-    end 
-  end 
- 
-  after "deploy:initial", :install_crontab 
-  after "deploy:migrating", :populate_db 
-  after  "symlink:linked_dirs",  :config_symlink 
-  before :starting,     :check_revision 
-  after  :finishing,    :compile_assets 
-  after  :finishing,    :cleanup 
-end 
- 
-</code> 
- 
-Crie o arquivo config/nginx.conf e utilize o conteúdo abaixo (substitua os a localização da aplicação): 
- 
-<code> 
-upstream puma { 
-  server unix:///home/deploy/apps/appname/shared/tmp/sockets/appname-puma.sock; 
-} 
- 
-server { 
-  listen 80 default_server deferred; 
- 
-  root /home/deploy/apps/appname/current/public; 
-  access_log /home/deploy/apps/appname/current/log/nginx.access.log; 
-  error_log /home/deploy/apps/appname/current/log/nginx.error.log info; 
- 
-  location ^~ /assets/ { 
-    gzip_static on; 
-    expires max; 
-    add_header Cache-Control public; 
-  } 
- 
-  try_files $uri/index.html $uri @puma; 
-  location @puma { 
-    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
-    proxy_set_header Host $http_host; 
-    proxy_redirect off; 
- 
-    proxy_pass http://puma; 
-  } 
- 
-  error_page 500 502 503 504 /500.html; 
-  client_max_body_size 10M; 
-  keepalive_timeout 10; 
-} 
-</code> 
- 
-==== Coloque o puma para ser iniciado automaticamente no boot da máquina ==== 
- 
-Crie o arquivo config/puma.rb.example com o seguinte conteúdo, substituindo <app_name> pelo nome da sua app: 
- 
-<code> 
-#!/usr/bin/env puma 
-directory '/mnt/apps/<app_name>/current' 
-rackup "/mnt/apps/<app_name>/current/config.ru" 
-environment 'production' 
- 
-pidfile "/mnt/apps/<app_name>/shared/tmp/pids/puma.pid" 
-state_path "/mnt/apps/<app_name>/shared/tmp/pids/puma.state" 
-stdout_redirect '/mnt/apps/<app_name>/current/log/puma.error.log', '/mnt/apps/<app_name>/current/log/puma.access.log', true 
- 
-threads 4,16 
- 
-bind 'unix:///mnt/apps/<app_name>/shared/tmp/sockets/<app_name>-puma.sock' 
- 
-workers 4 
- 
-preload_app! 
- 
-on_restart do 
-  puts 'Refreshing Gemfile' 
-  ENV["BUNDLE_GEMFILE"] = "/mnt/apps/<app_name>/current/Gemfile" 
-end 
- 
- 
-on_worker_boot do 
-  ActiveSupport.on_load(:active_record) do 
-    ActiveRecord::Base.establish_connection 
-  end 
-end 
-</code> 
- 
-Crie o arquivo config/puma__init.sh com o seguinte conteúdo, substituindo <app_name> pelo nome da sua app: 
- 
- 
-<code> 
-#! /bin/sh 
- 
-### BEGIN INIT INFO 
-# Provides:          puma 
-# Required-Start:    $remote_fs $syslog 
-# Required-Stop:     $remote_fs $syslog 
-# Default-Start:     2 3 4 5 
-# Default-Stop:      0 1 6 
-# Short-Description: Controls puma server 
-# Description:       Controls puma server 
-### END INIT INFO 
- 
-PUMA_WORKING_DIRECTORY=/mnt/apps/<app_name>/current 
-PUMA_CONFIG_FILE=config/puma.rb 
-PUMA_PID_FILE=/mnt/apps/<app_name>/shared/tmp/pids/puma.pid 
-PUMA_SOCKET_FILE=/mnt/apps/<app_name>/shared/tmp/sockets/<app_name>-puma.sock 
-PUMA_USER=<user_name> 
- 
-puma_is_running() { 
-  if [ -S $PUMA_SOCKET_FILE ] && [ -e $PUMA_PID_FILE ] && cat $PUMA_PID_FILE | xargs pgrep -P > /dev/null; then 
-    return 0 
-  else 
-    return 1 
-  fi 
-} 
- 
-case "$1" in 
-  start) 
-    if puma_is_running; then 
-      echo "Puma is running" 
-    else 
-      su -c "cd $PUMA_WORKING_DIRECTORY && bundle exec puma -C $PUMA_CONFIG_FILE --daemon" - $PUMA_USER 
-      echo "Puma started" 
-    fi 
-  ;; 
-  stop) 
-    if puma_is_running; then 
-      su -c "kill -s SIGTERM `cat $PUMA_PID_FILE`" - $PUMA_USER 
-      rm -f $PUMA_PID_FILE 
-      rm -f $PUMA_SOCKET_FILE 
-      echo "Puma stopped" 
-    else 
-      echo "Puma is not running" 
-    fi 
-  ;; 
-  restart) 
-    if puma_is_running; then 
-      su -c "kill -s SIGUSR2 `cat $PUMA_PID_FILE`" - $PUMA_USER 
-      echo "Puma restarted" 
-    else 
-      echo "Puma is not running" 
-    fi 
-  ;; 
-  status) 
-    if puma_is_running; then 
-      echo "Puma is running" 
-      exit 0 
-    else 
-      echo "Puma is not running" 
-      exit 1 
-    fi 
-  ;; 
-  *) 
-    echo "Usage: $0 {start|stop|restart|status}" 
-    exit 1 
-  ;; 
-esac 
-</code> 
- 
- 
-==== 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 do servidor: 
- 
-<code> 
-cd ~/.ssh && ls 
-</code> 
- 
-Verifique se o arquivo **id_rsa.pub** já existe. Caso não existe você deve criá-lo com o seguinte comando: 
- 
-<code> 
-ssh-keygen -t rsa -C "app_name@ifce.edu.br" 
-</code> 
- 
-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) 
- 
-<code> 
-Vá no Projeto > Settings > Repository > Deploy Keys e crie uma nova, colando o conteúdo da chave no campo Key. 
-</code> 
- 
-Adicione a chave ssh ao seu identity provider 
- 
-<code> 
-ssh-add ~/.ssh/id_rsa 
-</code> 
- 
- 
-==== Deploy inicial da estrutura (criação da estrutura de diretórios inicial) ==== 
- 
-Comite todas as mudanças no projeto 
- 
-<code> 
-git add -A . 
-git commit -m "Configuração de deploy com capistrano" 
-git push origin master 
-</code> 
- 
-Crie o diretório /mnt/apps/<app_name>/shared/config, com os arquivos database.yml e secrets.yml. E coloque o conteúdo correto em cada um dos arquivos. 
- 
-Execute o deploy inicial que irá criar a estrutura de diretórios do capistrano 
- 
-<code> 
-cap production deploy:initial 
-</code> 
- 
- 
-<fc #ff0000> 
-Obs: Deverão ocorrer erros no deploy inicial. Caso ocorram, siga os passos abaixo e depois execute um deploy normal, usando: cap production deploy. (Esse comando executado acima, foi apenas para criar a estrutura inicial do deploy, ele dá erro mesmo, é normal.) 
-</fc> 
- 
- 
- 
-==== Configurações finais de deploy ==== 
- 
-* Rode o comando abaixo na máquina remota para configurar o nginx 
- 
-<code> 
-sudo ln -nfs "/mnt/apps/app_name/current/config/nginx.conf" "/etc/nginx/sites-enabled/app_name" 
-</code> 
- 
- 
-* Adicione a configuração do ambiente correspondente (production ou staging) ao arquivo: 
- 
-<code> 
-/mnt/apps/app_name/shared/config/database.yml 
-</code> 
- 
-* Adicione as configurações abaixo(no projeto local) no arquivo config/enviroments/production.rb: 
- 
-<code> 
-config.action_mailer.delivery_method = :smtp 
-  config.action_mailer.default_url_options = { :host => 'http://<app_name>.ifce.edu.br' } 
- 
-  ActionMailer::Base.delivery_method = :smtp 
-  ActionMailer::Base.smtp_settings = { 
-    :address        => 'm.ifce.edu.br', 
-    :domain         => 'ifce.edu.br', 
-    :port           => 25, 
-    :openssl_verify_mode  => 'none' 
-  } 
-</code> 
- 
-* Adicione o token do devise (no seu projeto local) em config/initializers/devise.rb: 
- 
-<code> 
-config.secret_key = <sua_chave_aqui> 
-</code> 
- 
- 
-<fc #ff0000> 
-Você deve gerar essa chave na sua máquina local usando o comando: rake secret 
-</fc> 
- 
- 
-* Crie o arquivo /mnt/apps/app_name/shared/config/secrets.yml com o conteúdo: 
- 
-<code> 
-production: 
-  secret_key_base: <Sua chave aqui> 
-</code> 
- 
- 
-<fc #ff0000> 
-Você deve gerar essa chave na sua máquina local usando o comando: rake secret 
-</fc> 
- 
- 
-<fc #ff0000> 
-Após realizar as mudanças no seu projeto local, não esqueça de comitá-las e dar um push para o git remoto. 
-</fc> 
- 
- 
-* Remova o site padrão do nginx 
- 
-<code> 
-sudo rm /etc/nginx/sites-enabled/default 
-</code> 
- 
-* Reinicie o nginx 
- 
-<code> 
-sudo service nginx restart 
-</code> 
- 
-* Se você usa sidekiq no seu projeto instale o monit: 
- 
-<code> 
-sudo apt-get install monit 
-</code> 
- 
-Configure o monit para suportar a interface http 
- 
-Edite o arquivo: /etc/monit/monitrc e procure por: set httpd. Descomente as linhas para ficar igual o código abaixo: 
- 
-<code> 
-set httpd port 2812 and 
-    use address localhost  # only accept connection from localhost 
-    allow localhost        # allow localhost to connect to the server and 
-    allow admin:monit 
-</code> 
- 
-Reinicie o monit 
- 
-<code> 
-sudo /etc/init.d/monit restart 
-</code> 
- 
-* Deploy 
- 
-<code> 
-$ cap production deploy 
-</code> 
- 
-* Coloque o puma para ser iniciado automaticamente no boot da máquina 
- 
-<code> 
-sudo update-rc.d puma_<app_name> defaults 
-</code> 
  
  • linux/rails_with_puma_deploy.txt
  • Última modificação: 2021/08/25 10:33
  • (edição externa)