Защита связи в трехуровневом приложении Rails с использованием SSH-туннелей

Вступление

Веб-приложения часто проектируются с тремя различными уровнями:

  • Первый уровень - этоpresentation layer, то есть то, что видит пользователь.

  • Затем идетapplication layer, который предоставляетbusiness logic приложения.

  • Наконец,data layer хранит данные, необходимые приложению.

В приложенииRuby on Rails это свободно отображается на веб-сервер для уровня представления, сервер Rails для уровня приложения и базу данных для уровня данных. В этой настройке прикладной уровень связывается с уровнем данных для извлечения данных для приложения, которые затем отображаются пользователю через уровень представления.

Хотя все эти приложения можно установить на одном сервере, размещение каждого слоя на своем собственном сервере облегчает масштабирование приложения. Например, если бы сервер Rails стал узким местом, вы могли бы добавить больше серверов приложений, не затрагивая другие два уровня.

В этом руководстве вы развернете приложение Rails в трехуровневой конфигурации, установив уникальный набор программного обеспечения на три отдельных сервера, сконфигурировав каждый сервер и его компоненты для взаимодействия и совместной работы, а также защитив соединения между ними с помощью туннелей SSH. Для программного стека вы будете использоватьNginx в качестве веб-сервера на уровне представления,Puma в качестве сервера приложений Rails на уровне приложений иPostgreSQL в качестве базы данных на уровне данных. .

Предпосылки

Чтобы завершить этот урок, вам нужно раскрутить три сервера Ubuntu 16.04. Назовите этиweb-server,app-server иdatabase-server, и для каждого из них должна быть включена частная сеть.

На каждом из трех серверов должен быть пользователь без полномочий root с привилегиямиsudo, а также брандмауэр, настроенный для разрешения подключений по SSH (которые вы можете настроить с помощью нашегоInitial Server Setup guide). В контексте этого руководства пользовательsudo на каждом сервере называетсяsammy.

Кроме того, каждый из трех серверов имеет свои уникальные требования к конфигурации:

  • Наweb-server:

    • Установите и настройте веб-сервер Nginx. Для этого следуйте нашему руководству поHow to Install Nginx on Ubuntu 16.04.

  • Наapp-server:

    • Установите Node.js с помощью официального PPA, как описано вHow To Install Node.js on Ubuntu 16.04. Некоторые функции Rails, такие как конвейер активов, зависят от среды выполнения JavaScript, и Node.js предоставляет эту функцию.

    • Установите среду Ruby on Rails. Для этого следуйте нашему руководству поHow to Install Ruby on Rails with rbenv on Ubuntu 16.04. Следуя этому руководству, обязательно установите последнюю версию Ruby, которая на момент написания этой статьи была Ruby 2.5.1.

    • Установите PostgreSQL, как показано в первом разделе нашего руководстваHow To Use PostgreSQL with Your Ruby on Rails Application on Ubuntu 14.04. В этом разделе также описывается, как установитьlibpq-dev, еще один пакет, необходимый для этой трехуровневой установки.

    • Разверните приложение Rails с помощью Puma. Если у вас нет собственного приложения для развертывания, следуйте нашему руководству поHow To Deploy a Rails App with Puma and Nginx, чтобы развернуть образец приложения. Обратите внимание, что в разделе «Установить подключаемый модуль rbenv-vars» этого предварительного условия вы должны установить пользователя и пароль базы данных, отражающие значения, которые вы используете при установке PostgreSQL наdatabase-server. Кроме того, вы должны разрешить порт3000 через брандмауэр, чтобы раздел «Создать производственную базу данных» работал. Наконец, вам не нужно выполнять два последних шага этого обязательного учебного руководства: «Создание сценария запуска Puma» и «Установка и настройка Nginx».

  • Наdatabase-server:

    • Установите и настройте программное обеспечение базы данных PostgreSQL. Следуйте нашему руководству поHow To Install and Use PostgreSQL on Ubuntu 16.04, чтобы узнать, как это сделать. Следуя этому обязательному руководству, создайте роль PostgreSQL для своего приложения Rails с разрешениямиsuperuser, а также базу данных с тем же именем, что и роль PostgreSQL. В этом руководстве роль и база данных PostgreSQL называютсяsammy.

    • Установите пароль для вновь созданной роли PostgreSQL. Пропустите первую команду в «https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04#create -production-database-user [Create Production Database User] »учебника Puma (который вы также использовали для настройкиapp-server) и следуйте оставшимся командам в этом разделе, чтобы изменить пароль пользователя базы данных. . Обратите внимание, что имя роли PostgreSQL и пароль, который вы установили дляdatabase-server, должны быть идентичны тем, которые вы установили при установке PostgreSQLapp-server.

[[step-1 -—- create-a-user-for-the-ssh-tunnel]] == Шаг 1. Создание пользователя для SSH-туннелей

SSH tunnels - это зашифрованные соединения, которые могут отправлять данные с порта одного сервера на порт другого сервера, создавая впечатление, что программа прослушивания на втором сервере работает на первом. Наличие специального пользователя для туннелей SSH помогает повысить безопасность вашей установки: если злоумышленник получит доступ к пользователюsammy на одном из ваших серверов, он не сможет получить доступ к другим серверам в трех настройка уровня. Аналогично, если злоумышленник получит доступ к пользователюtunnel, он не сможет редактировать файлы в каталоге приложения Rails и не сможет использовать командуsudo.

На каждом сервере создайте дополнительного пользователя с именемtunnel. Единственная функция пользователяtunnel - это создание туннелей SSH для облегчения связи между серверами, поэтому, в отличие отsammy, не даетtunnelsudo привилегий. Кроме того, пользовательtunnel не должен иметь права записи в каталог приложения Rails. Выполните следующую команду на каждом сервере, чтобы добавить пользователяtunnel:

sudo adduser tunnel

На машинеweb-server переключитесь на пользователяtunnel.

sudo su tunnel

Как пользовательtunnel создайте пару ключей SSH:

ssh-keygen

Сохраните ключ в расположении по умолчанию и не создавайте парольную фразу для ключей, так как это может усложнить аутентификацию позже при создании туннелей SSH между серверами.

После создания пары ключей вернитесь к пользователюsammy:

exit

Теперь переключитесь наapp-server и снова выполните те же команды:

sudo su tunnel
ssh-keygen
exit

Теперь вы настроили всех пользователей, которые вам понадобятся для оставшейся части урока. Net, вы внесете некоторые изменения в файл/etc/hosts для каждого пользователяtunnel, чтобы упростить процесс создания туннелей SSH.

[[step-2 -—- configuring-the-hosts-file]] == Шаг 2. Настройка файла Hosts

На протяжении всего этого руководства вы много раз должны ссылаться на IP-адресаapp-server илиdatabase-server в команде. Вместо того, чтобы запоминать и вводить эти IP-адреса каждый раз, вы можете добавить частные IP-адресаapp-server иdatabase-server в файл/etc/hosts каждого сервера. Это позволит вам использовать их имена в последующих командах вместо их адресов и значительно упростит процесс настройки SSH-туннелей.

Обратите внимание, что для простоты в этом руководстве вам предлагается добавить частные IP-адресаapp-server иdatabase-server в файл/etc/hosts на каждом из трех серверов. Хотя технически нет необходимости добавлять частные IP-адресаapp-server илиdatabase-server в их собственные файлыhosts, это не вызовет никаких проблем. Описанный здесь метод был выбран просто для скорости и удобства.

Сначала найдите частные IP-адреса вашихapp-server иdatabase-server. Если вы используете DigitalOcean Droplets, перейдите на панель управления и нажмите на названия этих капель. На любой из их страниц, относящихся к дроплетам, как публичные, так и частные IP-адреса отображаются в верхней части страницы.

Затем на каждом сервере откройте файл/etc/hosts в своем любимом текстовом редакторе и добавьте следующие строки:

sudo nano /etc/hosts

/etc/hosts

. . .
app-server_private_ip app-server
database-server_private_ip database-server

Добавляя эти строки в этот файл на каждом сервере, вы можете использовать именаapp-server иdatabase-server в командах, которые обычно требуют использования IP-адресов этих серверов. Вы будете использовать эту функцию для настройки ключей SSH, чтобы каждый из ваших пользователейtunnel мог подключаться к другим вашим серверам.

[[step-3 -—- setting-up-ssh-logins]] == Шаг 3. Настройка SSH-входа

Теперь, когда у вас есть пользовательtunnel и обновленный файл/etc/hosts на всех трех ваших серверах, вы готовы приступить к созданию SSH-соединений между ними.

Проходя этот шаг, представьте себе три уровня пирамиды сdatabase-server внизу,app-server в середине иweb-server наверху. app-server должен иметь возможность подключаться кdatabase-server, чтобы получить доступ к данным, необходимым для приложения Rails, аweb-server должен иметь возможность подключаться кapp-server, поэтому ему есть что подарить пользователям.

Таким образом, вам нужно только добавить открытый ключ SSH каждого пользователяtunnel на сервер «под ним», что означает, что вы должны добавить открытый ключ пользователяweb-servertunnel кapp-server и добавьте открытый ключ пользователяapp-servertunnel вdatabase-server. Это позволит вам установить зашифрованные SSH-туннели между уровнями и запретить любому перехватчику в сети считывать трафик, проходящий между ними.

Чтобы начать этот процесс, скопируйте открытый ключ пользователяtunnel наweb-server, расположенный в/home/tunnel/.ssh/id_rsa.pub, в файл/home/tunnel/.ssh/authorized_keys наapp-server.

Наweb-server отобразите открытый ключ пользователяtunnel в терминале с помощью следующей команды:

sudo cat /home/tunnel/.ssh/id_rsa.pub

Выберите вывод текста и скопируйте его в буфер обмена вашей системы.

SSH вapp-server в отдельном сеансе терминала и переключитесь на пользователя туннеля:

sudo su tunnel

Добавьте ключ из системного буфера обмена в файлauthorized_keys наapp-server. Вы можете использовать следующую команду, чтобы сделать это за один шаг. Не забудьте заменитьtunnel_ssh_publickey_copied_from_web_server открытым ключом в системном буфере обмена:

echo "tunnel_ssh_publickey_copied_from_web-server" >> /home/tunnel/.ssh/authorized_keys

После этого измените права доступа к файлуauthorized_keys, чтобы предотвратить несанкционированный доступ к нему:

chmod 600 /home/tunnel/.ssh/authorized_keys

Затем вернитесь к пользователюsammy:

exit

Затем отобразите открытый ключ пользователяtunnel наapp-server - расположенный в/home/tunnel/.ssh/id_rsa.pub - и вставьте его в файл/home/tunnel/.ssh/authorized_keys наdatabase-server:

sudo cat /home/tunnel/.ssh/id_rsa.pub
sudo su tunnel

Поскольку вы не сгенерировали пару ключей SSH наdatabase-server, вам нужно будет создать папку/home/tunnel/.ssh и настроить ее разрешения:

mkdir /home/tunnel/.ssh
chmod 700 /home/tunnel/.ssh

Затем добавьте открытый ключapp-server в файлauthorized_keys и настройте его разрешения:

echo "tunnel_ssh_publickey_copied_from_app-server" >> /home/tunnel/.ssh/authorized_keys
chmod 600 /home/tunnel/.ssh/authorized_keys

Затем вернитесь к пользователюsammy:

exit

Затем проверьте первое соединение, используя SSH для подключения кapp-server от вашегоweb-server в качестве пользователяtunnel:

sudo su tunnel
ssh tunnel@app-server

При первом подключении отweb-server кapp-server вы увидите сообщение с просьбой подтвердить, что машине, к которой вы подключаетесь, можно доверять. Введите «да», чтобы подтвердить подлинностьapp-server:

OutputThe authenticity of host '111.111.11.111 (111.111.11.111)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes

Вы увидите приветственный баннер изapp-server, а в командной строке будет показано, что вы вошли в системуapp-server. Это подтверждает, что соединение SSH отweb-server кapp-server работает правильно.

Выйдите из SSH-подключения кapp-server, а затем выйдите из пользователяtunnel, чтобы вернуться к пользователюweb-serversammy:

