Установим с вами Redmine на RockyLinux. Инструкция также подойдёт для RHEL, CentOS, AlmaLinux.

Исходные данные:

  • Linux (RockyLinux 10), можно аналогично установить на RHEL, CentOS, AlmaLinux, так как они из одной линейки.
  • Redmine 6.0.7
  • Ruby 3.2.5 + rbenv
  • PostgreSQL
  • Puma (as application server)
  • Nginx (reverse proxy + HTTPS)
  • systemd

Авторизуемся под пользователем с правами администратора, как вы это будете делать вам решать, например root или…

Установка вспомогательного ПО

dnf install epel-release
dnf config-manager --set-enabled crb
dnf makecache
dnf install rubygem-bundler
dnf install ImageMagick ghostscript
dnf install postgresql-server postgresql postgresql-devel

# Это нужно для компиляции Ruby и некоторых C-расширений, далее мы будем компилировать требуемую нам версию Ruby
dnf groupinstall "Development Tools"
dnf install dnf-plugins-core

# Устанавливаем libyaml-devel (важно для Ruby)
dnf install libyaml-devel

Настройка PostgreSQL

Инициализация PostgreSQL:

postgresql-setup --initdb

Добавить в автозапуск и запустить:

systemctl start postgresql
systemctl enable postgresql
systemctl status postgresql

Создаём пользователя и базу данных для redmine в PostgreSQL:

psql -c "CREATE ROLE redmine_user LOGIN SUPERUSER PASSWORD 'redmine_user';"
psql -c "CREATE DATABASE redmine_db WITH ENCODING='UTF8' OWNER=redmine_user;"
exit

Изменяем тип авторизации пользователей на md5 в файле /var/lib/pgsql/data/pg_hba.conf:

Перезапускаем PostgreSQL:

systemctl restart postgresql

Создаём системного пользователя Redmine

useradd -m -s /bin/bash redmine
passwd redmine

Авторизуемся под пользователем redmine и работаем под ним.

Установка Ruby 3.2.5 через rbenv

Устанавливаем rbenv:

cd /home/redmine
git clone https://github.com/rbenv/rbenv.git ~/.rbenv

Добавляем rbenv в PATH и включаем auto-init:

echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init - bash)"' >> ~/.bash_profile
exec $SHELL -l

# Проверяем
rbenv -v

Устанавливаем ruby-build как плагин:

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

Ставим Ruby 3.2.5 и делаем его глобальным:

rbenv install 3.2.5
rbenv global 3.2.5

# Проверяем
ruby -v

Загрузка и подготовка Redmine

Скачиваем Redmin в zip-архиве в домашний каталог пользователя: https://www.redmine.org

Распаковываем:

cd /home/redmine

# Указывайте версию, которую скачали
unzip /home/redmine/redmine-6.0.7.zip -d /home/redmine
rm /home/redmine/redmine.zip

# Каталог с программой переименовываю, как мне удобно, запоминаем, так как дальше в командах будем использовать его
mv /home/redmine/redmine-6.0.7 /home/redmine/redminesoft

Настройка Redmine для подключения к PostgreSQL

Редактируем файл /home/redmine/redminesoft/config/database.yml или создаём, если его нет. Вносим в него строки:

production:
  adapter: postgresql
  database: redmine_db
  host: localhost
  username: redmine_user
  password: redmine_user
  encoding: utf8
  # Не изменяй последнюю строку, количеством управляем в
  # /etc/systemd/system/puma-redmine.service
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

Установка зависимостей Redmine

Редактируем файл /home/redmine/redminesoft/Gemfile.local, добавляем Puma. Если файла нет — создаём. Добавить:

gem 'puma'

Указываем, что dev/test группы не нужны в проде и устанавливаем зависимости Redmine:

bundle config set --local without 'development test'
bundle install

Инициализация Redmine

# Генерация секретного ключа
bundle exec rake generate_secret_token

# Применение миграций базы
RAILS_ENV=production bundle exec rake db:migrate

# Загрузка стандартных данных
RAILS_ENV=production bundle exec rake redmine:load_default_data REDMINE_LANG=ru

# Компиляция ассетов
RAILS_ENV=production bundle exec rake assets:precompile

Настройка Puma

Создаём каталоги и файлы:

cd ~/redminesoft
mkdir -p tmp/pids tmp/sockets log
# Создаём файл для запуска сервиса и сразу его наполняем

cat > /home/redmine/redminesoft/config/puma.rb << 'EOF'
# Кол-во потоков. Не менять здесь, количеством управляем в
# /etc/systemd/system/puma-redmine.service
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count
# Окружение
environment ENV.fetch("RAILS_ENV") { "production" }
# Порт, на котором будет слушать Puma (для Nginx)
port ENV.fetch("PORT") { 3333 }
# PID-файл
pidfile "tmp/pids/puma.pid"
# Логи
stdout_redirect "log/puma.stdout.log", "log/puma.stderr.log", true
# Рабочий каталог
directory "/home/redmine/redminesoft"
# Чтобы можно было нормально останавливать/перезапускать
plugin :tmp_restart
EOF

Обратите внимание на порт он будет фигурировать ещё в двух местах статьи. Если вы его здесь измените, то меняйте и в других местах.

Авторизуемся под пользователем с правами администратора и работаем под ним.

Создаём systemd-юнит для Puma

# Создаём файл для запуска сервиса и сразу его наполняем

cat > /etc/systemd/system/puma-redmine.service << 'EOF'
[Unit]
Description=Puma Redmine App Server
After=network.target

[Service]
Type=simple
User=redmine
Group=redmine
WorkingDirectory=/home/redmine/redminesoft
Environment="RAILS_ENV=production"
Environment="PORT=3333"
Environment="RAILS_MAX_THREADS=5"
Environment="PATH=/home/redmine/.rbenv/bin:/home/redmine/.rbenv/shims:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin"
ExecStart=/bin/bash -lc 'cd /home/redmine/redminesoft && exec bundle exec puma -C config/puma.rb'
Restart=always
RestartSec=5
TimeoutSec=300

[Install]
WantedBy=multi-user.target
EOF

Здесь как раз и управляем потоками в Environment=»RAILS_MAX_THREADS=5″, но только если увидим, что CPU свободен, а запросы много ждут БД/IO, то повышаем до 8. Не трогаем, если система работает без проблем.

Применяем:

systemctl daemon-reload
systemctl enable --now puma-redmine
systemctl status puma-redmine

SELinux — разрешаем Nginx подключаться к Puma

SELinux в RockyLinux по умолчанию в режиме Enforcing. Если не настроить, то при подключении к redmine будет ошибка «502 Bad Gateway.

setsebool -P httpd_can_network_connect 1

Устанавливаем и настраиваем Nginx

dnf install -y nginx
systemctl enable --now nginx

Открываем порты HTTP/HTTPS в firewall:

firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --zone=public --add-port=443/tcp --permanent
firewall-cmd --reload

Указал порты, а не протоколы, чтобы удобнее было тем у кого порты нестандартные.

Настройка Nginx + HTTPS

# Создаём файл конфигурации для Nginx и сразу его наполняем

cat > /etc/nginx/conf.d/redmine.conf << 'EOF'
upstream redmine_puma {
    server 127.0.0.1:3333 fail_timeout=0;
}
# HTTP: только редирект на HTTPS
server {
    listen 80;
    server_name redmine.victorz.ru;
    return 301 https://redmine.victorz.ru:443;
}
# HTTPS: основной сервер
server {
    listen 443 ssl;
    http2 on;
    server_name redmine.victorz.ru;
    root /home/redmine/redminesoft/public;
    access_log /var/log/nginx/redmine_ssl_access.log;
    error_log  /var/log/nginx/redmine_ssl_error.log;
    ssl_certificate     /etc/pki/tls/certs/sertifikat.crt;
    ssl_certificate_key /etc/pki/tls/certs/sertifikat.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    location / {
        proxy_pass http://redmine_puma;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_read_timeout 300;
        proxy_connect_timeout 300;
        proxy_redirect off;
    }
    location ~ ^/(assets|favicon.ico) {
        expires max;
        add_header Cache-Control public;
        try_files $uri @app;
    }
    location @app {
        proxy_pass http://redmine_puma;
    }
}
EOF

Жирным шрифтом выделил места, на которые вам обязательно надо обратить внимание. Здесь прописаны сертификаты, которые выпущены отдельно, если используете Let’s Encrypt, то возможно вам придётся изменять файл коннфигурации.

Сертификат и ключ

Поместите сертификт и ключ по указанному в конфигурационном файле Nginx пути.

Проверяем и перегружаем Nginx

nginx -t
systemctl reload nginx

Настроить адаптер очереди

Адаптер очереди — это механизм, который отвечает за выполнение фоновых задач.

Если у вас в Redmine в разделе Администрирование — Информация напротив сообщения «Изменен адаптер очереди по умолчанию, который хорошо подходит только для разработки/тестирования» имеется красный восклицательный знак, то вам необходимо донастроить систему. В Redmine 6 по умолчанию использует AsyncAdapter, который работает прямо внутри Puma — это подходит ТОЛЬКО для разработки. В продуктиве нужно использовать Delated Job или другие адаптеры. Delated Job, так как он проще в настройке.

Авторизуемся под пользователем redmine и работаем под ним.

Подключаем gem delayed_job_active_record

cd /home/redmine/redminesoft
echo "gem 'delayed_job_active_record'" >> Gemfile.local
echo "gem 'daemons'" >> Gemfile.local
bundle install

# Проверяем, что гемы есть
bundle list | grep delayed

# Ожидается, что увидиv хотя бы
delayed_job
delayed_job_active_record

Генерация миграции и bin/delayed_job

RAILS_ENV=production bundle exec rails generate delayed_job:active_record

# Ожидается вывод примерно такого вида
create  bin/delayed_job
chmod   bin/delayed_job
create  db/migrate/XXXXXXXXXXXXXX_create_delayed_jobs.rb

# Проверяем, что файлы реально появились
ls -l bin/delayed_job
ls -1 db/migrate | grep delayed

Применяем миграцию

bundle exec rake db:migrate RAILS_ENV=production

# Для контроля — проверяем, что таблица существует
bundle exec rails runner "p ActiveRecord::Base.connection.table_exists?(:delayed_jobs)" -e production

# Ожидаем увидеть
true

Включаем Delayed Job как ActiveJob-адаптер в Redmine

Redmine уже умеет подхватывать дополнительную конфигурацию через additional_environment.rb — его и используем.

# Создаём файл (при необходимости)
[ -f config/additional_environment.rb ] || cp config/additional_environment.rb.example config/additional_environment.rb

# Правим файл любым редактором и вставляем строку
config.active_job.queue_adapter = :delayed_job

Авторизуемся под пользователем с правами администратора и работаем под ним.

Создаём systemd-юнит для Delayed Job

# Создаём файл для запуска сервиса и сразу его наполняем

cat > /etc/systemd/system/redmine-delayed-job.service << 'EOF'
[Unit]
Description=Delayed Job worker for Redmine
After=network.target

[Service]
User=redmine
Group=redmine
WorkingDirectory=/home/redmine/redminesoft

Environment="RAILS_ENV=production"
Environment="PATH=/home/redmine/.rbenv/bin:/home/redmine/.rbenv/shims:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin"

ExecStart=/bin/bash -lc 'cd /home/redmine/redminesoft && exec bundle exec bin/delayed_job run'

Restart=always
RestartSec=5
TimeoutSec=300

[Install]
WantedBy=multi-user.target
EOF

Настраиваем логирование Delayed Job

# Создаём служебный файл

cat > config/initializers/delayed_job_logger.rb << 'EOF'
# Лог для Delayed Job
Delayed::Worker.logger = Logger.new(Rails.root.join('log', 'delayed_job.log'))
EOF

Включаем и запускаем сервис

systemctl daemon-reload
systemctl enable --now redmine-delayed-job
systemctl status redmine-delayed-job

Перезапускаем Puma и Nginx

systemctl restart puma-redmine
systemctl restart nginx

Идём в в раздел Администрирование — Информация и напротив сообщения «Изменен адаптер очереди по умолчанию, который хорошо подходит только для разработки/тестирования» видим галочку сообщающую, что всё корректно настроено.

Добавление плагинов и тем

Если добавили плагин или тему, то нужно выполнить ряд команд.

Плагины

cd /home/redmine/redminesoft
bundle exec rake redmine:plugins RAILS_ENV=production
bundle exec rake assets:precompile RAILS_ENV=production
sudo systemctl restart puma-redmine

Темы

cd /home/redmine/redminesoft
bundle exec rake assets:precompile RAILS_ENV=production
sudo systemctl restart puma-redmine

Без этого они не будут работать корректно.

Финиш

На этом всё. Обновление описано в статье Обновление Redmine на Linux.