Redmine: избавляемся от Webrick

Если внимательно читать официальный мануал по установке Redmine, то можно наткнуться на замечание:

Note: Webrick is not suitable for production use, please only use webrick for testing that the installation up to this point is functional. Use one of the many other guides in this wiki to setup redmine to use either Passenger (aka mod_rails), FCGI or a Rack server (Unicorn, Thin, Puma, hellip;) to serve up your redmine.

Я при установке руководствовался преимущественно русскоязычным гайдом, его составители были или ленивыми, или невнимательными, поэтому долгое время продакшн крутился на webrick с жуткими тормозами. В поисках причин и было найдено это уточнение. Переезд на thin в качестве бэкенда для nginx под катом

Итак, для начала устанавливаем Thin:

apt-get install thin

Перед настройкой создадим папку для логов

mkdir /var/log/thin
chmod 755 /var/log/thin

Позаботимся заблаговременно о ротации этих логов, чтобы в дальнейшем не возвращаться к проблеме растущего system time на сервере. Для этого создаем /etc/logrotate.d/thin следующего содержания:

/var/log/thin/*.log {
        daily
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 640 root adm
        sharedscripts
        postrotate
                /etc/init.d/thin restart >/dev/null
        endscript
}

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

thin config --config /tmp/redmine.yml --chdir /home/redmine \
    --environment production --socket /var/run/redmine/sockets/thin.sock \
    --daemonize --log /var/log/thin/redmine.log --pid /var/run/thin/redmine.pid \
    --user www-data --group www-data --servers 2 --prefix /redmine
mv /tmp/redmine.yml /etc/thin/redmine.yml
chown root:root /etc/thin/redmine.yml
chmod 644 /etc/thin/redmine.yml

Мне больше по душе редактирование конфига руками, в результате файл /etc/thin/redmine.yml выглядит примерно так:

# расположение файла pid
pid: /var/run/thin/thin.pid
# таймаут запросов
timeout: 30
# расположение логов
log: /var/log/thin/redmine.log
# максимальное количество одновременных соединений
max_conns: 1024
# подключение библиотек
require: []

# окружение фреймворка
environment: production
# максимальное количество постоянных соединений
max_persistent_conns: 512
# смена текущей директории
chdir: /home/redmine
# количество запускаемых серверов thin
servers: 2
# переходить в режим демона
daemonize: true

# расположение сокета
socket: /home/redmine/tmp/sockets/thin.sock
# учетная запись, под которой будет работать
# сервер thin
user: www-data
# группа, под которой будет работать сервер thin
group: www-data

Проверяем наличие run-скрипта /etc/init.d/thin и при необходимости правим его:

#!/bin/sh
### BEGIN INIT INFO
# Provides:          thin
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: thin initscript
# Description:       thin
### END INIT INFO

# Original author: Forrest Robertson

# Do NOT "set -e"

DAEMON=/usr/bin/thin
SCRIPT_NAME=/etc/init.d/thin

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

run_action() {
        ACTION="$1"
	
	if [ -x /usr/bin/ruby1.8 ]; then
	    /usr/bin/ruby1.8 $DAEMON $ACTION --all /etc/thin1.8
	fi
	
	if [ -x /usr/bin/ruby1.9.1 ]; then
	    /usr/bin/ruby1.9.1 $DAEMON $ACTION --all /etc/thin
	fi
	
}

case "$1" in
  start)
	run_action start
	;;
  stop)
	run_action stop
	;;
  restart|force-reload|reload)
	run_action restart
	;;
  *)
	echo "Usage: $SCRIPT_NAME {start|stop|restart}" >&2
	exit 3
	;;
esac

:

Запускаем, проверяем наличие «thin server» в списке процессов. Если что-то не работает — читаем логи, особое внимание стоит уделить наличию необходимых прав на рабочей директории redmine и папок для логов и pid-файлов.

После успешного запуска нового сервера правим конфигурацию nginx

	server {
		listen :80;
		server_name redmine;
		error_log   /var/log/nginx/thin_error.log;
		root /home/redmine/public;
		location / {
			try_files $uri $uri/index.html $uri.html @redmine_thin;
		}
		location @redmine_thin {
			proxy_pass http://redmine_thin;
			proxy_set_header   X-Forwarded-Proto $scheme;
			proxy_set_header   Host              $http_host;
			proxy_set_header   X-Real-IP         $remote_addr;
			proxy_redirect off;
		}
	}
	upstream redmine_thin {
		server unix://home/redmine/tmp/sockets/thin.0.sock;
		server unix://home/redmine/tmp/sockets/thin.1.sock;
	}

Здесь количество воркеров в директиве upstream совпадает с указанным в конфиге thin количеством запускаемых серверов.

Использование try_files позволяет избавить thin от раздачи статики, этим занимается непосредственно сам nginx.

Ссылки: