UMGUM.COM 

Redmine ( Установка и настройка написанного "Redmine", в попытке воспользоваться им для ведения процессов управления производственными задачами. )

10 апреля 2020  (обновлено 7 июля 2020)

OS: "Linux Debian 9/10", "Linux Ubuntu Server 16/18 LTS".
Apps: "Redmine", "Ruby On Rails", "MySQL", "Unicorn", "Nginx", LDAP.

Задача: установка и настройка написанного на "Ruby" web-приложения "Redmine", в попытке воспользоваться им для ведения "тикетов" процесса управления производственными задачами.


Последовательность дальнейших действий такова:

1. Подготовка системного окружения (отдельная инструкция);
2. Установка интерпретатора языка программирования "Ruby";
3. Установка и настройка СУБД "MySQL";
4. Загрузка и развёртывание web-приложения "Redmine";
5. Предварительная настройка и пробный запуск "Redmine";
6. Установка и настройка сервера приложений "Unicorn";
7. Установка фронтального web-сервера "Nginx";
8. Настройка подключения к внешнему LDAP для аутентификации.


Установка интерпретатора языка программирования "Ruby".

"Redmine" написан на языке программирования"Ruby", для исполнения в среде фреймворка "Ruby On Rails (RoR)". В среде ruby-программистов модно держать на одном компьютере несколько версий интерпретатора - ни одна широко-распространённая "в интернетах" инструкция не обходится без установки менеджера и переключателя контекста вроде "rbenv" или RVM. Однако, в случае развёртывания одиночного сервиса всего этого лишнего мусора в файловой системе и голове не нужно, и достаточно лишь установить "Ruby v2.5", имеющийся в дистрибутиве "Linux Ubuntu":

# aptitude install ruby2.5 ruby-full rubygems-integration

Установка и настройка СУБД "MySQL".

Команда "Redmine" заявляет о полноценной поддержке хранения данных в таких СУБД, как "MySQL", "PostgreSQL" и "Microsoft SQL Server", и даже ограниченную для "SQLite". Однако на практике разработчики расширений умудряются привязать свои программные продукты к определённым СУБД, и чаще всего это бывает "MySQL". Смехотворно, но, перед выбором СУБД вначале придётся определиться, каким набором расширений предстоит пользоваться.

В нашем случае пакет приобретаемых в попытке достижения минимально необходимого функционала работал только с СУБД "MySQL" - её и устанавливаем:

# apt-get install --no-install-recommends mysql-server

Заранее создаём директорию для временных файлов и последующего монтирования таковой в ОЗУ:

# mkdir -p /var/lib/mysql/tmp
# chown -R mysql:mysql /var/lib/mysql/tmp
# chmod -R go-rwx /var/lib/mysql/tmp

Вписываем нашу директорию в таблицу автоматического (при запуске операционной системы) монтирования файловых систем:

# vi /etc/fstab

....
# Tuning the location of MySQL temporary files
tmpfs /var/lib/mysql/tmp tmpfs rw,nosuid,nodev,size=2G,uid=mysql,gid=mysql,mode=0750 0 0
....

Монтируем или перемонтируем директорию временных файлов "MySQL":

# mount /var/lib/mysql/tmp || mount -o remount /var/lib/mysql/tmp

"Redmine" ничего экстраординарного от СУБД не требует - мы лишь внесём немного опций оптимизации "InnoDB" и укажем желательную кодировку данных:

# vi /etc/mysql/mysql.conf.d/mysqld.conf

....
[mysqld]
....
# Указываем оптимальную для "Redmine" кодировку
collation_server = utf8mb4_unicode_ci
character_set_server = utf8mb4
....
# Выносим временные файлы в удобное нам место
tmpdir = /var/lib/mysql/tmp
innodb_tmpdir = /var/lib/mysql/tmp
....
# Разрешаем только локальные подключения
bind-address = 127.0.0.1
....
# Увеличиваем лимит размера временной таблицы, обрабатываемой в ОЗУ, до сброса её в файловую систему
tmp_table_size = 512M
....
# Увеличиваем лимит размера создаваемых пользователем MEMORY-таблицы, обрабатываемой в ОЗУ
max_heap_table_size = 512M
....
# Следуя рекомендациям разработчиков "Redmine" корректируем параметры кеширования
bulk_insert_buffer_size = 64M
query_cache_limit = 128K
query_cache_size = 512M
....
# Увеличиваем размер буфера запросов и журнала транзакций
innodb_buffer_pool_size = 2G // ~40% RAM
innodb_log_file_size = 256M
....
# Указываем записывать журнал транзакций примерно один раз в секунду, а не немедленно после каждого изменения данных (default: 1)
innodb_flush_log_at_trx_commit = 2
....
# Чуть увеличиваем число конкурентных потоков
innodb_read_io_threads = 16
innodb_write_io_threads = 16
....
# Включаем поддержку нового формата файлов InnoDB и длинных индексных ключей
innodb_file_format = barracuda
innodb_large_prefix = 1
....
# Явно указываем создавать для каждой таблицы отдельные файлы описаний (.frm) и данных (.ibd) на диске, а не сваливать всё в один (ibdataX)
innodb_file_per_table = 1
....

Проверяем синтаксическую корректность конфигурации и применяем её перезагрузкой сервиса:

# /etc/init.d/mysql restart
# journalctl -xe

Создаём пользователя и регистрируем "базу данных" для "Redmine".

Всё просто, отдаём команды создания БД, пользователя и наделения последнего неограниченными полномочиями доступа к выделенной "баз данных", в соответствии с рекомендациями разработчиков:

# mysql
mysql> CREATE DATABASE redmine CHARACTER SET utf8mb4;
mysql> CREATE USER 'redmine'@'localhost' IDENTIFIED BY 'redmine_db_password';
mysql> GRANT ALL PRIVILEGES ON redmine.* TO 'redmine'@'localhost';
MySQL> FLUSH PRIVILEGES;
MySQL> QUIT;

Загрузка и развёртывание web-приложения "Redmine".

В APT-репозиториях "Linux Debian/Ubuntu" дистрибутивы "Redmine" имеются, но слишком устаревшие для использования их в сочетании с современными "плагинами". Например, в "Linux Ubuntu 18 LTS" доступен "Redmine 3.4.4", а на сайте стабильный релиз уже "4.1.1", при том, что ряд необходимых нам расширений требует себе минимальной версии "4.0".

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

Устанавливаем SVN-клиента:

# apt-get install subversion

Создаём корневую директорию web-сервиса "Redmine" и загружаем туда исходные коды проекта:

# mkdir -p /var/opt/redmine
# cd /var/opt/redmine
# svn co https://svn.redmine.org/redmine/branches/4.0-stable ./

Язык программирования "Ruby" - высокоуровневый. В коде приложения изложена логика работы, а все взаимодействия с ресурсами осуществляются через соответствующие библиотеки функций, объединённые в специальные пакеты, забавно названные "gems" (от английского "gem" - драгоценный камень).

"Redmine" использует специальный gems-пакет "Bundler" для управления зависимостями gems-пакетов, требуемых для "плагинов" - устанавливаем его:

# cd /var/opt/redmine
# gem install bundler

Устанавливаем поддержку парсинга HTML/XML в "Ruby":

# apt-get install build-essential patch ruby-dev zlib1g-dev liblzma-dev
# gem install nokogiri --no-ri --no-rdoc

Устанавливаем поддержку обработки изображений:

# apt-get install imagemagick libmagick++-dev
# gem install rmagick --no-ri --no-rdoc

Устанавливаем поддержку выбранной БД "MySQL":

# apt-get install libmysqlclient-dev
# gem install mysql2 --no-ri --no-rdoc

Финальным аккордом развёртывания приложения запускаем процедуру удовлетворения зависимостей, требующихся "Redmine" и его компонентам:

# cd /var/opt/redmine
# bundle config set without 'development test'
# bundle install

Fetching gem metadata from https://rubygems.org/...
Resolving dependencies....
Using rake 13.0.1
....
Using mysql2 0.5.3
....
Bundle complete! 31 Gemfile dependencies, 59 gems now installed.

Предварительная настройка и пробный запуск "Redmine".

Одно из первых действий при настройке - указание параметров подключения к "базе данных":

# cd /var/opt/redmine
# cp ./config/database.yml.example ./config/database.yml
# vi ./config/database.yml

# MySQL configuration
production:
  adapter: mysql2
  database: redmine
  host: localhost
  port: 3306
  username: redmine
  password: "redmine_db_password"
  encoding: utf8

В соответствии с рекомендациями разработчиков "Redmine" генерируем секретный ключ хранилища сеансов (Session store secret generation):

# bundle exec rake generate_secret_token

Запускаем процедуру создания необходимых структур (или модификации имеющихся при обновлении) в "базе данных":

# RAILS_ENV=production bundle exec rake db:migrate

Если инсталляция тестовая, то заполняем БД данными из дистрибутивной заготовки, для демонстрационных целей:

# RAILS_ENV=production REDMINE_LANG=en bundle exec rake redmine:load_default_data

Осуществляем пробный запуск сервиса с использованием включённого в дистрибутивную поставку "Redmine" web-сервера "WEBrick":

# cd /var/opt/redmine
# ruby ./bin/rails server -b 0.0.0.0 -e production

=> Booting WEBrick
=> Rails 5.2.4.2 application starting in production on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
... INFO  WEBrick 1.4.2
... INFO  ruby 2.5.1 (2018-03-29) [x86_64-linux-gnu]
... INFO  WEBrick::HTTPServer#start: pid=1950 port=3000

Обращаемся к web-сервису "Redmine" через любой web-браузер и входим в систему с логином и паролем "по умолчанию":

Default administrator account to log in:
  login: admin
  password: admin

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

# cd /var/opt/redmine
# cp ./config/configuration.yml.example ./config/configuration.yml

Установка и настройка сервера приложений "Unicorn".

Технически "Redmine" может быть запущен как ruby-приложение, непосредственно принимающее http-запросы пользователей через простой комплектный web-сервер "WEBrick". Однако наилучшим с точки зрения производительности в условиях большого количества конкурентных запросов и надёжности при высоких нагрузках является способ запуска в специализированных серверах приложений вроде "Phusion Passenger" или "Unicorn". Упомянутые два специализированные сервера в плане преимуществ идут ноздря в ноздрю, но для интеграции первого с "Nginx" требуется установка и не совсем очевидная настройка специального модуля, так что у меня в фаворитах оказался "Unicorn" - там более, что его для своего продукта также использует команда "GitLab".

Не мудрствуя лукаво, в едином для нашей инсталляции "Redmine" стиле установим gems-пакет с сервером приложений "Unicorn".

Дополним перечень зависимостей:

# cd /var/opt/redmine
# vi ./Gemfile

source 'https://rubygems.org'
....
gem 'unicorn'

И запустим процедуру удовлетворения зависимостей gems-пакетов:

# bundle config set without 'development test'
# bundle install

Заготовим место для сохранения журналов событий сервера приложений:

# mkdir -p /var/log/unicorn
# chown -R www-data:www-data /var/log/unicorn

Скопируем в директорию конфигураций "Redmine" файл с настройками "Unicorn" и приведём его к виду, рекомендованному разработчиками развёртываемого сервиса:

# cd /var/opt/redmine
# cp /usr/share/doc/unicorn/examples/unicorn.conf.rb ./config/unicorn.rb
# vi ./config/unicorn.rb

# Количество процессов обработки запросов
worker_processes 4

# Контекст, в котором запускается сервер приложений
user "www-data", "www-data"

# Корневая директория сервера приложений
working_directory "/var/opt/redmine"

# Точка приёма запросов от вышестоящего фронтального web-сервера
# (для максимально быстродействия выбираем "файловый сокет")
#listen 8080, :tcp_nopush => true
listen "/var/run/unicorn-redmine.sock", :backlog => 64

# Устанавливаем таймаут ожидания ответа на запрос в соединении
timeout 300

# PID-файл и журналы событий
pid "/var/run/unicorn-redmine.pid"
stderr_path "/var/log/unicorn/unicorn.stderr.log"
stdout_path "/var/log/unicorn/unicorn.stdout.log"

# Для ускорения работы активируем загрузку приложений в ОЗУ
preload_app true
run_once = true

# Описываем модель управления ресурсами при изменении в потоках
before_fork do |server, worker|
  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
  if run_once
    run_once = false
  end
end
after_fork do |server, worker|
  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end

Пробуем вручную запустить сервер приложений со всеми ruby-приложениями, обнаруженными в рабочей директории:

# cd /var/opt/redmine
# bundle exec unicorn_rails -E production -c ./config/unicorn.rb

Настройка автозагрузки "Unicorn" посредством "Systemd".

Создаём файл описания параметров запуска и остановки сервера приложений с "Redmine", в роли сервиса "Systemd":

# vi /etc/systemd/system/unicorn-redmine.service

[Unit]
Description=Unicorn/Ruby web service for Redmine
After=network.target mysql.service

[Service]
WorkingDirectory=/var/opt/redmine

[Service]
ExecStart=/usr/local/bin/unicorn_rails -c ./config/unicorn.rb -E production
Restart=on-abort

[Install]
WantedBy=multi-user.target

Указываем "Systemd" перечитать и принять новую конфигурацию, а также явно активируем и запускаем новый сервис:

# systemctl daemon-reload
# systemctl enable unicorn-redmine.service
# systemctl start unicorn-redmine

Смотрим журнал событий "Systemd", если "что-то пошло не так":

# systemctl status unicorn-redmine
# journalctl -xe

Установка фронтального web-сервера "Nginx".

Выше мы запустили "Redmine" в web-сервере приложений "Unicorn". На практике для приёма и первичной обработки клиентских подключений удобно использовать более легковесный web-сервер. Воспользуемся "Nginx":

