Beget VPS: Ubuntu 24.04 + Rails 8
Статья представляет собой пошаговое руководство к развёртыванию Rails платформы на предоставленном хостинге Beget на операционной системе Ubuntu. Использованы актуальные компоненты по состоянию на март 2025 года.
Параметры арендуемого виртуального сервера:
- 1 ядро процессора
- 2 Гб оперативной памяти. На 1 Гб нормально работал Ubuntu 20.04 + Rails 7, в новой связке, из-за нехватки памяти Ubuntu 24.04 стал убивать процесс make при установке Ruby, пришлось добавить. Считайте 2 Гб памяти минимальным требованием
- 10 Гб NVMe
- 1 внешний IP адрес, 250 Мб/сек. канал
- Установка пароля и смена имени сервера
- Дистанционное обслуживание БД
Ubuntu 24.04
Параметры установки Ubuntu 24.04 контролируются провайдером, пользователь получит готовую систему с доступом по SSH. Стоит оговорить некоторые моменты.
Настройка SSH
Сразу надо настроить SSH-аутентификацию по сертификату вместо пароля, так будет безопаснее и проще подключаться. Клиент, с которого будем подключаться к нашему серверу также на Ubuntu 24.04. Сделаем на клиенте необходимые ключи шифрования:
# Проверяем наличие папки .ssh, если её нет, то создаём $ mkdir ~/.ssh # Генерим пару: закрытый и публичный ключи $ ssh-keygen -q -t ed25519 -N '' -f $HOME/.ssh/remote_access # Проверяем что в папке .ssh появились 2 файла: # "remote_access" # "remote_access.pub" $ ls ~/.ssh # Выводим содержимое публичного ключа на консоль для копирования $ cat .ssh/remote_access.pub
На страничке установки/переустановки операционной системы у Beget есть кнопка "Добавить новый SSH-ключ". Нажимаем её и вставляем содержимое публичного ключа из консоли. Далее у нас появляется блок dev@rails, активируем его как способ аутентификации. При развёртывании Ubuntu хостинг пропишет наш ключик в файле /root/.ssh/authorized_keys.
После установки Ubuntu хостинг также пришлёт на почту пароль root. Если мы будем пользоваться консолью Beget или Putty то он понадобится. А так, со своей машины Ubuntu соединяемся с хостом через SSH командой:
$ ssh -i ~/.ssh/remote_access root@<IP_VPS>
Параметр -i задаёт явное имя закрытого ключа, без него ssh будет искать файл "id_rsa".
Сконфигурировал SSH следующим образом:
$ nano /etc/ssh/sshd_config # /etc/ssh/sshd_config PasswordAuthentication no PermitRootLogin prohibit-password PubkeyAuthentication yes AuthorizedKeysFile %h/.ssh/authorized_keys $ systemctl restart ssh
Значение prohibit-password позволяет подключаться под root, но только по ключу.
Установка пароля и смена имени сервера
# Смена пароля root (желательно) $ passwd
# Смена имени сервера $ hostnamectl set-hostname <MY_NAME_HOST> $ nano /etc/hosts # Добавить строчку 127.0.1.1 <MY_NAME_HOST> <MY_NAME_HOST>
Добавление пользователя
Эксплуатация root в постоянном режиме не приветствуется, так что создадим отдельного пользователя, под которым будет работать наш сервер. Назовём его picker:
# Добавление нового пользователя $ adduser picker # Добавление в группу привилегированных пользователей $ adduser picker sudo # В домашней директории пользователя создаём папку для хранения ключей $ mkdir -p /home/picker/.ssh $ chown picker:picker /home/picker/.ssh # Копируем у root файлик authorized_keys, чтобы соединяться по SSH $ cp -i /root/.ssh/authorized_keys /home/picker/.ssh/authorized_keys # Завершаем сессию root и входим под пользователем picker $ exit $ ssh -i ~/.ssh/remote_access picker@<IP_VPS>
Все последующие действия выполняем под пользователем picker, учётной записью root больше не пользуемся.
UFW
Поработаем ещё на защитой сервера и задействуем простой межсетевой экран UFW. По умолчанию он неактивен, а если мы его включим, то стандартные настройки запретят все входящие соединения и разрешат все исходящие. Поэтому перед включением добавим несколько протоколов: SSH или 22 порт (обязательно, мы через него подключаемся к машине), HTTP или 80 порт, через который работает web-приложение, HTTPS или 443 порт, защищённый протокол web-приложения. Далее все команды с комментариями:
# Проверяем, установлен ли вообще UFW $ ufw --version ufw 0.36.2 Copyright 2008-2023 Canonical Ltd. # В каком состоянии находится UFW $ sudo ufw status Status: inactive # Добавляем нужные нам правила $ sudo ufw allow ssh $ sudo ufw allow http $ sudo ufw allow https # Включаем UFW (после перезагрузки также будет работать) $ sudo ufw enable # В каком состоянии находится UFW + действующие правила $ sudo ufw status verbose Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip To Action From -- ------ ---- 22/tcp ALLOW IN Anywhere 80/tcp ALLOW IN Anywhere 443/tcp ALLOW IN Anywhere 22/tcp (v6) ALLOW IN Anywhere (v6) 80/tcp (v6) ALLOW IN Anywhere (v6) 443/tcp (v6) ALLOW IN Anywhere (v6)
PostgreSQL
После того как Beget развернул нам операционку мы ещё не разу её не обновляли, поэтому после sudo apt update Ubuntu скорее всего скажет, что доступно много пакетов обновления, возможно даже связанных с безопасностью. Поставим их все и для верности выполним перезагрузку:
$ sudo apt update $ sudo apt upgrade $ sudo reboot
В качестве базы данных будем использовать PostgreSQL. Ставим последнюю доступную версию и пакет разработчика следующей командой:
$ sudo apt install postgresql libpq-dev
Убеждаемся, что служба postgresql запущена.
$ sudo systemctl status postgresql
Выполним ещё некоторые предварительные настройки базы данных. Входим в сессию служебного пользователя postgres:
$ sudo su - postgres
Входим в командную строку PostgreSQL:
$ psql
Устанавливаем пароль служебного пользователя postgres (можно писать USER вместо ROLE, но USER считается устаревшей конструкцией):
postgres=# ALTER ROLE postgres WITH PASSWORD '<пароль>';
Добавим ещё одного пользователя СУБД - trader, под которым будет работать приложение, и укажем его пароль:
postgres=# CREATE ROLE trader WITH LOGIN PASSWORD '<пароль>';
Разрешим пользователю создавать базы:
postgres=# ALTER ROLE trader WITH CREATEDB;
Выходим из командной строки PostgreSQL:
postgres=# exit
Выходим из сессии служебного пользователя postgres.
$ exit
Дистанционное обслуживание БД
Если нужно удалённое подключение к базе данных, то следует добавить правило межсетевого экрана, для той машины с которой будет выполняться подключение (вместо 192.168.123.123 нужно подставить свой IP адрес):
$ sudo ufw allow proto tcp from 192.168.123.123 to any port 5432
Или создать более простое правило, разрешающее подключение с любых адресов:
$ sudo ufw allow 5432/tcp
Далее требуется изменить основной файл конфигурации:
# Определяем путь к файлу конфигурации
$ sudo su - postgres -c "psql -c 'SHOW config_file;'"
config_file
---------------------------------------
/etc/postgresql/16/main/postgresql.conf
(1 row)
$ sudo nano /etc/postgresql/16/main/postgresql.conf
# /etc/postgresql/16/main/postgresql.conf
listen_addresses = '*'Чтобы изменения вступили в силу, перезапускаем службу postgresql:
$ sudo systemctl restart postgresql
Проверим что настройка применилась:
$ ss -tunlp | grep 5432 tcp LISTEN 0 200 0.0.0.0:5432 0.0.0.0:* tcp LISTEN 0 200 [::]:5432 [::]:*
Далее требуется изменить файл конфигурации pg_hba.conf.
# Определяем путь к файлу hba_file
$ sudo su - postgres -c "psql -c 'SHOW hba_file;'"
hba_file
-------------------------------------
/etc/postgresql/16/main/pg_hba.conf
(1 row)
$ sudo nano /etc/postgresql/16/main/pg_hba.conf
# /etc/postgresql/16/main/pg_hba.conf добавить строку:
# IPv4 local connections:
host all all 192.168.123.123/32 scram-sha-256Если хотим разрешить подключения с любых адресов, то вместо 192.168.123.123/32 надо написать 0.0.0.0/0. Далее ещё раз перезапустим службу postgresql:
$ sudo systemctl restart postgresql
Резервное копирование БД
Раздел привожу справочно, сюда лучше заглянуть когда будет создана база данных приложения, иначе команды не заработают - резервировать нечего.
Для приложения предполагается:
- пользователь от имени которого работает сервер - picker;
- пользователь от имени которого работаем с PostgreSQL - trader;
- база данных приложения - market;
Для целей резервного копирования добавим пару папок backup и scripts в домашнюю директорию:
$ mkdir backup $ mkdir scripts
Если сходу попробовать сделать копию БД командой pg_dump, то будет примерно такая ошибка:
pg_dump: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "trader"
Ошибка происходит из-за попытки системы выполнить команду в контексте текущего пользователя - picker, даже несмотря на явное указание пользователя в команде. А для корректного сопоставления имён необходимо добавить следующие строчки в пару файлов:
$ sudo nano /etc/postgresql/16/main/pg_ident.conf # MAPNAME SYSTEM-USERNAME PG-USERNAME picker picker trader
Вместо picker напишите своё имя, которое вернёт команда whoami.
$ sudo nano /etc/postgresql/16/main/pg_hba.conf # TYPE DATABASE USER ADDRESS METHOD local all postgres peer local all trader peer map=picker
$ sudo systemctl restart postgresql
После этого команда pg_dump отрабатывает корректно:
$ pg_dump -U trader market | gzip > backup/pgsql_$(date "+%Y-%m-%d").sql.gz
Для автоматизации резервного копирования написал скрипт, со следующим содержимым:
$ nano scripts/backup.sh #!/bin/sh PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin PGPASSWORD=<your password> export PGPASSWORD pathB=backup dbUser=trader database=market find $pathB -type f -ctime +10 -delete pg_dump -c -U $dbUser $database | gzip > $pathB/pgsql_$(date "+%Y-%m-%d_%H-%M").sql.gz unset PGPASSWORD
Первая команда в скрипте удалит из папки backup файлы старше 10 дней, вторая сделает сжатую резервную копию.
Скрипт делаем исполняемым и пробуем запускать, проверяя на отсутствие ошибок и появление сжатых дампов баз данных в папке backup:
$ chmod +x scripts/backup.sh $ ./scripts/backup.sh
Настроим запуск скрипта каждые 4 часа:
$ crontab -e 0 */4 * * * /home/picker/scripts/backup.sh # pg_dump "market"
Полноценное резервное копирование лучше делать на другой носитель, здесь дампы больше нужны для целей разработки, чтобы оперативно получить БД из производственной среды.
В среде разработки конфиги никакие не правил, так что восстановление распакованной базы данных выполняется такой командой:
$ sudo -u postgres psql -d market < pgsql_2025-06-16_12-50.sql
Mise & Ruby
https://gorails.com/setup/ubuntu/24.04
Теперь собственно к средствам программирования. Информация преимущественно взята с хорошей странички gorails, там можно найти инструкции для установки Rails под разные операционные системы. Устанавливаем необходимые пакеты для компиляции Ruby:
$ sudo apt-get update $ sudo apt install build-essential rustc libssl-dev libyaml-dev zlib1g-dev libgmp-dev
Раньше различными версиями Ruby управляли с помощью менеджера пакетов RVM (Ruby Version Manager). Более современное решение - Mise (наследие Rbenv), который управляет не только пакетами Ruby, но и например Golang, Node.js, Yarn, Rust и многими другими.
Следующими командами мы установим Mise:
$ curl https://mise.run | sh $ echo 'eval "$(~/.local/bin/mise activate)"' >> ~/.bashrc $ source ~/.bashrc # Mise может проверить себя $ mise doctor
Установка актуального Ruby из 3-ей ветки с помощью Mise (ставился в моём случае 15 мин, а на 1 Гб эта команда и вовсе не могла завершиться):
$ mise use --global ruby@3
$ ruby --version ruby 3.4.3 (2025-04-14 revision d0b7e5b6a0) +PRISM [x86_64-linux]
Вместе с Ruby также установится его менеджер пакетов Rubygems, обновим его версию до последней:
$ gem update --system
Для полноценной работы с Rails нам может понадобится Node.js и Yarn. Поставим их последние версии следующими командами:
$ mise use --global node $ mise use --global yarn
Git
$ git -v git version 2.43.0
Увязываем локальный git с учётной записью на Github:
$ git config --global color.ui true $ git config --global user.name "YOUR NAME" $ git config --global user.email "YOUR@EMAIL.com" # Генерим пару: закрытый и публичный ключи # На этот раз для SSH соединения с сайтом github.com $ ssh-keygen -t ed25519 -C "YOUR@EMAIL.com" -f $HOME/.ssh/github # Выводим содержимое публичного ключа на консоль для копирования $ cat .ssh/github.pub
Содержимое файла github.pub вставляем на своей страничке: https://github.com/settings/ssh
Успешное подключение можно проверить командой:
$ ssh -i ~/.ssh/github -T git@github.com
Rails 8.0.2
Версия 8.0.2 - это то что было актуально на момент написания статьи, со временем будут появляться новые версии. Установка:
$ gem install rails -v 8.0.2
Проверяем наличие rails в системе.
$ rails -v Rails 8.0.2
Не будем пока разворачивать тестовое приложение, как это делается во многих учебниках, а подготовим front-end.
Nginx
Установка Nginx
$ sudo apt update $ sudo apt install nginx
Добавим программу в автозагрузку, проверим присутствие в автозагрузке (должны увидеть enabled) и проверим текущий статус:
$ sudo systemctl enable nginx $ sudo systemctl is-enabled nginx $ sudo systemctl status nginx
Раз nginx запущен, то в браузере должны увидеть подтверждение корректной работы с любой интернет машины:
Настройка HTTPS
https://certbot.eff.org/instructions?ws=nginx&os=snap
Сервер настроим на работу по протоколу HTTPS, для чего понадобится выпустить бесплатный сертификат Let's Encrypt (некоммерческий центр сертификации). Все инструкции по настройке можно взять на официальном сайте (см. выше), потребуется указать какой веб-сервер используется и какой используется менеджер пакетов. В итоге настройка получилась из таких шагов:
$ sudo apt-get install snapd $ sudo snap install core $ sudo snap refresh core $ sudo snap install --classic certbot $ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Выпуск сертификата выполнялся с помощью плагина nginx. В процессе потребуется ввести зарегистрированное доменное имя сервера:
$ sudo certbot --nginx
Сразу после этого сайт стал открываться по https:// с тем же содержимым, а с http:// срабатывает переадресация на защищённое соединение.
Сертификат выпускается на 90 дней. Задание на обновление обнаружилось по команде systemctl list-timers. Насколько оно успешно будет отрабатывать можно проверить следующей командой:
$ sudo certbot renew --dry-run
Конфигурация Nginx
Настроим конфигурацию единственного приложения Nginx:
$ sudo mv /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
$ sudo nano /etc/nginx/sites-available/default
# /etc/nginx/sites-available/default
upstream app {
# Path to Puma TCP
server 127.0.0.1:3000;
}
server {
# managed by Certbot
listen 443 ssl;
listen [::]:443 ssl ipv6only=on;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
ssl_certificate /etc/letsencrypt/live/<VPS_DOMAIN_NAME>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<VPS_DOMAIN_NAME>/privkey.pem;
server_name <VPS_DOMAIN_NAME>;
root home/picker/market/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_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-Port $server_port;
proxy_redirect off;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
server {
listen 80 ;
listen [::]:80;
server_name <VPS_DOMAIN_NAME>;
return 302 https://$server_name$request_uri;
}
Все вставки <VPS_DOMAIN_NAME> надо поменять на свои данные, фрагменты Certbot-а нужно оставить, переделал только записи, добавленные для 80 порта. Далее последовательно тестируем конфигурацию Nginx на отсутствие ошибок sudo nginx -t и перезапускаем Nginx sudo systemctl restart nginx.
Теперь Nginx ожидает back-end потока по адресу http://127.0.0.1:3000, пришло время создать приложение Rails.
Генерация приложения Rails
Создаём новое приложение Rails:
$ rails new market -d postgresql -T --skip-solid
Настраиваем подключение к СУБД, правим файл config/database.yml:
$ cd market && nano config/database.yml
# config/database.yml:
default: &default
host: localhost
port: 5432
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
production:
<<: *default
database: market
username: <%= Rails.application.credentials[:database][:username] %>
password: <%= Rails.application.credentials[:database][:password] %>Переменные database_username и database_password добавим в файл с чувствительными данными:
EDITOR=nano rails credentials:edit # config/credentials.yml.enc database: username: trader password: ...
Попробуем создать базу данных и убедиться, что нигде не ошиблись:
$ rake db:create Created database 'market'
Чтобы не срабатывал Host Authorization нужно вручную указать допустимые DNS имена сервера:
$ nano config/environments/production.rb # Add lines to: config/environments/production.rb: Rails.application.configure do ... # Whitelist one hostname config.hosts << "<VPS_DOMAIN_NAME>"
Находясь в папке приложения запускаем сервер:
$ RAILS_ENV=production bundle exec rake assets:precompile $ rails s -e production
После этого, зайдя на наш сайт по защищённому протоколу должны увидеть такую страничку:
Может показаться что сайт не работает. На самом деле дизайн странички указывает на то что её отдал Rails и эта страничка лежит по адресу /home/picker/market/public/404.html. Такое поведение приложение связано с тем что в приложении не определена стартовая страница, да её и нет по сути.
Можно остановить сервер Rails [Ctrl+C] и сгенерировать пустой контроллер с представлением:
$ rails g controller start index
После повторного запуска страница https://<VPS_IP>/start/index будет отдавать созданное по умолчанию представление:
Настройка Puma
Наверно стоит немного объясниться на счёт Puma.
Обычно при настройке Nginx штатный веб-сервер Puma заменяется на Passenger, но в последних релизах Passenger получил приставку Enterprise и стал требовать лицензии. Не имея серьёзных амбиций по быстродействию можно продолжать использовать Puma.
https://puma.io/puma/file.systemd.html
Для среды production Puma желательно запускать в виде службы. Сделаем такую службу согласно официальной рекомендации. Для этого внутри папки /etc/systemd/system/ нужно создать новый файл puma.service, со следующим содержимым (ExecStart два варианта, оба рабочие):
$ sudo nano /etc/systemd/system/puma.service # puma.service [Unit] Description=Puma HTTP Server After=network.target [Service] Type=notify WatchdogSec=10 User=picker WorkingDirectory=/home/picker/market/ ExecStart=/home/picker/.local/share/mise/shims/puma -e production -C /home/picker/market/config/puma.rb # ExecStart=/home/picker/.local/share/mise/shims/bundle exec puma -e production -C ./config/puma.rb config.ru -b tcp://127.0.0.1:3000 Restart=always [Install] WantedBy=multi-user.target
# Применить изменения в файлах служб systemd $ sudo systemctl daemon-reload # Добавить службу в автозагрузку $ systemctl enable puma.service # Проверим присутствие в автозагрузке $ sudo systemctl is-enabled puma # Стартуем службу $ sudo systemctl start puma # Проверяем статус работы службы $ sudo systemctl status puma
Если служба успешно стартовала, то наше приложение должно работать. И также должно работать после перезагрузки сервера.
Вот основное, чтобы мог бы выделить по подготовке платформы Rails на Ubuntu. Остаётся разрабатывать хорошие приложения и заливать их на подготовленный сервер.