exit
exit

Затем выполните те же действия, чтобы проверить соединение SSH отapp-server кdatabase-server:

sudo su tunnel
ssh tunnel@database-server

Примите также подлинностьdatabase-server. Когда вы увидите приветственный баннер и командную строку отdatabase-server, вы узнаете, что SSH-соединение отapp-server кdatabase-server работает должным образом.

Выйдите из SSH-соединения наdatabase-server, а затем выйдите из пользователяtunnel:

exit
exit

Соединения SSH, которые вы установили в шаге, образуют основу туннелей SSH, которые обеспечат безопасную связь между вашими тремя уровнями сервера. Однако в их нынешнем виде эти соединения подвержены сбоям и поэтому не настолько надежны, как могли бы быть. Однако, установив дополнительное программное обеспечение и настроив туннель для работы в качестве службы, вы можете устранить эти уязвимости.

[[step-4 -—- setting-up-a-persistent-ssh-tunnel-to-the-database-server]] == Шаг 4 - Настройка постоянного SSH-туннеля к серверу базы данных

На последнем шаге вы получили доступ к командной строке на удаленном сервере с локального сервера. Туннель SSH позволяет вам сделать гораздо больше, туннелируя трафик от портов на локальном хосте к портам на удаленном. Здесь вы будете использовать SSH-туннель для шифрования соединения между вашимapp-server иdatabase-server.

Если вы выполнили все предварительные требования для этого руководства, вы установите PostgreSQL как наapp-server, так и наdatabase-server. Чтобы предотвратить конфликт номеров портов, необходимо настроить туннель SSH между этими серверами для пересылки соединений с порта5433 наapp-server на порт5432 наdatabase-server. Позже вы переконфигурируете свое приложение Rails (размещенное на вашемapp-server) для использования экземпляра PostgreSQL, запущенного наdatabase-server.

Начиная с пользователяsammy наapp-server, переключитесь на пользователяtunnel, которого вы создали на шаге 1:

sudo su tunnel

Запустите командуssh со следующими флагами и параметрами, чтобы создать туннель междуapp-server иdatabase-server:

ssh -f -N -L 5433:localhost:5432 tunnel@database-server
  • Параметр-f отправляетssh в фоновый режим. Это позволяет вам запускать новые команды в существующем приглашении, пока туннель продолжает работать как фоновый процесс.

  • Параметр-N указываетssh не выполнять удаленную команду. Это используется здесь, поскольку вы хотите только перенаправить порты.

  • За параметром-L следует значение конфигурации5433:localhost:5432. Это указывает, что трафик из порта5433 на локальной стороне (app-server) перенаправляется на порт5432localhost на удаленном сервере (database-server). Обратите внимание, чтоlocalhost здесь с точки зрения удаленного сервера.

  • Последняя часть команды,tunnel@database-server, указывает пользователя и удаленный сервер для подключения.

После установления SSH-туннеля вернитесь к пользователюsammy:

exit

В этот момент туннель работает, но нет ничего, что следило бы за ним, чтобы убедиться, что он не отключился. В случае сбоя процесса туннель отключится, приложение Rails больше не сможет взаимодействовать со своей базой данных, и вы начнете видеть ошибки.

Убейте созданный вами туннель, поскольку мы собираемся сделать более надежную настройку. Поскольку соединение находится в фоновом режиме, вам нужно будет найти его идентификатор процесса, чтобы уничтожить его. Поскольку каждый туннель создается пользователемtunnel, вы можете найти его идентификатор процесса, перечислив текущие процессы и отфильтровав вывод по ключевому слову «туннель»:

ps axu | grep tunnel

Это вернет что-то вроде вывода ниже:

Outputtunnel   21814  0.0  0.1  44920   692 ?        Ss   14:12   0:00 ssh -f -N -L 5433:localhost:5432 tunnel@database-server
sammy    21816  0.0  0.2  12916  1092 pts/0    S+   14:12   0:00 grep --color=auto tunnel

Остановите процесс, запустив командуkill, за которой следует идентификатор процесса:

sudo kill 21814

Чтобы поддерживать постоянное соединение SSH между сервером приложений и базой данных, установитеautossh. autossh - это программа, которая запускает и контролирует соединение SSH и перезапускает его, если соединение прерывается или прекращается передача трафика:

sudo apt-get install autossh

systemd is the default init system on Ubuntu, что означает, что он управляет процессами после загрузки системы. Вы можете использоватьsystemd для создания службы, которая будет управлять вашим SSH-туннелем и автоматически запускать его при перезапуске сервера. Для этого создайте файл с именемdb-tunnel.service в каталоге/lib/systemd/system/, стандартном месте, где хранятся файлы модулейsystemd:

sudo nano /lib/systemd/system/db-tunnel.service

Добавьте в новый файл следующее содержимое, чтобы настроить службу для управленияsystemd:

/lib/systemd/system/db-tunnel.service

[Unit]
Wants=network-online.target
After=network-online.target

[Service]
User=tunnel
WorkingDirectory=/home/tunnel
ExecStart=/bin/bash -lc 'autossh -N -L 5433:localhost:5432 tunnel@database-server'
Restart=always
StandardInput=null
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=%n
KillMode=process

[Install]
WantedBy=multi-user.target

Ключевая строка здесьExecStart. Здесь указывается полный путь к команде и аргументы, которые необходимо выполнить для запуска процесса. Здесь он запускает новую оболочкуbash, а затем запускает программуautossh.

Сохраните и закройте файл, а затем перезагрузите конфигурациюsystemd, чтобы убедиться, что она подхватывает новый служебный файл:

sudo systemctl daemon-reload

Включите службуdb-tunnel, чтобы туннель кdatabase-server запускался автоматически при каждой загрузке сервера:

sudo systemctl enable db-tunnel.service

Затем запустите сервис:

sudo systemctl start db-tunnel.service

Еще раз введите следующую команду, чтобы проверить, работает ли туннель:

ps axu | grep tunnel

В выходных данных вы увидите, что на этот раз запущено больше процессов, потому чтоautossh теперь отслеживает туннель:

Outputtunnel   25925  0.0  0.1   4376   704 ?        Ss   14:45   0:00 /usr/lib/autossh/autossh -N -L 5432:localhost:5432 tunnel@database-server
tunnel   25939  0.2  1.0  44920  5332 ?        S    14:45   0:00 /usr/bin/ssh -L 61371:127.0.0.1:61371 -R 61371:127.0.0.1:61372 -N -L 5432:localhost:5432 tunnel@database-server
sammy    25941  0.0  0.2  12916  1020 pts/0    S+   14:45   0:00 grep --color=auto tunnel

Теперь, когда туннель запущен и работает, вы можете протестировать соединение сdatabase-server с помощьюpsql, чтобы убедиться, что он работает правильно.

Запустите клиентpsql и скажите ему подключиться кlocalhost. Вы также должны указать порт5433 для подключения через туннель SSH к экземпляру PostgreSQL наdatabase-server. Укажите имя базы данных, которое вы создали ранее, и введите пароль, который вы создали для пользователя базы данных, когда будет предложено:

psql -hlocalhost -p5433 sammy

Если вы видите что-то вроде следующего вывода, соединение с базой данных было установлено правильно:

Outputpsql (9.5.10)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

sammy=#

Чтобы закрыть приглашение PostgreSQL, введите\q, а затем нажмитеENTER.

Наконец, у вас есть постоянный и надежный туннель SSH, который шифрует трафик между вашимиapp-server иdatabase-server. Функции безопасности туннеля являются ключевыми, поскольку именно через этот туннель приложение Rails на вашемapp-server будет взаимодействовать с экземпляром PostgreSQL на вашемdatabase-server.

[[step-5 -—- configuring-rails-to-use-a-remote-database]] == Шаг 5 - Настройка Rails для использования удаленной базы данных

Теперь, когда туннель отapp-server кdatabase-server настроен, вы можете использовать его в качестве безопасного канала для вашего приложения Rails для подключения через туннель к экземпляру PostgreSQL наdatabase-server .

Откройте файл конфигурации базы данных приложения:

nano /home/sammy/appname/config/database.yml

Обновите разделproduction, чтобы номер порта был указан как переменная среды. Теперь это должно выглядеть примерно так:

/home/sammy/appname/config/database.yml

. . .
production:
  <<: *default
  host: localhost
  adapter: postgresql
  encoding: utf8
  database: appname_production
  pool: 5
  username: <%= ENV['APPNAME_DATABASE_USER'] %>
  password: <%= ENV['APPNAME_DATABASE_PASSWORD'] %>
  port: <%= ENV['APPNAME_DATABASE_PORT'] %>

Сохраните и закройте этот файл, затем откройте файл.rbenv-vars в каталоге приложения и отредактируйте переменные среды:

nano /home/sammy/appname/.rbenv-vars

Если вы установили другое имя и пароль для роли PostgreSQL вdatabase-server, замените их сейчас (в приведенном ниже примере роль PostgreSQL называетсяsammy). Также добавьте новую строку, чтобы указать порт базы данных. После внесения этих изменений ваш файл.rbenv-vars должен выглядеть так:

/home/sammy/appname/.rbenv-vars

SECRET_KEY_BASE=secret_key_base
APPNAME_DATABASE_USER=sammy
APPNAME_DATABASE_PASSWORD=database_password
APPNAME_DATABASE_PORT=5433

Сохраните и закройте этот файл, когда закончите.

Поскольку теперь вы используете экземпляр PostgreSQL наdatabase-server вместо экземпляра наapp-server, где вы развернули приложение Rails, вам придется снова настроить базу данных.

Наapp-server перейдите в каталог вашего приложения и выполните командуrake, чтобы настроить базу данных:

[.note] #Note: Эта командаnot переносит любые данные из существующей базы данных в новую. Если у вас уже есть важные данные в вашей базе данных, вы должны создать их резервную копию, а затем восстановить ее позже.
#

cd /home/sammy/appname
rake db:setup

После завершения этой команды ваше приложение Rails начнет взаимодействовать с экземпляром PostgreSQL наdatabase-server через зашифрованный туннель SSH. Следующее, что нужно сделать, это настроить Puma как службуsystemd, чтобы упростить управление.

[[step-6 -—- configuring-and-start-puma]] == Шаг 6 - Настройка и запуск Puma

Подобно тому, как вы настраивали службуdb-tunnel на шаге 4, вы настроитеsystemd для запуска Puma (серверное программное обеспечение, которое вы установили наapp-server как часть предварительных условий) в качестве службы. . Запуск Puma как службы позволяет автоматически запускаться при загрузке сервера или автоматически перезагружаться в случае сбоя, что делает развертывание более надежным.

Создайте новый файл с именемpuma.service в каталоге/lib/systemd/system/:

sudo nano /lib/systemd/system/puma.service

Добавьте в новый файл следующий контент, адаптированный изPuma’s systemd documentation. Обязательно обновите выделенные значения в директивахUser,WorkingDirectory иExecStart, чтобы отразить вашу собственную конфигурацию:

/lib/systemd/system/puma.service

[Unit]
Description=Puma HTTP Server
After=network.target

[Service]
# Foreground process (do not use --daemon in ExecStart or config.rb)
Type=simple

# Preferably configure a non-privileged user
User=sammy

# The path to the puma application root
# Also replace the "" place holders below with this path.
WorkingDirectory=/home/sammy/appname

# Helpful for debugging socket activation, etc.
# Environment=PUMA_DEBUG=1

Environment=RAILS_ENV=production

# The command to start Puma.
ExecStart=/home/sammy/.rbenv/bin/rbenv exec bundle exec puma -b tcp://127.0.0.1:9292

Restart=always

[Install]
WantedBy=multi-user.target

Сохраните и закройте файл. Затем перезагрузитеsystemd, включите службу Puma и запустите Puma:

sudo systemctl daemon-reload
sudo systemctl enable puma.service
sudo systemctl start puma.service

После этого убедитесь, что Puma запущена, проверив состояние службы:

sudo systemctl status puma.service

Если он работает, вы увидите вывод, похожий на этот:

Outputpuma.service - Puma HTTP Server
   Loaded: loaded (/lib/systemd/system/puma.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2017-12-26 05:35:50 UTC; 1s ago
 Main PID: 15051 (bundle)
    Tasks: 2
   Memory: 31.4M
      CPU: 1.685s
   CGroup: /system.slice/puma.service
           └─15051 puma 3.11.0 (tcp://127.0.0.1:9292) [appname]

Dec 26 05:35:50 app systemd[1]: Stopped Puma HTTP Server.
Dec 26 05:35:50 app systemd[1]: Started Puma HTTP Server.
Dec 26 05:35:51 app rbenv[15051]: Puma starting in single mode...
Dec 26 05:35:51 app rbenv[15051]: * Version 3.11.0 (ruby 2.4.3-p205), codename: Love Song
Dec 26 05:35:51 app rbenv[15051]: * Min threads: 5, max threads: 5
Dec 26 05:35:51 app rbenv[15051]: * Environment: production

Затем используйтеcurl для доступа и распечатки содержимого веб-страницы, чтобы вы могли проверить, правильно ли оно обслуживается. Следующая команда указываетcurl посетить только что запущенный сервер Puma наapp-server через порт9292:

curl localhost:9292/tasks

Если вы видите что-то вроде приведенного ниже кода, это подтверждает, что и Puma, и соединение с базой данных работают правильно:

Output...

Tasks

Title Note
...

Убедившись, что ваше приложение Rails обслуживается Puma и правильно настроено для использования удаленного экземпляра PostgreSQL наdatabase-server, вы можете переходить к настройке SSH-туннеля междуweb-server и app-server.

[[step-7 -—- setting-up-and-persisting-the-ssh-tunnel-to-the-app-server]] == Шаг 7. Настройка и сохранение SSH-туннеля на сервере приложений

Теперь, когдаapp-server запущен и работает, вы можете подключить его кweb-server. Аналогично процессу, который вы прошли в шаге 4, вы сделаете это, настроив другой SSH-туннель. Этот туннель позволит Nginx наweb-server безопасно подключаться через зашифрованное соединение к Puma наapp-server.

Начните с установкиautossh наweb-server:

sudo apt-get install autossh

Создайте новый файл с именемapp-tunnel.service в каталоге/lib/systemd/system/:

sudo nano /lib/systemd/system/app-tunnel.service

Добавьте следующее содержимое в этот файл. Опять же, ключевая строка - это строка, которая начинается сExecStart. Здесь эта строка перенаправляет порт9292 наweb-server на порт9292 наapp-server, где Puma прослушивает:

/lib/systemd/system/app-tunnel.service

[Unit]
StopWhenUnneeded=true
Wants=network-online.target
After=network-online.target

[Service]
User=tunnel
WorkingDirectory=/home/tunnel
ExecStart=/bin/bash -lc 'autossh -N -L 9292:localhost:9292 tunnel@app-server'
Restart=always
StandardInput=null
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=%n
KillMode=process

[Install]
WantedBy=multi-user.target

[.note] #Note: Номер порта в строкеExecStart такой же, как и номер порта, настроенный для Puma на предыдущем шаге.
#

Перезагрузитеsystemd, чтобы он прочитал новый служебный файл, затем включите и запустите службуapp-tunnel:

sudo systemctl daemon-reload
sudo systemctl enable app-tunnel.service
sudo systemctl start app-tunnel.service

Проверьте, что туннель работает:

ps axu | grep tunnel

Вы должны увидеть что-то похожее на вывод ниже:

Outputtunnel   19469  0.0  0.1   4376   752 ?        Ss   05:45   0:00 /usr/lib/autossh/autossh -N -L 9292:localhost:9292 tunnel@app-server
tunnel   19482  0.5  1.1  44920  5568 ?        S    05:45   0:00 /usr/bin/ssh -L 54907:127.0.0.1:54907 -R 54907:127.0.0.1:54908 -N -L 9292:localhost:9292 tunnel@app-server
sammy    19484  0.0  0.1  12916   932 pts/0    S+   05:45   0:00 grep --color=auto tunnel

Этот отфильтрованный список процессов показывает, чтоautossh запущен и запустил другой процессssh, который создает фактический зашифрованный туннель междуweb-server иapp-server.

Теперь ваш второй туннель включен и шифрование связи между вашимиweb-server иapp-server. Все, что вам нужно сделать, чтобы запустить и запустить ваше трехуровневое приложение Rails, - это настроить Nginx для передачи запросов в Puma.

[[step-8 -—- configuring-nginx]] == Шаг 8 - Настройка Nginx

На этом этапе все необходимые SSH-соединения и туннели были настроены, и каждый из трех ваших уровней сервера может обмениваться данными друг с другом. Последняя часть этой головоломки для вас - настроить Nginx для отправки запросов в Puma, чтобы сделать установку полностью функциональной.

Наweb-server создайте новый файл конфигурации Nginx в/etc/nginx/sites-available/appname:

sudo nano /etc/nginx/sites-available/appname

Добавьте следующее содержимое в файл. Этот файл конфигурации Nginx похож на тот, который вы использовали, если следовали нашему руководству поHow To Deploy a Rails App with Puma and Nginx. Основное отличие заключается в расположении вышестоящего приложения; вместо использования локального файла сокета эта конфигурация указывает Nginx на SSH-туннель, прослушивающий порт9292:

/etc/nginx/sites-available/appname

upstream app {
    server 127.0.0.1:9292;
}

server {
    listen 80;
    server_name localhost;

    root /home/sammy/appname/public;

    try_files $uri/index.html $uri @app;

    location @app {
        proxy_pass http://app;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}

Сохраните и закройте этот файл, затем включите сайт и сделайте изменения активными.

Сначала удалите сайт по умолчанию:

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

Перейдите в каталог Nginxsites-enabled:

cd /etc/nginx/sites-enabled

Создайтеsymbolic link в каталогеsites-enabled для файла, который вы только что создали в каталогеsites-available:

sudo ln -s /etc/nginx/sites-available/appname appname

Проверьте свою конфигурацию Nginx на наличие синтаксических ошибок:

sudo nginx -t

Если сообщается о каких-либо ошибках, вернитесь и проверьте файл, прежде чем продолжить.

Когда вы будете готовы, перезапустите Nginx, чтобы он прочитал вашу новую конфигурацию:

sudo systemctl restart nginx

Если вы выполнили предварительные требования к руководству Puma, вы бы установили Nginx и PostgreSQL наapp-server. Оба были заменены отдельными экземплярами, работающими на двух других серверах, поэтому эти программы являются избыточными. Следовательно, вы должны удалить эти пакеты изapp-server:

sudo apt remove nginx
sudo apt remove postgresql

После удаления этих пакетов обязательно обновите правила брандмауэра, чтобы предотвратить доступ нежелательного трафика к этим портам.

Ваше приложение Rails сейчас в разработке. Посетите общедоступный IP-адрес вашегоweb-server в веб-браузере, чтобы увидеть его в действии:

http://web-server_public_IP/tasks

Заключение

Следуя этому руководству, вы развернули свое приложение Rails на трехуровневой архитектуре и защитили соединения от вашегоweb-server кapp-server и отapp-server кdatabase-server с зашифрованными туннелями SSH.

Различных компонентов вашего приложения на отдельных серверах, вы можете выбрать оптимальные спецификации для каждого сервера в зависимости от объема трафика, который получает ваш сайт. Первым шагом для этого является мониторинг ресурсов, которые использует сервер. См.our guide on CPU monitoring для получения инструкций о том, как контролировать использование ЦП ваших серверов. Если вы видите, что загрузка ЦП или памяти на одном уровне очень высока, вы можете изменить размер сервера только на этом уровне. Дополнительные советы по выбору размера сервера см. В нашем руководстве поChoosing the Right Droplet for Your Application.

В качестве ближайшего следующего шага вам также следует защитить соединение ваших пользователей сweb-server, установив сертификат SSL наweb-server. Ознакомьтесь с инструкциями вNginx Let’s Encrypt tutorial. Кроме того, если вы хотите узнать больше об использовании туннелей SSH, посетитеthis guide.

Related