Как деплоить Ruby on Rails через
Capistrano + NGINX + Passenger

Автор: https://github.com/krdprog

<< назад на главную


Перед работой с инструкцией замените на свои данные следующие переменные (данные меняются динамически средствами Vue.js и нигде не сохраняются, отслеживания через счётчик на данной странице нет):

IP сервера:

Версия Ruby:

Версия bundler:

Название каталога проекта, файлов nginx конфигурации:

Адрес сайта:

Имя базы данных:

Репозиторий с кодом проекта:

Из какой ветки брать код:

Через замену нужные данные подставятся в нужные места.


Настройка сервера перед деплоем


      ssh root@{{ ip }}

      adduser deploy

      # password: your_password_here

      adduser deploy sudo

      exit
      

      # local
      ssh-copy-id root@{{ ip }}
      ssh-copy-id deploy@{{ ip }}
      

      ssh deploy@{{ ip }}
      

      curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -

      curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -

      echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list

      sudo add-apt-repository ppa:chris-lea/redis-server

      sudo apt-get update

      sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev \
      libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev \
      libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev \
      dirmngr gnupg apt-transport-https ca-certificates redis-server redis-tools nodejs yarn

      git clone https://github.com/rbenv/rbenv.git ~/.rbenv

      echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc

      echo 'eval "$(rbenv init -)"' >> ~/.bashrc

      git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

      echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc

      git clone https://github.com/rbenv/rbenv-vars.git ~/.rbenv/plugins/rbenv-vars

      exec $SHELL

      rbenv install {{ ruby_version }}

      rbenv global {{ ruby_version }}

      ruby -v

      # gem install bundler

      # If you want install old bundler: gem install bundler -v 1.17.3

      gem install bundler -v {{ bundler_version }}

      bundle -v

      sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7

      sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger \
      focal main > /etc/apt/sources.list.d/passenger.list'

      sudo apt-get update

      sudo apt-get install -y nginx-extras libnginx-mod-http-passenger

      if [ ! -f /etc/nginx/modules-enabled/50-mod-http-passenger.conf ]; then \
      sudo ln -s /usr/share/nginx/modules-available/mod-http-passenger.load \
      /etc/nginx/modules-enabled/50-mod-http-passenger.conf ; fi

      sudo ls /etc/nginx/conf.d/mod-http-passenger.conf
      

      sudo nano /etc/nginx/conf.d/mod-http-passenger.conf
      

      # добавить в файл
      passenger_ruby /home/deploy/.rbenv/shims/ruby;
      

      sudo service nginx start
      

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

      sudo nano /etc/nginx/sites-available/{{ project_name }}.conf
      

      server {
        listen 80;
        listen [::]:80;

        server_name {{ site_url }};
        access_log /var/log/nginx/{{ project_name }}.access.log;
        error_log /var/log/nginx/{{ project_name }}.error.log;

        passenger_enabled on;
        passenger_app_env production;

        root /home/deploy/{{ project_name }}/current/public;

        location /cable {
          passenger_app_group_name myapp_websocket;
          passenger_force_max_concurrent_requests_per_process 0;
        }

        # Allow uploads up to 100MB in size
        client_max_body_size 100m;

        location ~ ^/(assets|packs) {
          expires max;
          gzip_static on;
        }
      }
      

      sudo ln -s /etc/nginx/sites-available/{{ project_name }}.conf /etc/nginx/sites-enabled/{{ project_name }}.conf

      sudo nginx -T

      sudo service nginx restart && sudo service nginx reload
      

      # deploy@

      locale
      sudo locale-gen ru_RU.UTF-8
      sudo nano /etc/environment

      LANGUAGE=en_US.UTF-8
      LANG=en_US.UTF-8
      LC_ALL=ru_RU.UTF-8
      LC_COLLATE=ru_RU.UTF-8
      LC_TIME=en_US.UTF-8

      timedatectl
      sudo dpkg-reconfigure tzdata

      Europe/Moscow
      

Этот шаг нужен, если на проекте надо из гит убрать секретные файлы


      # локально в каталоге проекта (если у нас в git сохранены секретные файлы. уберём их)

      git rm config/database.yml --cached

      # add to .gitignore
      /config/database.yml

      # and commit
      

      # @deploy

      sudo apt-get install postgresql postgresql-contrib libpq-dev

      sudo su - postgres

      # user postgres

      psql
      \dg
      create user deploy with password 'yourpasswordhere';

      alter user deploy with superuser createdb createrole replication;

      \l
      create database "{{ db_name }}" with owner = deploy;

      \q

      psql -h localhost -U deploy -W {{ db_name }}

      \q
      exit
      

      # local. add to Gemfile

      gem 'capistrano', '~> 3.11'
      gem 'capistrano-rails', '~> 1.4'
      gem 'capistrano-passenger', '~> 0.2.0'
      gem 'capistrano-rbenv', '~> 2.1', '>= 2.1.4'
      

      bundle

      cap install STAGES=production
      

      # add to Capfile

      require 'capistrano/rails'
      require 'capistrano/passenger'
      require 'capistrano/rbenv'

      set :rbenv_type, :user
      set :rbenv_ruby, '{{ ruby_version }}'
      

      # add to config/deploy.rb

      set :application, "{{ project_name }}"
      set :repo_url, "{{ git_repo }}"

      set :branch, "{{ branch_name }}"

      # Deploy to the user's home directory
      set :deploy_to, "/home/deploy/{{ project_name }}"

      append :linked_files, 'config/database.yml', 'config/credentials.yml.enc', 'config/master.key'
      append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', '.bundle',
                           'public/system', 'public/uploads'

      # Only keep the last 5 releases to save disk space
      set :keep_releases, 5
      

      # local config/database.yml

      default: &default
        adapter: postgresql
        encoding: unicode
        pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
        timeout: 5000

      development:
        <<: *default
        host: localhost
        port: 5432
        user: postgres
        database: rubydeploy_dev

      test:
        <<: *default
        host: localhost
        port: 5432
        database: rubydeploy_test

      production:
        <<: *default
        host: localhost
        port: 5432
        database: {{ db_name }}
        username: deploy
        password: yourdbpassword
      

      # add to config/production/deploy.rb

      server '{{ ip }}', user: 'deploy', roles: %w{app db web}
      

      ssh deploy@{{ ip }}

      mkdir /home/deploy/{{ project_name }}

      exit
      

      # local. если надо обновить секретные файлы
      rm config/master.key
      rm config/credentials.yml.enc

      rails credentials:edit
      

      # local in project

      # если были изменения в коде
      git add
      git commit -m "Edit deploy files"
      git push

      # далее
      cap production deploy

      # при первом деплое споткнётся об ERROR
      # linked file /home/deploy/{{ project_name }}/shared/config/database.yml does not exist on {{ ip }}
      # теперь мы можем добавить на сервер в структуру секретные файлы проекта

      cd config

      scp database.yml deploy@{{ ip }}:/home/deploy/{{ project_name }}/shared/config/database.yml

      scp credentials.yml.enc deploy@{{ ip }}:/home/deploy/{{ project_name }}/shared/config/credentials.yml.enc

      scp master.key deploy@{{ ip }}:/home/deploy/{{ project_name }}/shared/config/master.key

      # далее
      cap production deploy
      

      # если выпала ошибка Passenger надо включить показ ошибок

      ssh deploy@{{ ip }}

      sudo nano /etc/nginx/sites-available/{{ project_name }}.config

      # добавить строку
      passenger_friendly_error_pages on;

      sudo nginx -T

      sudo service nginx restart && sudo service nginx reload

      # после исправления ошибки, убрать строку и перезапустить nginx
      

Выпуск сертификата SSL

  • https://eax.me/lets-encrypt/

      sudo add-apt-repository ppa:certbot/certbot
      sudo apt-get update
      sudo apt-get install python3-certbot-nginx
      

      sudo certbot --nginx -d {{ site_url }}
      
  • https://whatsmychaincert.com/
  • https://www.ssllabs.com/ssltest/analyze.html

Перевыпуск сертификата SSL


      sudo certbot renew --dry-run
      

      sudo nano /etc/nginx/sites-available/{{ project_name }}.conf
      

      server {
        listen 80;
        listen [::]:80;

        server_name {{ site_url }};

        access_log /var/log/nginx/{{ project_name }}.access.log;
        error_log /var/log/nginx/{{ project_name }}.error.log;

        passenger_enabled on;
        passenger_app_env production;

        root /home/deploy/{{ project_name }}/current/public;

        location /cable {
          passenger_app_group_name myapp_websocket;
          passenger_force_max_concurrent_requests_per_process 0;
        }

        # Allow uploads up to 100MB in size
        client_max_body_size 100m;

        location ~ ^/(assets|packs) {
          expires max;
          gzip_static on;
        }

        listen [::]:443 ssl; # managed by Certbot
        listen 443 ssl; # managed by Certbot
        ssl_certificate /etc/letsencrypt/live/{{ site_url }}/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/{{ site_url }}/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed
      }
      

      sudo nginx -T

      sudo service nginx restart && sudo service nginx reload
      

Как запустить рельсовую консоль:


      ssh deploy@{{ ip }}

      cd /home/deploy/{{ project_name }}/current/bin
      RAILS_ENV=production bundle exec rails c
      

<< назад на главную

 

Снятие ответственности: сайт не является исчерпывающей документацией. Это всего лишь одна из точек зрения на рассматриваемый вопрос по деплою приложений. За достоверной информацией просьба обращаться к документации к программному обеспечению. Автор снимает с себя ответственность за последствия следования описанной инструкции по деплою. Данная инструкция носит чисто информационный характер и является сгруппированной коллекцией собранных материалов из открытых источников в интернете.