Skip to content

apache_tomcat: support Tomcat 10.1 on RHEL 10 - #405

Merged
danyalberchtoldlf merged 14 commits into
mainfrom
feat/tomcat-10.1
Oct 15, 2026
Merged

danyalberchtoldlf merged 14 commits into
mainfrom
feat/tomcat-10.1

Conversation

@danyalberchtoldlf

Copy link
Copy Markdown
Contributor

RHEL 10 ships Tomcat 10.1 instead of 9.0, and the role aborted there because it had no templates for that version. This PR adds a template set for 10.1 and fixes a default the role was missing on every version.

What changes

  • Tomcat 10.1 templates (server.xml, context.xml, logging.properties, tomcat-users.xml, sysconfig/tomcat), based on the files of the RHEL 10 package tomcat-10.1.49-4.el10_2 and kept as close to them as possible. They are picked by the installed version like the 9.0 set, and 10.1 is added to __apache_tomcat__supported_versions.
  • Deliberate deviations from the package, documented under "How the Role Behaves":
    • tomcat-users.xml stores the passwords from apache_tomcat__users__*_var as an unsalted sha-256 digest instead of in clear text; server.xml configures the matching MessageDigestCredentialHandler.
    • The access log pattern omits the session ID (%S) the package ships, since anyone who can read the log could take over the session.
    • As on 9.0, Tomcat's own log rotation is off in favour of logrotate.
  • Connector timeout: apache_tomcat__server_xml_connector_connection_timeout had no default, so the role aborted on an undefined variable unless the inventory set it. It now defaults to the documented 20000, which is also what the package ships. Separate commit.
  • README: supported versions as a list (9.0 on RHEL 8/9, 10.1 on RHEL 10). The claim that EPEL is required is gone: tomcat and the three webapp packages come from AppStream on Rocky 8, 9 and 10.
  • COMPATIBILITY.md: RHEL 10 marked as x.

Testing

  • The role runs on a Rocky 10 host with Tomcat 10.1.
  • The 10.1 templates were diffed against the files extracted from the Rocky 10 RPM; the remaining differences are the ones listed above, plus the role's variables.
  • The package source (AppStream, no EPEL) was checked in Rocky 8, 9 and 10 containers.
  • The XML templates are well-formed.
  • pre-commit is clean on the changed files.
  • ansible-lint on the role and playbook reports one failure, var-naming[no-role-prefix] for tomcat__installed_version, which main reports as well.

Not covered

  • There is no Molecule scenario for apache_tomcat yet.
  • The 9.0 templates are unchanged. They may deserve the same review against the RHEL 8/9 package.
  • playbooks/apache_tomcat.yml still enables EPEL and CRB, although the role needs neither.
  • Older deviations from CONTRIBUTING.md, left for a later PR: no meta/argument_specs.yml, 'Combined Users:' task name, tomcat__installed_version without the __apache_tomcat__ prefix, bare variables without | bool, ansible.builtin.systemd instead of service, no rpmnew/rpmsave cleanup, no restart after a change to /etc/sysconfig/tomcat, undocumented deviations from the package defaults (compression, CATALINA_OPTS, AJP address), and non-RFC-5737 example IPs in the README.

@danyalberchtoldlf
danyalberchtoldlf marked this pull request as ready for review September 30, 2026 14:00
…apps abort and manager upload defaults

The host-manager context.xml used the docs allow list instead of apache_tomcat__webapps_manager_context_xml_allow.

The host-manager context.xml was deployed whenever the ROOT webapp was installed, although host-manager ships with tomcat-admin-webapps, so apache_tomcat__skip_admin_webapps: true made the template task fail on the missing directory.

apache_tomcat__webapps_manager_web_xml_max_file_size and apache_tomcat__webapps_manager_web_xml_max_request_size had no default, so the run aborted unless the inventory set them. The README already documented 52428800.
…anager web.xml, refresh 9.0 templates

Declare every documented variable in meta/argument_specs.yml and add the env_* defaults the README already documented.

Tag the version detection always, guarded for hosts without tomcat, and rename the fact to __apache_tomcat__installed_version. Use ansible.builtin.service, apply | bool to bare variables and drop the trailing colon from the debug task name.

Split manager/WEB-INF/web.xml into 9.0 and 10.1 templates taken from the shipped files, since 10.1 uses the Jakarta EE 6.0 schema. The META-INF/context.xml files are identical in both versions and stay shared.

Bring 9.0-server.xml and 9.0-logging.properties in line with tomcat-9.0.120 on Rocky 8 and 9, which also replaces the deprecated compressableMimeType (with a trailing space in the value) by compressibleMimeType.

Point the README links to the Tomcat 10.1 documentation.
…tils dependencies

tomcat and its Java dependency come from AppStream on RHEL 8, 9 and 10 (tomcat-9.0.120 on Rocky 8 and 9, tomcat-10.1.49 on Rocky 10); EPEL does not ship tomcat at all. CRB was only enabled because repo_epel needs it. apache_tomcat__skip_repo_baseos is therefore gone.

policycoreutils goes as well: the role runs no SELinux module (no seport, sefcontext or seboolean task), so neither the playbook entry nor the README's Dependent Roles and Requirements sections, which pointed at policycoreutils and the selinux playbook, had a reason to exist.
install runs the playbook on Rocky 8, 9 and 10, which covers both template sets (9.0 and 10.1). verify.yml reads the connector settings back from the running Tomcat through the manager JMX proxy, checks the login of the configured user (and that a wrong password is refused), that tomcat-users.xml holds no clear-text password on 10.1, and from the hypervisor that host-manager and docs each honour their own allow list.

foreign_tags runs the playbook with another role's tag against hosts without tomcat, since the version detection is tagged always.
… hashes

Both template sets configure a SecretKeyCredentialHandler with PBKDF2WithHmacSHA512 and 210000 iterations, and tomcat-users.xml stores <hex salt>$<iterations>$<hex key> instead of the clear-text password (9.0) or an unsalted sha-256 digest (10.1). The salt is derived from inventory_hostname and the username, so the file stays stable across runs.

The new linuxfabrik.lfops.tomcat_pbkdf2 filter computes the stored form. Its unit tests re-derive hashes that Tomcat's own RealmBase produced with tomcat-9.0.120 (OpenJDK 8, Rocky 8) and tomcat-10.1.49 (OpenJDK 21, Rocky 10), including a non-ASCII password, which proves the UTF-8 encoding of the password.

The 9.0 user lines use the username attribute like 10.1; MemoryUserDatabase of 9.0.120 reads it before the legacy name attribute.
- move the AJP and log rotation notes from the intro to "How the Role Behaves", and say that the AJP connector only listens on 127.0.0.1
- move apache_tomcat__users__* from Mandatory to Optional with `Default: []`, since the role runs without users; keep the manager role descriptions with it and drop the `admin` and `manager` roles, which Tomcat no longer has since 7
- document that the allow regexes are appended to the localhost pattern and must start with `|`, and when they are mandatory
- use RFC 5737 ranges in the examples (`192.2.0.x` was a typo, `10.80.32.x` is not a documentation range), sort the optional example
- use the `Type: String. One of ...` form for apache_tomcat__service_state
- set apache_tomcat__logrotate in defaults/main.yml like example__logrotate, instead of falling back to logrotate__rotate inside the template
- drop the d() fallbacks and `is defined` checks for variables that defaults/main.yml always sets; the rendered files stay byte-identical, so their timestamps are not bumped
- drop the stray "#" in front of the timestamp inside the XML comment of the docs and manager context.xml templates
- name the template tasks after their destination and the version assert like roles/example
- flush the handlers at the end of the role, so Tomcat already runs its new configuration when a later role in the play uses it
…at:logrotate tag

CONTRIBUTING.md has `role_name:logrotate` in the controlled tag vocabulary, and keycloak, librenms, php and shiny_server use it. The logrotate task leaves apache_tomcat:configure, which now only covers the Tomcat configuration itself.

BREAKING CHANGE: `--tags apache_tomcat:configure` no longer deploys /etc/logrotate.d/tomcat; use `--tags apache_tomcat:logrotate`.
…hanges

The task deploying /etc/sysconfig/tomcat notified no handler, so a changed apache_tomcat__env_xms, apache_tomcat__env_xmx or apache_tomcat__env_xx was written to disk but the running JVM kept its old heap and -XX settings until something else restarted it.

The install scenario sets -Xms256M and -Xmx512M and asserts both on the command line of the running JVM, which proves the chain from group_vars through /etc/sysconfig/tomcat to the JVM. Both values change together, since the JVM refuses to start with -Xms above -Xmx. Verified on Rocky 8, 9 and 10.
… config files

The tomcat package marks /etc/sysconfig/tomcat and the files under /etc/tomcat as %config(noreplace), so a package update leaves its own version as .rpmnew next to the files the role deploys. Include shared/remove-rpmnew-rpmsave.yml for each of them, as CONTRIBUTING.md asks.

The webapp META-INF/context.xml and WEB-INF/web.xml files are plain package files, never %config, so they get no .rpmnew and are left out. Verified with `rpm -qc` against tomcat 9.0.120 on Rocky 9 and tomcat 10.1.49 on Rocky 10.
…ebapp is skipped

apache_tomcat__webapps_docs_context_xml_allow and apache_tomcat__webapps_manager_context_xml_allow are mandatory while the webapp they protect is installed. argument_specs cannot express a requirement that depends on another variable, so a missing value failed deep inside the context.xml template on an undefined variable. Assert both at the start of the role instead, tagged always as CONTRIBUTING.md asks for inventory validation, and name the variable and the way out.

The foreign_tags scenario sets both variables now, since its run limited to another role's tag still runs the asserts.
@danyalberchtoldlf
danyalberchtoldlf merged commit 24a5974 into main Oct 15, 2026
13 checks passed
@danyalberchtoldlf
danyalberchtoldlf deleted the feat/tomcat-10.1 branch October 15, 2026 19:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants