Apps: Java, Apache Maven, Ant, Tomcat, Nginx, PostgreSQL, patch.
Задача: описание этапов сборки из исходных кодов и развёртывания комплекса web-приложений ("сервлетов") репозитория цифровых документов "DSpace v6", в среде контейнеризатора "Apache Tomcat".
В качестве отправных точек при настройке мною использовались следующие разделы официальной документации: "DSpace 6.x Documentation" и "Installing DSpace 6.x".
Последовательность дальнейших действий такова:
1. Производим предварительную подготовку системного окружения (отдельная инструкция).
2. Устанавливаем интерпретатор языка "Java" (OpenJDK).
3. Устанавливаем инструментарий сборки Java-приложений "Apache Maven".
4. Устанавливаем инструментарий сборки Java-приложений "Apache Ant".
5. Устанавливаем контейнеризатор "Apache Tomcat".
6. Устанавливаем фронтальный web-сервер "Nginx" и связываем его с "Tomcat".
7. Устанавливаем СУБД "PostgreSQL" и преднастраиваем её.
8. Получаем и вносим исправления в исходные коды проекта "DSpace".
9. Конфигурируем специфичные для инстанса параметры "DSpace".
10. Собираем и развёртываем Java-сервлеты web-приложений "DSpace".
11. Проверяем корректность работы компонентов запущенного web-сервиса.
2. Устанавливаем интерпретатор языка "Java" (OpenJDK).
3. Устанавливаем инструментарий сборки Java-приложений "Apache Maven".
4. Устанавливаем инструментарий сборки Java-приложений "Apache Ant".
5. Устанавливаем контейнеризатор "Apache Tomcat".
6. Устанавливаем фронтальный web-сервер "Nginx" и связываем его с "Tomcat".
7. Устанавливаем СУБД "PostgreSQL" и преднастраиваем её.
8. Получаем и вносим исправления в исходные коды проекта "DSpace".
9. Конфигурируем специфичные для инстанса параметры "DSpace".
10. Собираем и развёртываем Java-сервлеты web-приложений "DSpace".
11. Проверяем корректность работы компонентов запущенного web-сервиса.
Первые семь пунктов плана исполним в этой заметке, а сборку и установку web-приложений "DSpace" как такового разберём в следующей публикации.
Создание выделенного пользователя и файловой структуры для приложений "DSpace".
Заранее заводим пользователя, от имени которого будет запускаться web-приложение (лишая его при этом возможности работать в полноценной командной оболочке, во избежание):
# groupadd --system dspace
# useradd --system --home-dir /var/lib/dspace --shell /bin/false -g dspace dspace
# useradd --system --home-dir /var/lib/dspace --shell /bin/false -g dspace dspace
Через POSIX ACL предпишем устанавливать всем создаваемым файлам (и директориям) в месторасположении ресурсов web-проекта разрешения полного доступа как для пользователя, так и группы (в отличии от системных установок "umask 0022", разрешающим группе только чтение), при этом полностью запрещая доступ всем остальным:
# mkdir -p /var/lib/dspace
# setfacl --recursive --modify default:user::rwX,default:group::rwX,default:other:--- /var/lib/dspace
# setfacl --recursive --modify default:user::rwX,default:group::rwX,default:other:--- /var/lib/dspace
Переводим файловую структуру web-сервиса во владение выделенного для него пользователя:
# chown -R dspace:dspace /var/lib/dspace
# chmod -R ug+rw,o-rwx /var/lib/dspace
# chmod -R ug+rw,o-rwx /var/lib/dspace
Подготовка среды исполнения Java-сервлетов.
Для работы "DSpace" достаточно реализации Java-интерпретатора, разрабатываемой открытым сообществом - OpenJDK:
# aptitude install openjdk-8-jdk
Удобно создать символическую ссылку на директорию с текущей инсталляцией JRE, чтобы в дальнейшем проще было вызывать целевой интерпретатор:
# ln -s /usr/lib/jvm/java-8-openjdk-amd64 /usr/lib/jvm/default
Удостоверяясь в правильности действий узнаём версию Java-интерпретатора, указанного в системе вызываемым по умолчанию:
# java -version
Установка инструмента сборки Java-приложений.
Для полуавтоматизированной сборки "DSpace" используется инструментарий "Apache Maven".
В репозитории "Linux Ubuntu 18.04 LTS" уже имеется готовый APT-пакет "Maven v3.5.2" - формально этого вполне достаточно для наших задач, но мне не нравится подход к размещению его ресурсов в файловой иерархии и отсутствие функционала регистрации в роли исполняемого приложения в операционной системе. Я предпочитаю загрузить дистрибутив с сайта разработчиков и развернуть в удобном мне месте файловой системы:
# cd /usr/src/
# wget http://apache-mirror.rbc.ru/pub/apache/maven/maven-3/3.6.0/binaries/apache-maven-3.6.0-bin.tar.gz
# tar -xzvf ./apache-maven-3.6.0-bin.tar.gz -C /opt
# ln -s /opt/apache-maven-3.6.0 /opt/apache-maven
# wget http://apache-mirror.rbc.ru/pub/apache/maven/maven-3/3.6.0/binaries/apache-maven-3.6.0-bin.tar.gz
# tar -xzvf ./apache-maven-3.6.0-bin.tar.gz -C /opt
# ln -s /opt/apache-maven-3.6.0 /opt/apache-maven
Добавляем в глобальный перечень путей к исполняемым файлам нашу директорию со вспомогательным инструментарием:
# vi /etc/environment && source /etc/environment
PATH="/usr/local/sbin:...:/opt/apache-maven/bin"
Запрашиваем сведения о текущей версии ПО:
# mvn -v
Установка инструмента инсталляции Java-приложений.
Для упрощения процедур подготовки инсталляционного пакета "DSpace" используется инструментарий "Apache Ant".
Аналогично вышеприведённому решению с "Apache Maven", несмотря на наличие APT-пакета "Ant v1.10.3", я предпочитаю установить приложение вручную, загрузив его с сайта разработчиков:
# cd /usr/src/
# wget https://www.apache.org/dist/ant/binaries/apache-ant-1.10.5-bin.tar.gz
# tar -xzvf ./apache-ant-1.10.5-bin.tar.gz -C /opt
# ln -s /opt/apache-ant-1.10.5 /opt/apache-ant
# wget https://www.apache.org/dist/ant/binaries/apache-ant-1.10.5-bin.tar.gz
# tar -xzvf ./apache-ant-1.10.5-bin.tar.gz -C /opt
# ln -s /opt/apache-ant-1.10.5 /opt/apache-ant
Добавляем в глобальный перечень путей к исполняемым файлам нашу директорию со вспомогательным инструментарием:
# vi /etc/environment && source /etc/environment
PATH="/usr/local/sbin:...:/opt/apache-ant/bin"
Запрашиваем сведения о текущей версии ПО:
# ant -v
Развёртываем сервер приложений "Tomcat" для контейнера "DSpace".
Предварительно желательно установить системные библиотеки "Apache Portable Runtime", предназначенные для поддержки некоторых функций ускорения обработки событий ("LifecycleEvent"):
# aptitude install libtcnative-1 libapr1
После пробного запуска "Tomcat" следует проконтролировать (просмотрев журнал событий), совместима ли с ним установленная из APT-репозитория версия библиотеки ARP - возможно придётся использовать таковую из других источников. Важно не забыть указать "Tomcat"-у на специфичное месторасположение этой библиотеки в директории, например "/usr/lib/x86_64-linux-gnu".
Заготавливаем месторасположение исполняемых файлов и библиотек "Tomcat", выделенного только для проекта "DSpace":
# mkdir -p /opt/dspace/tomcat
Следуем в раздел загрузки на сайте разработчиков, забираем дистрибутив и устанавливаем его в желаемое место файловой системы простой распаковкой архива:
# cd /usr/src
# wget http://mirror.linux-ia64.org/apache/tomcat/tomcat-9/v9.0.17/bin/apache-tomcat-9.0.17.tar.gz
# tar -xvzf ./apache-tomcat-9.0.17.tar.gz
# mv ./apache-tomcat-9.0.17/* /opt/dspace/tomcat && rm -r ./apache-tomcat-9.0.17
# wget http://mirror.linux-ia64.org/apache/tomcat/tomcat-9/v9.0.17/bin/apache-tomcat-9.0.17.tar.gz
# tar -xvzf ./apache-tomcat-9.0.17.tar.gz
# mv ./apache-tomcat-9.0.17/* /opt/dspace/tomcat && rm -r ./apache-tomcat-9.0.17
Я предпочитаю разделять сущности, оставляя исполняемые файлы и разделяемые библиотеки в "/opt/", а web-приложения, их настройки и данные вынести в директорию динамичных данных "/var".
# mkdir -p /var/lib/dspace
# mv /opt/dspace/tomcat/conf /var/lib/dspace/conf
# mv /opt/dspace/tomcat/temp /var/lib/dspace/temp
# mv /opt/dspace/tomcat/webapps /var/lib/dspace/webapps
# mv /opt/dspace/tomcat/work /var/lib/dspace/work
# mv /opt/dspace/tomcat/logs /var/log/dspace
# mv /opt/dspace/tomcat/conf /var/lib/dspace/conf
# mv /opt/dspace/tomcat/temp /var/lib/dspace/temp
# mv /opt/dspace/tomcat/webapps /var/lib/dspace/webapps
# mv /opt/dspace/tomcat/work /var/lib/dspace/work
# mv /opt/dspace/tomcat/logs /var/log/dspace
Естественно, файловые ресурсы выделенного "Tomcat" передаём во владение выделенного для его запуска пользователя "dspace":
# chown -R dspace:dspace /opt/dspace /var/lib/dspace /var/log/dspace
# chmod -R o-rwx /opt/dspace /var/lib/dspace /var/log/dspace
# chmod -R o-rwx /opt/dspace /var/lib/dspace /var/log/dspace
Учитывая то, что у проекта "DSpace" есть свой набор разделяемых библиотек, а мы разнесли директории "HOME" и "BASE", важно предоставить возможность "Tomcat"-у загрузить необходимые ресурсы - если контейнеризатор запускается в режиме повышенной безопасности с "Java SecurityManager" (с ключём "-security"):
# vi /var/lib/dspace/conf/catalina.policy
....
// ========== CATALINA CODE PERMISSIONS ==============
....
// Using per instance lib directory (DSpace extensions)
grant codeBase "file:${catalina.base}/lib/-" {
permission java.security.AllPermission;
};
....
// ========== CATALINA CODE PERMISSIONS ==============
....
// Using per instance lib directory (DSpace extensions)
grant codeBase "file:${catalina.base}/lib/-" {
permission java.security.AllPermission;
};
....
В процессе запуска "Tomcat" упорно ищет библиотеки "gsi-classes.jar" и "serializer.jar", Java-классы которые на самом деле не потребуются, так как переопределены в библиотеках самого "DSpace" - на отработку этой процедуры уходит некоторое время, так что вносим эти библиотеки в список исключений:
# vi /var/lib/dspace/conf/catalina.properties
....
tomcat.util.scan.StandardJarScanFilter.jarsToSkip=\
....
gsi-classes*.jar,\
....
serializer*.jar,\
....
tomcat.util.scan.StandardJarScanFilter.jarsToSkip=\
....
gsi-classes*.jar,\
....
serializer*.jar,\
....
Если мысль удовлетворить все пожелания "Tomcat" неотступна, то можно точечно загрузить (например с репозитория "https://mvnrepository.com/artifact/xalan/serializer") нужные Java-библиотеки посредством "Apache Maven" (но мои сервисы отлично живут без этого):
# /opt/apache-maven/bin/mvn dependency:get -DremoteRepositories=http://central.maven.org/maven2/ -DgroupId=xalan -DartifactId=serializer -Dversion=2.7.1 -Dtransitive=false -Ddest=/tmp/serializer.jar
Настройка журналирования событий компонентов "Tomcat".
Дабы избежать разрастания не особо нужных журналов событий компонентов "Tomcat", скорректируем срок их хранения, уменьшив его до недели:
# vi /var/lib/dspace/conf/logging.properties
....
# Задаём место и срок хранения журналов событий в течение недели (по умолчанию три месяца)
# (обращаем внимание на то, что потоков журналирования может быть несколько)
#
1catalina.org.apache.juli.AsyncFileHandler.directory = /var/log/dspace
1catalina.org.apache.juli.AsyncFileHandler.maxDays = 7
....
2localhost.org.apache.juli.AsyncFileHandler.directory = /var/log/dspace
2localhost.org.apache.juli.AsyncFileHandler.maxDays = 7
....
3manager.org.apache.juli.AsyncFileHandler.directory = /var/log/dspace
3manager.org.apache.juli.AsyncFileHandler.maxDays = 7
....
4host-manager.org.apache.juli.AsyncFileHandler.directory = /var/log/dspace
4host-manager.org.apache.juli.AsyncFileHandler.maxDays = 7
....
# Задаём место и срок хранения журналов событий в течение недели (по умолчанию три месяца)
# (обращаем внимание на то, что потоков журналирования может быть несколько)
#
1catalina.org.apache.juli.AsyncFileHandler.directory = /var/log/dspace
1catalina.org.apache.juli.AsyncFileHandler.maxDays = 7
....
2localhost.org.apache.juli.AsyncFileHandler.directory = /var/log/dspace
2localhost.org.apache.juli.AsyncFileHandler.maxDays = 7
....
3manager.org.apache.juli.AsyncFileHandler.directory = /var/log/dspace
3manager.org.apache.juli.AsyncFileHandler.maxDays = 7
....
4host-manager.org.apache.juli.AsyncFileHandler.directory = /var/log/dspace
4host-manager.org.apache.juli.AsyncFileHandler.maxDays = 7
....
Из соображений унификации аналогично вышеприведённому примеру задаём параметры хранения журнала событий запросов к web-приложениям в контейнере:
# vi /var/lib/dspace/conf/server.xml
....
<Server ...>
....
<Service name="Catalina">
....
<Engine name="Catalina" defaultHost="localhost">
....
<Host name="localhost" ...>
....
<!-- Изменяем именование журнала событий доступа и устанавливаем срок хранения в одну неделю (по умолчанию неограниченно) -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="/var/log/dspace"
prefix="localhost_access" suffix=".log"
pattern="%h %l %u %t "%r" %s %b"
rotatable="true" fileDateFormat=".yyyy-MM-dd" maxDays="7" />
....
<Server ...>
....
<Service name="Catalina">
....
<Engine name="Catalina" defaultHost="localhost">
....
<Host name="localhost" ...>
....
<!-- Изменяем именование журнала событий доступа и устанавливаем срок хранения в одну неделю (по умолчанию неограниченно) -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="/var/log/dspace"
prefix="localhost_access" suffix=".log"
pattern="%h %l %u %t "%r" %s %b"
rotatable="true" fileDateFormat=".yyyy-MM-dd" maxDays="7" />
....
Вообще, возне с журналами событий "Tomcat" посвящается особая песня, часть из которой вынесена в отдельную публикацию.
Регистрация в "Systemd" сервиса "Tomcat" с контейнерами "DSpace".
Создаём файл описания параметров запуска и остановки контейнера "Tomcat" с web-приложением "DSpace" в качестве сервиса "Systemd":
# vi /etc/systemd/system/dspace-tomcat.service
[Unit]
Description=Service Tomcat with DSpace servlet.
After=network.target
[Service]
Type=forking
User=dspace
Group=dspace
UMask=0006
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Environment="LANG=en_US.UTF-8"
Environment="JAVA_HOME=/usr/lib/jvm/default"
Environment="CATALINA_PID=/var/run/dspace-tomcat.pid"
Environment="CATALINA_HOME=/opt/dspace/tomcat"
Environment="CATALINA_BASE=/var/lib/dspace"
Environment="CATALINA_TMPDIR=/var/lib/dspace/temp"
Environment="CATALINA_OUT=/var/log/dspace/catalina.out"
Environment="CATALINA_OPTS=-Djava.library.path=/lib:/usr/lib:/usr/lib/x86_64-linux-gnu"
Environment="JAVA_OPTS=-Xms2G -Xmx4G -XX:+UseConcMarkSweepGC -XX:+UseNUMA -XX:+UseCompressedOops -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Duser.language=en -Duser.country=US"
ExecStart=/opt/dspace/tomcat/bin/startup.sh
ExecStop=/opt/dspace/tomcat/bin/shutdown.sh
[Install]
WantedBy=multi-user.target
Description=Service Tomcat with DSpace servlet.
After=network.target
[Service]
Type=forking
User=dspace
Group=dspace
UMask=0006
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Environment="LANG=en_US.UTF-8"
Environment="JAVA_HOME=/usr/lib/jvm/default"
Environment="CATALINA_PID=/var/run/dspace-tomcat.pid"
Environment="CATALINA_HOME=/opt/dspace/tomcat"
Environment="CATALINA_BASE=/var/lib/dspace"
Environment="CATALINA_TMPDIR=/var/lib/dspace/temp"
Environment="CATALINA_OUT=/var/log/dspace/catalina.out"
Environment="CATALINA_OPTS=-Djava.library.path=/lib:/usr/lib:/usr/lib/x86_64-linux-gnu"
Environment="JAVA_OPTS=-Xms2G -Xmx4G -XX:+UseConcMarkSweepGC -XX:+UseNUMA -XX:+UseCompressedOops -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Duser.language=en -Duser.country=US"
ExecStart=/opt/dspace/tomcat/bin/startup.sh
ExecStop=/opt/dspace/tomcat/bin/shutdown.sh
[Install]
WantedBy=multi-user.target
Указываем "Systemd" перечитать и принять новую конфигурацию, а также явно активируем и запускаем новый сервис:
# systemctl daemon-reload
# systemctl enable dspace-tomcat
# systemctl start dspace-tomcat
# journalctl -xe
# systemctl enable dspace-tomcat
# systemctl start dspace-tomcat
# journalctl -xe
Сразу можно удостоверится, прослушивает ли "Tomcat" нужный нам сетевой порт в ожидании запросов от пользователей:
# netstat -apn | grep -i java
....
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN .../java
....
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN .../java
....
Уже сейчас можно было бы развёртывать web-приложение под управлением "Tomcat" и обращаться к нему через через локальную сетевую петлю (в нашем случае по адресу "http://localhost:8080").
Разрешаем управление сервисом "Systemd" выделенному пользователю.
Мне очень хочется иметь возможность запускать и останавливать запущенный в качестве сервиса "Tomcat", чтобы весь функционал управления "DSpace" был доступен из контекста непривилегированного пользователя "dspace".
Используя функционал расширения конфигурации SUDO добавляем разрешающее правило в отдельный файл конфигурации:
# vi /etc/sudoers.d/dspace-tomcat-users
....
dspace ALL=(root) NOPASSWD: /bin/systemctl start dspace-tomcat
dspace ALL=(root) NOPASSWD: /bin/systemctl stop dspace-tomcat
dspace ALL=(root) NOPASSWD: /bin/systemctl start dspace-tomcat
dspace ALL=(root) NOPASSWD: /bin/systemctl stop dspace-tomcat
Обязательно проверяем синтаксическую корректность вносимых изменений:
# visudo -cf /etc/sudoers.d/dspace-tomcat-users
Ограничиваем доступ к файлу конфигурации:
# chown root:root /etc/sudoers.d/dspace-tomcat-users
# chmod go-rwx /etc/sudoers.d/dspace-tomcat-users
# chmod go-rwx /etc/sudoers.d/dspace-tomcat-users
В современном Linux правила SUDO уже не полностью определяющие - над ними появилась надстройка "PolicyKit", которая в интеграции с "Systemd" не допускает рядового пользователя до управления "юнитами" последнего, требуя ввода пароля - примерно таким образом:
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
Authentication is required to stop 'dspace-tomcat.service'.
Authentication is required to stop 'dspace-tomcat.service'.
Фреймворк "PolicyKit" - это средство для управления правами приложений пользовательского уровня, позволяющее непривилегированным процессам решать административные задачи: единый интерфейс предоставления прав доступа к привилегированным операциям для непривилегированных приложений при помощи набора правил (политик) и шины "D-Bus".
В данный момент встречается две реализации "PolicyKit", с кардинально различающимся форматом конфигурационных файлов. Узнаём нашу:
# pkaction --version
Для версии до "0.105" и включительно мы имеем возможность только выдать разрешение конкретному пользователю всеми Systemd-сервисам, без указания какого-то конкретного:
# vi /etc/polkit-1/localauthority/50-local.d/org.freedesktop.systemd1.pkla
[Allow user "dspace" to run systemctl commands]
Identity=unix-user:dspace
Action=org.freedesktop.systemd1.manage-units
ResultInactive=no
ResultActive=no
ResultAny=yes
Identity=unix-user:dspace
Action=org.freedesktop.systemd1.manage-units
ResultInactive=no
ResultActive=no
ResultAny=yes
Начиная с версии "0.106" и выше со сменой формата конфигурации появилась возможность выдать разрешение на управление конкретным System-сервисом:
# vi /etc/polkit-1/rules.d/10-dspace.rules
/* Allow user "dspace" to run systemctl unit "dspace-tomcat" */
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.systemd1.manage-units" && action.lookup("unit") == "dspace-tomcat.service" && subject.user == "dspace") {
return polkit.Result.YES;
}
});
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.systemd1.manage-units" && action.lookup("unit") == "dspace-tomcat.service" && subject.user == "dspace") {
return polkit.Result.YES;
}
});
После изменения конфигурации проверяем, получил ли пользователь "dspace" право управлять сервисом:
# sudo -u dspace systemctl restart dspace-tomcat
Установка фронтального web-сервера Nginx.
"Apache Tomcat" предназначен не только для контейнеризации Java-сервлетов, но и выступает в роли web-сервера. Однако на практике для приёма и первичной обработки клиентских подключений удобнее использовать более легковесный web-сервер. Я предпочитаю "Nginx":
# aptitude install nginx-light
Конфигурация принимающего подключения пользователей web-сервера "Nginx" проста и сводится к описанию параметров "проксирования" всех запросов нижележащему "Tomcat":
# vi /etc/nginx/nginx.conf
....
http {
....
# Велим Nginx не выдавать сведения о номере своей версии
server_tokens off;
# Отключаем проверку размера тела передаваемого Tomcat запроса
client_max_body_size 0;
....
http {
....
# Велим Nginx не выдавать сведения о номере своей версии
server_tokens off;
# Отключаем проверку размера тела передаваемого Tomcat запроса
client_max_body_size 0;
....
Конфигурация web-сайта, принимающего и проксирующего запросы к web-приложениям в "Tomcat":
# vi /etc/nginx/sites-available/dspace.example.net.conf
# Блок перехвата обращений посредством открытого HTTP и перенаправления таковых на HTTPS
server {
listen 80 default_server;
server_name dspace.example.net;
access_log off;
error_log off;
rewrite ^(.+)$ https://dspace.example.net$1 permanent;
}
# Блок описания web-сервиса приёма, терминирования SSL/TLS запросов и проксирования их нижележащему Tomcat
server {
listen 443 ssl http2;
server_name dspace.example.net;
access_log /var/log/nginx/dspace.example.net_access.log;
error_log /var/log/nginx/dspace.example.net_error.log;
# Явно указываем обслуживать здесь только SSL/TLS подключения
ssl on;
# Описываем параметры установления соединений SSL/TLS
ssl_certificate /etc/nginx/ssl/wildcard.example.net.crt;
ssl_certificate_key /etc/nginx/ssl/wildcard.example.net.key.decrypt;
ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Перенаправляем на основное web-приложение при запросе корня web-ресурса
location = / {
rewrite ^ $scheme://$host/xmlui/ last;
}
# Блокируем доступ к "закрытым" извне web-приложениям
location ~* /(jspui|solr)/ {
deny all; log_not_found off; access_log off;
}
# Отправляем все запросы на обработку в Tomcat
location / {
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_connect_timeout 240;
proxy_send_timeout 240;
proxy_read_timeout 240;
}
}
server {
listen 80 default_server;
server_name dspace.example.net;
access_log off;
error_log off;
rewrite ^(.+)$ https://dspace.example.net$1 permanent;
}
# Блок описания web-сервиса приёма, терминирования SSL/TLS запросов и проксирования их нижележащему Tomcat
server {
listen 443 ssl http2;
server_name dspace.example.net;
access_log /var/log/nginx/dspace.example.net_access.log;
error_log /var/log/nginx/dspace.example.net_error.log;
# Явно указываем обслуживать здесь только SSL/TLS подключения
ssl on;
# Описываем параметры установления соединений SSL/TLS
ssl_certificate /etc/nginx/ssl/wildcard.example.net.crt;
ssl_certificate_key /etc/nginx/ssl/wildcard.example.net.key.decrypt;
ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Перенаправляем на основное web-приложение при запросе корня web-ресурса
location = / {
rewrite ^ $scheme://$host/xmlui/ last;
}
# Блокируем доступ к "закрытым" извне web-приложениям
location ~* /(jspui|solr)/ {
deny all; log_not_found off; access_log off;
}
# Отправляем все запросы на обработку в Tomcat
location / {
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_connect_timeout 240;
proxy_send_timeout 240;
proxy_read_timeout 240;
}
}
Удаляем ненужную конфигурацию-заглушку, активируем для "Nginx" новую конфигурацию, проверяем её синтаксическую корректность и запускаем в работу:
# rm /etc/nginx/sites-enabled/default
# ln -s /etc/nginx/sites-available/dspace.example.net.conf /etc/nginx/sites-enabled/dspace.example.net.conf
# nginx -t
# /etc/init.d/nginx reload
# ln -s /etc/nginx/sites-available/dspace.example.net.conf /etc/nginx/sites-enabled/dspace.example.net.conf
# nginx -t
# /etc/init.d/nginx reload
Адаптация "Tomcat" для работы в спарке с "Nginx".
С учётом того, что запросы пользователей будут приниматься web-сервером "Nginx", а обрабатываться скрытым за ним "Tomcat", потребуется согласовать адреса FQDN и номера сетевых портов терминирования подключений пользователя, которые должны сохранятся неизменными на протяжении всей цепочки обработки запроса, при передачи от сервера к серверу, и назад.
В самом простом случае достаточно уведомить наш контейнеризатор "Tomcat" о параметрах терминирования клиентских запросов вышестоящим проксирующим web-сервисом, чтобы в ответах таковому вместо внутренних имени сайта "localhost", порта "8080" и протокола "http" было указано то, что видится клиентам снаружи. Для этого достаточно модифицировать всего одну секцию в XML-файле конфигурации выделенного под наш web-сервис инстанса "Tomcat":
# vi /var/lib/dspace/conf/server.xml
....
<Server ... >
....
<Service name="Catalina">
....
<!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
<Connector port="8080" protocol="HTTP/1.1"
address="127.0.0.1"
minSpareThreads="25"
enableLookups="false"
connectionTimeout="20000"
disableUploadTimeout="true"
URIEncoding="UTF-8"
<!-- Невостребованный в нашей схеме обслуживания SSL/TLS вышестоящим Nginx параметр редиректа для обслуживания HTTPS-запросов. -->
<!-- redirectPort="8443" -->
<!-- Дополнительный набор параметров описания точки терминирования клиентских запросов вышестоящим проксирующим web-сервисом. -->
proxyName="dspace.example.net" proxyPort="443" scheme="https"
/>
....
<Server ... >
....
<Service name="Catalina">
....
<!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
<Connector port="8080" protocol="HTTP/1.1"
address="127.0.0.1"
minSpareThreads="25"
enableLookups="false"
connectionTimeout="20000"
disableUploadTimeout="true"
URIEncoding="UTF-8"
<!-- Невостребованный в нашей схеме обслуживания SSL/TLS вышестоящим Nginx параметр редиректа для обслуживания HTTPS-запросов. -->
<!-- redirectPort="8443" -->
<!-- Дополнительный набор параметров описания точки терминирования клиентских запросов вышестоящим проксирующим web-сервисом. -->
proxyName="dspace.example.net" proxyPort="443" scheme="https"
/>
....
В конфигурационном файле "Apache Tomcat" есть секция описания поддержки соединений по специальном протоколу согласования (AJP) с вышестоящим web-сервером "Apache HTTP". Мы выбрали для этой роли "Nginx", так что прослушивание ненужного в схеме порта отключаем:
# vi /var/lib/dspace/conf/server.xml
....
<!-- Define an AJP 1.3 Connector on port 8009 -->
<!-- Connector port="8009" protocol="AJP/1.3" ... /-->
....
<!-- Define an AJP 1.3 Connector on port 8009 -->
<!-- Connector port="8009" protocol="AJP/1.3" ... /-->
....
Уже для порядка, раз начали править конфигурацию контейнеризатора, деактивируем функционал выключения "Tomcat" посредством посыла команды на выделенный для этого сетевой порт (обычно TCP:8005 на интерфейсе "локальной петли"), установив номер порта в "-1":
# vi /var/lib/dspace/conf/server.xml
<?xml ... ?>
....
<Server port="-1" shutdown="SHUTDOWN">
....
....
<Server port="-1" shutdown="SHUTDOWN">
....
# systemctl restart dspace-tomcat
# journalctl -xe
# journalctl -xe
На этом с настройкой web-сервисов заканчиваем.
Установка и базовая настройка "PostgreSQL".
"DSpace" может работать с СУБД "Oracle" и "PostgreSQL". Я выбираю последний, как наиболее знакомый:
# aptitude install postgresql postgresql-client postgresql-contrib pgtop
Разработчики "PostgreSQL" сделали её такой, что она запускается сразу и везде, не требуя вообще никаких настроек для начала работы. Из соображений унификации методов доступа и повышения пассивной безопасности для обращений через локальный файловый сокет и "сетевую петлю" потребуем аутентификации паролем (шифрованным в MD5), используемым только внутри самой СУБД - это позволит не смешивать локальных системных пользователей и пользователей СУБД:
# vi /etc/postgresql/10/main/pg_hba.conf
....
# TYPE DATABASE USER ADDRESS METHOD
....
# Unix domain socket connections only
local all all md5
# IPv4 local connections:
host all all 127.0.0.1/32 md5
....
# TYPE DATABASE USER ADDRESS METHOD
....
# Unix domain socket connections only
local all all md5
# IPv4 local connections:
host all all 127.0.0.1/32 md5
....
Иногда полезно разрешить СУБД обслуживать чуть большее принятого по умолчанию количество клиентских соединений:
# vi /etc/postgresql/10/main/postgresql.conf
....
max_connections = 200 # (default = 100)
....
max_connections = 200 # (default = 100)
....
Для применения вышеприведённых изменений потребуется перезапуск сервиса:
# /etc/init.d/postgresql restart
Убедимся в том, что "PostgreSQL" успешно запущен и слушает назначенный ему порт:
# netstat -apn | grep postgres
tcp ... 127.0.0.1:5432 0.0.0.0:* LISTEN .../postgres
....
....
Естественно, для хранения данных проекта "DSpace" необходимо создать внутри БД соответствующие структуры. Воспользуемся CLI-утилитой для этого:
# su - postgres
postgres@dspace:~$ psql
postgres@dspace:~$ psql
postgres=# DROP DATABASE IF EXISTS dspace;
postgres=#
postgres=# CREATE USER dspace WITH PASSWORD '<userPassword>';
postgres=#
postgres=# CREATE DATABASE dspace WITH OWNER = 'dspace' ENCODING = 'UTF-8' LC_COLLATE = 'ru_RU.UTF-8' LC_CTYPE = 'ru_RU.UTF-8' TEMPLATE = 'template0';
postgres=# \q
postgres=#
postgres=# CREATE USER dspace WITH PASSWORD '<userPassword>';
postgres=#
postgres=# CREATE DATABASE dspace WITH OWNER = 'dspace' ENCODING = 'UTF-8' LC_COLLATE = 'ru_RU.UTF-8' LC_CTYPE = 'ru_RU.UTF-8' TEMPLATE = 'template0';
postgres=# \q
Учитывая то, что пользователь "dspace" является владельцем БД "dspace", особых разрешений на доступ к таковой выдавать нет необходимости.
Проверяем соединение с СУБД и возможность доступа к ресурсам БД от имени выделенного для "DSpace" пользователя:
# psql -h localhost -U dspace -W dspace
В дальнейшем нам понадобится автоматизировать выгрузку и загрузку резервных копий (для процедур CI/CD), и для упрощения аутентификации в домашней директории пользователя "dspace" разместим файл с логином и паролем для подключения к СУБД:
# vi /var/lib/dspace/.pgpass
localhost:5432:dspace:dspace:<userPassword>
Разумеется, в обязательном порядке закрываем доступ к паролю всем посторонним:
# chown dspace:root /var/lib/dspace/.pgpass && chmod go-rwx /var/lib/dspace/.pgpass
Проверяем соединение с СУБД и возможность доступа к ресурсам БД в контексте выделенного для "DSpace" пользователя, с автоматической подстановкой пароля:
# sudo -u dspace psql dspace
Со временем будет полезно понаблюдать за текущей ситуацией с использованием ресурсов СУБД, особенно в ситуации, когда web-сервис перестанет справляться с нагрузкой и понадобится локализовать узкое место:
# sudo -u postgres pg_top
Включение специфичного расширения в "PostgreSQL".
Начиная с "DSpace v6" разработчики решили создавать идентификаторы объектов (UUID) посредством криптографической функции, гарантируя тем самым глобальную уникальность UUID. Придётся установить модуль "pgcrypto" (в APT-пакете "postgresql-contrib") и включить этот функционал явно для созданной "базы данных" (и это нужно будет делать каждый раз, как БД создаётся - например, после зачистки в процессе экспериментирования):
# su - postgres
postgres@dspace:~$ psql
postgres@dspace:~$ psql
postgres=# \c dspace;
dspace=#
dspace=# CREATE EXTENSION pgcrypto;
dspace=#
dspace=# \dx
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+------------------------------
pgcrypto | 1.3 | public | cryptographic functions
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
dspace=# \q
dspace=#
dspace=# CREATE EXTENSION pgcrypto;
dspace=#
dspace=# \dx
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+------------------------------
pgcrypto | 1.3 | public | cryptographic functions
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
dspace=# \q
Одной командой, например в профилактических целях при автоматизированном развёртывание приложения, активировать расширение можно так:
# sudo -u postgres psql --username=postgres dspace -c "CREATE EXTENSION pgcrypto;"
Очень неудобно, что для активации "расширения" требуются привилегии суперпользователя - это усложняет автоматизацию, для безопасности изолируемую в рамках контекста простого пользователя.
Сборку и установку web-приложений "DSpace" как такового разберём в следующей публикации.