Apps: "Ansible", "XWiki", "Docker", "Docker Compose".
Задача: избавление URL документа в "XWiki" от избыточных составляющих.
Сразу после установки "XWiki" из дистрибутива типичный URL современного режима отображения "Domain-based wiki access" выглядит следующим образом (с бессмысленными "bin" и "view" в середине):
https://xwiki.example.net/[xwiki/]bin/view/level0/level1/level2/
Это некрасиво, и я не первый, кто захотел избавиться от лишних слов в строке адреса документа - тому посвящена отдельная инструкция "ShortURLs" на сайте разработчиков "XWiki".
Первая ненужная составляющая URL "xwiki" легко убирается в случае, если "Tomcat" обслуживает только один "сервлет" и отсутствует необходимость выбора между web-приложениями. Достаточно установить xwiki-сервлет "as ROOT" и оставить пустым параметр "xwiki.webapppath" в "xwiki.cfg" - в собираемом разработчиками "XWiki" официальном docker-контейнере это уже сделано.
Вторая нежелательная составляющая URL "bin" удаляется сложнее всего. Это указатель на один из главных сервлетов обработки страницы ("Struts"), а кроме него есть ещё несколько вспомогательных, и нельзя просто перенаправить весь трафик в одно место "по умолчанию" - придётся вычленять из запросов те, что предназначены НЕ главному сервлету, отправлять их по назначению, и только все ОСТАЛЬНЫЕ отправлять главному сервлету ("Struts").
Третья невнятная составляющая URL "view" убирается проще всего - активацией параметра "xwiki.showviewaction=0" в "xwiki.cfg". При этом в дальнейшем указание "view" не вызовет ошибки - будет показана запрашиваемая страница - но в URL, генерируемом самой "XWiki" этой составляющей уже не будет.
Для применения изменений на любом этапе изменения режима отображения URL требуется перезапуск сервиса.
В итоге мы должны достигнуть следующего отображения адреса документа:
https://xwiki.example.net/level0/level1/level2/
Подготовка ansible-скрипта для создания модификации docker-образа "XWiki".
Как было отмечено выше, первый и третий этапы нормализации строки URL крайне просты, а вот в работе над вторым пришлось совершить столько взаимосвязанных настроек, что я счёл необходимым изложить их в виде скрипта, в процессе исполнения которого делается всё необходимое. Так проще обеспечить неизменность финальной конфигурации и снизить риск человеческой ошибки. На привычном "Bash" писать всё менее интересно, так что в этот раз применим для автоматизации "Ansible".
В самом простом изложении задача ansible-скрипта состоит в том, чтобы загрузить свежую версию docker-образа "XWiki", модифицировать содержимое docker-образа и создать на основе внесённых изменений новый docker-образ, который впоследствии будет применён для запуска web-сервиса.
Важно учитывать, что операции доработки контейнера важно делать или до первого запуска web-приложения в нём, или уже ПОСЛЕ успешной первичной настройки web-приложения, с заведением административного пользователя, как минимум. Если запустить контейнер, а потом сохранить его состояние - впоследствии неправильно написанный автоматический конфигуратор "XWiki" в "docker-entrypoint.sh" попросту не запустится.
Устанавливаем интерпретатор ansible-скриптов:
# apt-get install --no-install-recommends ansible
Создаём выделенную для автоматизации модификации "XWiki" директорию:
# mkdir -p /usr/local/etc/devops/images/xwiki
# cd /usr/local/etc/devops/images/xwiki
# cd /usr/local/etc/devops/images/xwiki
Загружаем исходный код проекта, в котором "XWiki" упаковывается в docker-образ - нам оттуда понадобятся конфигурационные файлы, преобразуемые в процессе:
# git clone https://github.com/xwiki-contrib/docker-xwiki.git ./docker-xwiki
Заготавливаем директорию для "самоподписанных" SSL-сертификатов, которые будут автоматически добавлены в список доверенных (необходимо для подключения к LDAP-серверам, как минимум):
# mkdir -p /usr/local/etc/ansible/xwiki-cacerts
# cp ./ss-rootCA.crt /usr/local/etc/ansible/xwiki-cacerts
# cp ./ss-rootCA.crt /usr/local/etc/ansible/xwiki-cacerts
Описываем правила обработки запросов библиотекой "UrlRewriteFilter":
# mkdir -p /usr/local/etc/ansible/xwiki-shorturls
# cd /usr/local/etc/ansible/xwiki-shorturls
# vi ./urlrewrite.xml
# cd /usr/local/etc/ansible/xwiki-shorturls
# vi ./urlrewrite.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN" "http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">
<urlrewrite decode-using="null">
<rule>
<note>
Ensure that URLs ending with .gwtrpc are not modified.
Note: Not needed with XWiki 9.7+ since the GWT editor has been removed.
</note>
<from>^/(.*)\.gwtrpc$</from>
<to type="forward" last="true">-</to>
</rule>
<rule>
<note>
Ensure that URLs that must not be served by the Struts Servlet are not modified.
</note>
<from>^/((bin|resources|skins|asyncrenderer|rest|webdav|xmlrpc|wiki|webjars)/(.*)|robots\.txt)$</from>
<to type="forward" last="true">-</to>
</rule>
<rule>
<note>
For all other URLs we prepend the "/bin/" prefix so that they get routed to the XWiki Action Servlet.
</note>
<from>^/(.*)$</from>
<to type="forward">/bin/$1</to>
</rule>
<outbound-rule>
<note>
Rewrite outbound URLs to remove the "/bin" part when there are two paths after it.
</note>
<from>/bin/(.*)/(.*)$</from>
<to>/$1/$2</to>
</outbound-rule>
<outbound-rule>
<note>
Rewrite outbound URLs to remove the "/bin" part when there's a single path after it.
</note>
<from>/bin/(.*)$</from>
<to>/$1</to>
</outbound-rule>
<outbound-rule>
<note>
Rewrite outbound URLs to remove the "/bin" part it's the last path.
</note>
<from>/bin$</from>
<to>/</to>
</outbound-rule>
</urlrewrite>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN" "http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">
<urlrewrite decode-using="null">
<rule>
<note>
Ensure that URLs ending with .gwtrpc are not modified.
Note: Not needed with XWiki 9.7+ since the GWT editor has been removed.
</note>
<from>^/(.*)\.gwtrpc$</from>
<to type="forward" last="true">-</to>
</rule>
<rule>
<note>
Ensure that URLs that must not be served by the Struts Servlet are not modified.
</note>
<from>^/((bin|resources|skins|asyncrenderer|rest|webdav|xmlrpc|wiki|webjars)/(.*)|robots\.txt)$</from>
<to type="forward" last="true">-</to>
</rule>
<rule>
<note>
For all other URLs we prepend the "/bin/" prefix so that they get routed to the XWiki Action Servlet.
</note>
<from>^/(.*)$</from>
<to type="forward">/bin/$1</to>
</rule>
<outbound-rule>
<note>
Rewrite outbound URLs to remove the "/bin" part when there are two paths after it.
</note>
<from>/bin/(.*)/(.*)$</from>
<to>/$1/$2</to>
</outbound-rule>
<outbound-rule>
<note>
Rewrite outbound URLs to remove the "/bin" part when there's a single path after it.
</note>
<from>/bin/(.*)$</from>
<to>/$1</to>
</outbound-rule>
<outbound-rule>
<note>
Rewrite outbound URLs to remove the "/bin" part it's the last path.
</note>
<from>/bin$</from>
<to>/</to>
</outbound-rule>
</urlrewrite>
Пишем ansible-скрипт, посредством которого осуществляются все необходимые преобразования:
# cd /usr/local/etc/ansible
# vi ./01.xwiki-ldapssl-shorturls.yml
# vi ./01.xwiki-ldapssl-shorturls.yml
- name: Completion of the XWiki container configuration with the addition of support "self-signed" SSL (for LDAP authentication) and "urlrewrite" rules
any_errors_fatal: true
gather_facts: false
hosts: 127.0.0.1
connection: local
tasks:
- name: Preventive delete temporary container
shell: docker rm tmp-xwiki-web || true
#- name: Preventive delete target container
# shell: docker rm --name selfmade:lts-mysql-tomcat-ldapssl-shorturls || true
- name: Pull original XWiki image
shell: docker pull xwiki:lts-mysql-tomcat
- name: Create temporary container
shell: docker create --name tmp-xwiki-web xwiki:lts-mysql-tomcat
- name: Clear file before fetch from temporary container
file: path='./xwiki-shorturls/docker-entrypoint.sh' state=absent
- name: Fetch file from temporary
shell: docker cp tmp-xwiki-web:/usr/local/bin/docker-entrypoint.sh ./xwiki-shorturls/docker-entrypoint.sh
- name: Adding certificate installation to the Java keystore in container
lineinfile:
path: ./xwiki-shorturls/docker-entrypoint.sh
insertafter: "^function first_start()"
line: " for I in /etc/ssl/xwiki/* ; do /opt/java/openjdk/bin/keytool -import -noprompt -trustcacerts -alias \"Added CA certificat ${I}\" -file \"${I}\" -storetype JKS -keystore /opt/java/openjdk/lib/security/cacerts -keypass changeit -storepass changeit ; done"
- name: Upload file into container
shell: docker cp ./xwiki-shorturls/docker-entrypoint.sh tmp-xwiki-web:/usr/local/bin/docker-entrypoint.sh
- name: Upload files of CA-certificates
shell: docker cp ./xwiki-cacerts/ tmp-xwiki-web:/etc/ssl/xwiki
- name: Clear file before fetch from temporary container
file: path='./xwiki-shorturls/web.xml' state=absent
- name: Fetch file from temporary
shell: docker cp tmp-xwiki-web:/usr/local/tomcat/webapps/ROOT/WEB-INF/web.xml ./xwiki-shorturls/web.xml
- name: Download "urlrewrite" library distribution file
get_url:
url: https://repo1.maven.org/maven2/org/tuckey/urlrewritefilter/4.0.3/urlrewritefilter-4.0.3.jar
dest: ./xwiki-shorturls/urlrewritefilter-4.0.3.jar
- name: Add configuration "urlrewrite" in global
lineinfile:
path: ./xwiki-shorturls/web.xml
insertafter: "<description>XWiki Application</description>"
line: "\n <!-- Custom filter inserted for support XWiki Short-URLs:\n https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/ShortURLs/ -->\n <filter>\n <filter-name>UrlRewriteFilter</filter-name>\n <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>\n </filter>\n <filter-mapping>\n <filter-name>UrlRewriteFilter</filter-name>\n <url-pattern>/*</url-pattern>\n <dispatcher>REQUEST</dispatcher>\n <dispatcher>FORWARD</dispatcher>\n </filter-mapping>"
- name: Upload file into container
shell: docker cp ./xwiki-shorturls/web.xml tmp-xwiki-web:/usr/local/tomcat/webapps/ROOT/WEB-INF/
- name: Upload file into container
shell: docker cp ./xwiki-shorturls/urlrewrite.xml tmp-xwiki-web:/usr/local/tomcat/webapps/ROOT/WEB-INF/
- name: Upload file into container
shell: docker cp ./xwiki-shorturls/urlrewritefilter-4.0.3.jar tmp-xwiki-web:/usr/local/tomcat/webapps/ROOT/WEB-INF/lib/
- name: Create target image from temporary container
shell: docker commit tmp-xwiki-web selfmade:lts-mysql-tomcat-ldapssl-shorturls
- name: Delete temporary container
shell: docker rm tmp-xwiki-web || true
- name: Prune dangling images
shell: docker image prune -f
any_errors_fatal: true
gather_facts: false
hosts: 127.0.0.1
connection: local
tasks:
- name: Preventive delete temporary container
shell: docker rm tmp-xwiki-web || true
#- name: Preventive delete target container
# shell: docker rm --name selfmade:lts-mysql-tomcat-ldapssl-shorturls || true
- name: Pull original XWiki image
shell: docker pull xwiki:lts-mysql-tomcat
- name: Create temporary container
shell: docker create --name tmp-xwiki-web xwiki:lts-mysql-tomcat
- name: Clear file before fetch from temporary container
file: path='./xwiki-shorturls/docker-entrypoint.sh' state=absent
- name: Fetch file from temporary
shell: docker cp tmp-xwiki-web:/usr/local/bin/docker-entrypoint.sh ./xwiki-shorturls/docker-entrypoint.sh
- name: Adding certificate installation to the Java keystore in container
lineinfile:
path: ./xwiki-shorturls/docker-entrypoint.sh
insertafter: "^function first_start()"
line: " for I in /etc/ssl/xwiki/* ; do /opt/java/openjdk/bin/keytool -import -noprompt -trustcacerts -alias \"Added CA certificat ${I}\" -file \"${I}\" -storetype JKS -keystore /opt/java/openjdk/lib/security/cacerts -keypass changeit -storepass changeit ; done"
- name: Upload file into container
shell: docker cp ./xwiki-shorturls/docker-entrypoint.sh tmp-xwiki-web:/usr/local/bin/docker-entrypoint.sh
- name: Upload files of CA-certificates
shell: docker cp ./xwiki-cacerts/ tmp-xwiki-web:/etc/ssl/xwiki
- name: Clear file before fetch from temporary container
file: path='./xwiki-shorturls/web.xml' state=absent
- name: Fetch file from temporary
shell: docker cp tmp-xwiki-web:/usr/local/tomcat/webapps/ROOT/WEB-INF/web.xml ./xwiki-shorturls/web.xml
- name: Download "urlrewrite" library distribution file
get_url:
url: https://repo1.maven.org/maven2/org/tuckey/urlrewritefilter/4.0.3/urlrewritefilter-4.0.3.jar
dest: ./xwiki-shorturls/urlrewritefilter-4.0.3.jar
- name: Add configuration "urlrewrite" in global
lineinfile:
path: ./xwiki-shorturls/web.xml
insertafter: "<description>XWiki Application</description>"
line: "\n <!-- Custom filter inserted for support XWiki Short-URLs:\n https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/ShortURLs/ -->\n <filter>\n <filter-name>UrlRewriteFilter</filter-name>\n <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>\n </filter>\n <filter-mapping>\n <filter-name>UrlRewriteFilter</filter-name>\n <url-pattern>/*</url-pattern>\n <dispatcher>REQUEST</dispatcher>\n <dispatcher>FORWARD</dispatcher>\n </filter-mapping>"
- name: Upload file into container
shell: docker cp ./xwiki-shorturls/web.xml tmp-xwiki-web:/usr/local/tomcat/webapps/ROOT/WEB-INF/
- name: Upload file into container
shell: docker cp ./xwiki-shorturls/urlrewrite.xml tmp-xwiki-web:/usr/local/tomcat/webapps/ROOT/WEB-INF/
- name: Upload file into container
shell: docker cp ./xwiki-shorturls/urlrewritefilter-4.0.3.jar tmp-xwiki-web:/usr/local/tomcat/webapps/ROOT/WEB-INF/lib/
- name: Create target image from temporary container
shell: docker commit tmp-xwiki-web selfmade:lts-mysql-tomcat-ldapssl-shorturls
- name: Delete temporary container
shell: docker rm tmp-xwiki-web || true
- name: Prune dangling images
shell: docker image prune -f
Запускаем ansible-скрипт и читаем выводимые им сообщения:
# cd /usr/local/etc/ansible
# ansible-playbook ./01.xwiki-ldapssl-shorturls.yml --connection=local
# ansible-playbook ./01.xwiki-ldapssl-shorturls.yml --connection=local
Применение подготовленной docker-образа в конфигурации "Docker Compose".
Если описываемый выше ansible-скрипт отработал корректно, то приготовленный им docker-образ можно применить для запуска инстанса "XWiki":
# vi ./docker-compose.yml
version: "3"
services:
xwiki:
container_name: "xwiki-web"
#image: "xwiki:lts-mysql-tomcat"
image: "selfmade:lts-mysql-tomcat-ldapssl-shorturls"
....
services:
xwiki:
container_name: "xwiki-web"
#image: "xwiki:lts-mysql-tomcat"
image: "selfmade:lts-mysql-tomcat-ldapssl-shorturls"
....
Полностью останавливаем и запускаем (с пересозданием) docker-контейнер с "XWiki":
# systemctl stop xwiki-docker && systemctl start xwiki-docker