# apt-get install nginx-light

Для последующего включения в "Nginx" современного SSL/TLS и HTTPv2 генерируем DH-файл:

# mkdir -p /etc/ssl/nginx && chown -R root:root /etc/ssl/nginx
# openssl dhparam -out /etc/ssl/nginx/dhparam.2048.pem 2048

Слегка преднастроим фронтальный web-сервер:

# vi /etc/nginx/nginx.conf

user www-data www-data;
worker_processes auto;
....
http {
  ....
  server_tokens off;
  client_max_body_size 0;
....

Конфигурация принимающего подключения пользователей web-сервера "Nginx" проста и сводится к описанию параметров "проксирования" всех запросов нижележащему web-сервису, запущенному внутри сервера приложений, доступному через "файловый сокет":

# vi /etc/nginx/sites-available/redmine.example.net.conf

upstream redmine {
  server unix:/var/run/unicorn-redmine.sock fail_timeout=0;
}

server {
  listen 80;
  server_name redmine.example.net;
  location / { rewrite ^(.+)$ https://$host$1 permanent; }
  #include /etc/nginx/snippets/letsencrypt.conf;
}

server {
  listen 443 ssl http2;
  server_name redmine.example.net;

  access_log /var/log/nginx/redmine.example.net_access.log;
  error_log /var/log/nginx/redmine.example.net_error.log;

  ssl_dhparam /etc/ssl/nginx/dhparam.2048.pem;
  ssl_certificate /etc/ssl/nginx/wildcard.example.net.crt;
  ssl_certificate_key /etc/ssl/nginx/wildcard.example.net.key.decrypt;
  ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers on;

  root /var/opt/redmine/public;
  try_files $uri/index.html $uri.html $uri @redmine;
  location = / { rewrite ^(.+)$ $scheme://$host/my/page permanent; }

  location @redmine {
    proxy_pass http://redmine;
    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-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header X-Scheme https;
    proxy_set_header X-NginX-Proxy true;
    proxy_redirect off;
    proxy_read_timeout 300;
  }

  error_page 404 /404.html;
  location = /404.html {
    root /var/redmine/public;
  }

  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /var/redmine/public;
  }
}

Удаляем конфигурацию "по умолчанию", активируем новую, проверяем и запускаем в работу:

# rm /etc/nginx/sites-enabled/default
# ln -s /etc/nginx/sites-available/redmine.example.net.conf /etc/nginx/sites-enabled/redmine.example.net.conf
# nginx -t && /etc/init.d/nginx reload

Корректировка прав доступа к файлам "Redmine".

Учитывая то, что сервер приложений "Unicorn" и фронтальный web-сервер "Nginx" запущены в контексте пользователя "www-data", требуется предоставить таковому доступ к файлам "Redmine". Проще всего передать все файлы во владение нужному пользователю:

# chown -R www-data:www-data /var/opt/redmine
# chmod -R o-rwx /var/opt/redmine

Если необходимо реализовать строгое разграничение доступа к ресурсам "Redmine", то следует учесть, что следующие директории должны быть доступны на запись для "Unicorn":

/var/opt/redmine/files
/var/opt/redmine/public/plugin_assets
/var/opt/redmine/tmp

Настройка интеграции с потовым сервисом.

Для уведомлений пользователей о событиях в "тикетах" обязательно настраиваем связь с почтовым сервисом:

# cd /var/opt/redmine
# vi ./config/configuration.yml

....
default:
  email_delivery:
    delivery_method: :smtp
    smtp_settings:
      address: mail.example.net
      port: 25
      enable_starttls_auto: true
      authentication: :login
      domain: example.net
      user_name: redmine@example.net
      password: ***

Для применения изменений требуется перезапуск сервера приложений:

# systemctl restart unicorn-redmine
# systemctl status unicorn-redmine

Настройка подключения к внешнему LDAP для аутентификации.

В "Redmine" реализована интеграция с внешними сервисами аутентификации. Соединение с LDAP-сервисом описывается просто и работает впоследствии без нареканий:

Redmine -> Administration -> LDAP authentication -> New authentication mode:
  Name: ldap0.example.net
  Host: ldap0.example.net
  Port: 636 (LDAPS)
  Account: uid=redmine,ou=Accounts,ou=Services,dc=example,dc=net
  Password: ***
  Base DN: ou=People,dc=example,dc=net
  LDAP filter: (& (objectclass=person)(memberOf=cn=redmineusers,ou=groups,dc=example,dc=net))
  On-the-fly user creation: on
  Attributes:
    Login attribute: uid
    Firstname attribute: givenName
    Lastname attribute: sn
    Email attribute: mail


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )