From dd070b192575265747bb3142c7f3b5f10d3a8ebc Mon Sep 17 00:00:00 2001 From: Liraz Siri Date: Mon, 24 Aug 2026 12:05:04 +0000 Subject: [PATCH 1/9] Port standalone Tomcat to Debian Trixie Move the packaged Java runtime to OpenJDK 21 while retaining Debian Tomcat 10.1 and its normal APT update path. Keep the standalone direct connectors and correct the bundled documentation link for the packaged Tomcat generation. Add functional acceptance for normal service startup, HTTP and HTTPS, generated manager credentials, a complete WAR deploy/read/undeploy flow, MariaDB, Webmin, and signed Trixie package candidates. Document the README crosswalk, inherited Core evidence, and the harmless legacy authbind compatibility files. Verified with a disposable Trixie package probe, git diff --check, and Bash syntax checks. The exact appliance acceptance remains the next gate. --- README.rst | 16 +++--- TESTING.md | 62 ++++++++++++++++++++++++ changelog | 12 +++++ conf.d/main | 1 + plan/main | 4 +- tests/v19.sh | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 220 insertions(+), 9 deletions(-) create mode 100644 TESTING.md create mode 100755 tests/v19.sh diff --git a/README.rst b/README.rst index 5b5da7c..86dfcd8 100644 --- a/README.rst +++ b/README.rst @@ -8,7 +8,7 @@ numerous large-scale, mission-critical web applications across a diverse range of industries and organizations. This appliance configures Tomcat as a standalone application server -(I.e., without an external web server). A `Tomcat on Apache Appliance`_ +(that is, without an external web server). A `Tomcat on Apache Appliance`_ is also available for integrations requiring a fully-featured web server. @@ -17,17 +17,19 @@ and on top of that: - Tomcat configurations: - - Installed from package management. - - Using OpenJDK Java runtime. + - Tomcat 10.1 installed from Debian package management. + - Using the OpenJDK 21 Java runtime from Debian. - Web applications in /var/lib/tomcat10/webapps. - Includes TurnKey web control panel. - Created Tomcat admin/manager roles and admin user. - - Bind Tomcat HTTP connector to port 80 (default: 8080). - - Bind SSL interface to port 443 (default: 8443). + - Tomcat Manager at /manager/html and Virtual Host Manager at + /host-manager/html. + - Binds the Tomcat HTTP connector directly to port 80 (default: 8080). + - Binds the Tomcat SSL interface directly to port 443 (default: 8443). - Disabled AJP connector on port 8009 (security). - Tomcat and Java environment variables configuration system wide. -- Includes MySQL. +- Includes MariaDB, a MySQL-compatible database server. - SSL support out of the box. - Postfix MTA (bound to localhost) to allow sending of email from web applications (e.g., password recovery). @@ -35,7 +37,7 @@ and on top of that: Credentials *(passwords set at first boot)* ------------------------------------------- -- Webmin, SSH, MySQL: username **root** +- Webmin, SSH, MariaDB: username **root** - Tomcat administration applications: username **admin** diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 0000000..68928e9 --- /dev/null +++ b/TESTING.md @@ -0,0 +1,62 @@ +# Tomcat 19.0 acceptance + +## Source decision + +Tomcat 19.0 uses Debian 13 Trixie packages for Tomcat 10.1, its manager +applications, OpenJDK 21 and MariaDB. Webmin and its MariaDB module continue to +come from the signed TurnKey Trixie repository. The complete documented stack +is maintained through APT, so this appliance does not need an upstream package +source or a separate updater. + +The standalone appliance binds Tomcat directly to ports 80 and 443. It does +not use the Apache reverse proxy provided by the separate Tomcat on Apache +appliance. + +## Acceptance command + +```sh +/sandboxed-git/turnkey/tools/test-v19-appliance tomcat \ + --source /home/agent/.local/worktrees/turnkey-apps/tomcat/wish-tomcat-v19-trixie +``` + +## README crosswalk + +| README contract | Focused check | Required result | +| --- | --- | --- | +| Tomcat 10.1 and OpenJDK 21 come from Debian | Query packages, versions and binary ownership | Versions match Trixie packages | +| Standalone HTTP and HTTPS on ports 80 and 443 | Request the landing page through both connectors | Both responses identify TurnKey Tomcat | +| Manager and Virtual Host Manager use the firstboot admin account | Check unauthenticated denial, then authenticate to both applications and the text manager | Anonymous access is denied and the generated password succeeds | +| Applications deploy under `/var/lib/tomcat10/webapps` | Upload a minimal JSP WAR through the manager, request it through HTTP and HTTPS, then undeploy it | Deployment, both readbacks and removal succeed | +| AJP on port 8009 is disabled | Inspect runtime listeners | No listener exists on port 8009 | +| MariaDB is available for applications | Create a temporary database and table, write and read a row, then remove them | The database roundtrip succeeds | +| Webmin is the documented system management surface | Request its HTTPS endpoint and verify the MariaDB module package | Webmin responds and the module is installed | +| APT maintains the packaged stack | Refresh metadata and inspect candidates for identity-defining packages | Signed Trixie metadata is accepted, candidates exist and installed versions remain unchanged | +| Root Webmin and SSH credentials are inherited from Core | Cite the unchanged Core layer | Core 19 passed at source `24c82ee3540ce545422742b0e28ba6b687c53ec2` | + +## Updater check + +`tests/v19.sh` runs `apt-get update` and checks candidates for `tomcat10`, +`tomcat10-admin`, `openjdk-21-jre-headless` and `mariadb-server`. It confirms +that the refresh does not change installed versions and that no Bookworm +source remains. + +## Core evidence and limitations + +Core 19 run `20260824t010251z-1634-32241` passed normal init, multi-user, SSH, +cron, Trixie identity and the signed APT updater at source +`24c82ee3540ce545422742b0e28ba6b687c53ec2`. + +Docker acceptance does not exercise the installer, kernel, bootloader or +physical hardware. Tomcat adds no behavior at those boundaries, so the Core +19 result supplies the inherited evidence. + +## Accepted run + +Pending the exact acceptance command above. + +## Deferred minor issues + +- The package plan still includes `authbind` and its historical port files. + Trixie's Tomcat systemd unit grants only the low-port capability needed for + ports 80 and 443, so Tomcat no longer relies on authbind. The compatibility + files are harmless and remain for v19.0. diff --git a/changelog b/changelog index 000da43..8033a87 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,15 @@ +turnkey-tomcat-19.0 (1) turnkey; urgency=low + + * Update the standalone appliance for Debian 13 Trixie packages, including + Tomcat 10.1 and OpenJDK 21. + + * Update the bundled Tomcat documentation link for the packaged release. + + * Add focused runtime acceptance for the Tomcat managers, direct HTTP and + HTTPS connectors, WAR deployment, MariaDB, Webmin and APT updates. + + -- TurnKey Linux Developers Mon, 24 Aug 2026 00:00:00 +0000 + turnkey-tomcat-18.0 (1) turnkey; urgency=low * Updated all relevant Debian packages to Bookworm/12 versions; including diff --git a/conf.d/main b/conf.d/main index 1f07bae..cb737ea 100755 --- a/conf.d/main +++ b/conf.d/main @@ -13,6 +13,7 @@ done sed -i "s|HOSTNAME_DESC|Tomcat|g" $WEBROOT/index.jsp sed -i "s|HOSTNAME|tomcat|g" $WEBROOT/index.jsp +sed -i "s|tomcat-9.0-doc|tomcat-10.1-doc|g" $WEBROOT/index.jsp setup_authbind() { touch /etc/authbind/byport/$1 diff --git a/plan/main b/plan/main index d92142e..95c8127 100644 --- a/plan/main +++ b/plan/main @@ -5,8 +5,8 @@ ant authbind /* Allows non-root programs to bind() to low ports */ -openjdk-17-jdk-headless -openjdk-17-jre-headless +openjdk-21-jdk-headless +openjdk-21-jre-headless default-mysql-server libmariadb-java diff --git a/tests/v19.sh b/tests/v19.sh new file mode 100755 index 0000000..9d71d40 --- /dev/null +++ b/tests/v19.sh @@ -0,0 +1,134 @@ +#!/bin/bash +set -Eeuo pipefail +umask 077 + +result=${TKL_TEST_RESULT:?TKL_TEST_RESULT is required} +password=${TKL_TEST_APP_PASS:?TKL_TEST_APP_PASS is required} +manager=http://127.0.0.1/manager/text +context=/turnkey-v19-test +war_root=$(mktemp -d /tmp/tkl-tomcat-war.XXXXXX) +war=/tmp/tkl-tomcat-v19.$$.war +response=/tmp/tkl-tomcat-response.$$ +policy=/tmp/tkl-tomcat-policy.$$ +database=tkl_tomcat_v19_acceptance +deployed=false +database_created=false + +cleanup() { + if $deployed; then + curl --fail --silent --show-error --user "admin:$password" \ + "$manager/undeploy?path=$context" >/dev/null || true + fi + if $database_created; then + mariadb --execute "DROP DATABASE IF EXISTS $database" || true + fi + rm -rf -- "$war_root" + rm -f -- "$war" "$response" "$policy" +} +trap cleanup EXIT + +systemctl --quiet is-active tomcat10.service mariadb.service multi-user.target +systemctl --quiet is-enabled tomcat10.service mariadb.service + +tomcat_package=$(dpkg-query -W -f='${Version}' tomcat10) +tomcat_admin_package=$(dpkg-query -W -f='${Version}' tomcat10-admin) +java_package=$(dpkg-query -W -f='${Version}' openjdk-21-jre-headless) +mariadb_package=$(dpkg-query -W -f='${Version}' mariadb-server) +java_version=$(java -version 2>&1 | head -n 1) +tomcat_version=$(/usr/share/tomcat10/bin/version.sh 2>&1 | \ + awk -F': ' '/Server number/ {print $2}') + +grep -q '^10\.1\.' <<<"$tomcat_version" +grep -q 'version "21\.' <<<"$java_version" +java_binary=$(readlink -f "$(command -v java)") +dpkg-query -S /usr/share/tomcat10/bin/catalina.sh "$java_binary" >/dev/null +test -d /var/lib/tomcat10/webapps/manager +test -d /var/lib/tomcat10/webapps/host-manager +test -d /var/lib/tomcat10/webapps/docs +test -s /etc/tomcat10/cert.p12 +grep -q 'CATALINA_HOME="/usr/share/tomcat10"' /etc/environment +grep -q 'JAVA_HOME="/usr/lib/jvm/java-21-openjdk-amd64"' /etc/environment +! ss -ltnH 'sport = :8009' | grep -q . + +curl --fail --silent --show-error http://127.0.0.1/ >"$response" +grep -q 'TurnKey Tomcat' "$response" +grep -q 'href="/manager/html"' "$response" +grep -q 'href="/host-manager/html"' "$response" +grep -q 'https://127.0.0.1:12321' "$response" +curl --insecure --fail --silent --show-error \ + https://127.0.0.1/ >"$response" +grep -q 'TurnKey Tomcat' "$response" + +test "$(curl --silent --output /dev/null --write-out '%{http_code}' \ + http://127.0.0.1/manager/html)" = 401 +curl --fail --silent --show-error --user "admin:$password" \ + http://127.0.0.1/manager/html >"$response" +grep -q 'Tomcat Web Application Manager' "$response" +curl --fail --silent --show-error --user "admin:$password" \ + http://127.0.0.1/host-manager/html >"$response" +grep -q 'Tomcat Virtual Host Manager' "$response" +curl --fail --silent --show-error --user "admin:$password" \ + "$manager/serverinfo" >"$response" +grep -q '^OK - Server version:' "$response" +grep -q 'username="admin"' /etc/tomcat10/tomcat-users.xml +! grep -q 'password="turnkey"' /etc/tomcat10/tomcat-users.xml + +cat >"$war_root/index.jsp" <<'EOF' +<%@ page contentType="text/plain" %>turnkey-tomcat-v19-deploy-ok +EOF +jar --create --file "$war" -C "$war_root" . +curl --fail --silent --show-error --user "admin:$password" \ + --upload-file "$war" \ + "$manager/deploy?path=$context&update=true" >"$response" +grep -q '^OK - Deployed application at context path' "$response" +deployed=true +curl --retry 5 --retry-delay 1 --fail --silent --show-error \ + "http://127.0.0.1$context/" >"$response" +grep -Fxq 'turnkey-tomcat-v19-deploy-ok' "$response" +curl --insecure --fail --silent --show-error \ + "https://127.0.0.1$context/" >"$response" +grep -Fxq 'turnkey-tomcat-v19-deploy-ok' "$response" +curl --fail --silent --show-error --user "admin:$password" \ + "$manager/undeploy?path=$context" >"$response" +grep -q '^OK - Undeployed application at context path' "$response" +deployed=false +test "$(curl --silent --output /dev/null --write-out '%{http_code}' \ + "http://127.0.0.1$context/")" = 404 + +dpkg-query -W webmin-mysql >/dev/null +curl --insecure --fail --silent --show-error --head \ + https://127.0.0.1:12321/ >/dev/null + +mariadb --execute "CREATE DATABASE $database" +database_created=true +mariadb "$database" --execute \ + 'CREATE TABLE probe (value VARCHAR(32)); INSERT INTO probe VALUES ("database-ok")' +mariadb --batch --skip-column-names "$database" \ + --execute 'SELECT value FROM probe' | grep -Fxq 'database-ok' +mariadb "$database" --execute 'DELETE FROM probe; DROP TABLE probe' +mariadb --execute "DROP DATABASE $database" +database_created=false + +before="$tomcat_package|$tomcat_admin_package|$java_package|$mariadb_package" +apt-get update >/dev/null +for package in tomcat10 tomcat10-admin openjdk-21-jre-headless mariadb-server; do + apt-cache policy "$package" >"$policy" + candidate=$(awk '/Candidate:/ {print $2}' "$policy") + test -n "$candidate" + test "$candidate" != '(none)' + grep -Eq 'trixie|deb13' "$policy" +done +after="$(dpkg-query -W -f='${Version}' tomcat10)|$(dpkg-query -W -f='${Version}' tomcat10-admin)|$(dpkg-query -W -f='${Version}' openjdk-21-jre-headless)|$(dpkg-query -W -f='${Version}' mariadb-server)" +test "$after" = "$before" +grep -Rqs '^Suites: trixie' /etc/apt/sources.list.d +! grep -Rqi bookworm /etc/apt/sources.list.d + +cat >"$result" < Date: Mon, 24 Aug 2026 12:24:47 +0000 Subject: [PATCH 2/9] Repair the generated Tomcat cipher attribute The shared Trixie cipher substitution preserved its quoted placeholder after inserting the selected list. That produced malformed server.xml, so normal boot left tomcat10.service failed before any HTTP flow could run. Normalize only the invalid suffix after shared configuration. This keeps the selected shared cipher list intact and restores valid Tomcat XML without changing the TLS policy. Verified by reproducing the shared substitution against the shipped server.xml, applying the normalization, parsing the result with Python XML tooling, and rerunning Bash syntax and diff checks. Exact acceptance loop 1 evidence is retained under run 20260824t120525z-6979-20860. --- TESTING.md | 5 +++++ conf.d/main | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/TESTING.md b/TESTING.md index 68928e9..4f21c6e 100644 --- a/TESTING.md +++ b/TESTING.md @@ -12,6 +12,11 @@ The standalone appliance binds Tomcat directly to ports 80 and 443. It does not use the Apache reverse proxy provided by the separate Tomcat on Apache appliance. +The shared v19 cipher substitution leaves its quoted placeholder attached to +the selected Tomcat cipher list. The appliance removes only that invalid XML +suffix after shared configuration, preserving the shared Trixie cipher +selection. + ## Acceptance command ```sh diff --git a/conf.d/main b/conf.d/main index cb737ea..ccabd03 100755 --- a/conf.d/main +++ b/conf.d/main @@ -15,6 +15,10 @@ sed -i "s|HOSTNAME_DESC|Tomcat|g" $WEBROOT/index.jsp sed -i "s|HOSTNAME|tomcat|g" $WEBROOT/index.jsp sed -i "s|tomcat-9.0-doc|tomcat-10.1-doc|g" $WEBROOT/index.jsp +# The shared cipher substitution leaves its quoted placeholder behind. +# Preserve the selected Trixie cipher list and remove that invalid XML suffix. +sed -i 's|""ZZ_SSL_CIPHERS"|"|' /etc/tomcat10/server.xml + setup_authbind() { touch /etc/authbind/byport/$1 chmod 500 /etc/authbind/byport/$1 From 283334a3bf20f6fedc2eba406429b90736ffaffe Mon Sep 17 00:00:00 2001 From: Liraz Siri Date: Mon, 24 Aug 2026 12:40:56 +0000 Subject: [PATCH 3/9] Test Debian Tomcat deployment paths Debian deploys the manager, host manager, and documentation from package directories under /usr/share through context descriptors. The first runtime test incorrectly expected those package payloads in the writable application directory and exited before exercising the documented flow. Check the actual Debian-owned paths and allow the initial landing request to wait while Tomcat completes normal ROOT deployment. Subsequent requests remain immediate, and the WAR flow still proves the writable webapps deployment contract. Verified the three package paths in a disposable Trixie container, then reran Bash syntax and diff checks. Exact acceptance loop 2 proved normal boot and active Tomcat before this focused test correction. --- tests/v19.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/v19.sh b/tests/v19.sh index 9d71d40..e6b2c6d 100755 --- a/tests/v19.sh +++ b/tests/v19.sh @@ -42,15 +42,16 @@ grep -q '^10\.1\.' <<<"$tomcat_version" grep -q 'version "21\.' <<<"$java_version" java_binary=$(readlink -f "$(command -v java)") dpkg-query -S /usr/share/tomcat10/bin/catalina.sh "$java_binary" >/dev/null -test -d /var/lib/tomcat10/webapps/manager -test -d /var/lib/tomcat10/webapps/host-manager -test -d /var/lib/tomcat10/webapps/docs +test -d /usr/share/tomcat10-admin/manager +test -d /usr/share/tomcat10-admin/host-manager +test -d /usr/share/tomcat10-docs/docs test -s /etc/tomcat10/cert.p12 grep -q 'CATALINA_HOME="/usr/share/tomcat10"' /etc/environment grep -q 'JAVA_HOME="/usr/lib/jvm/java-21-openjdk-amd64"' /etc/environment ! ss -ltnH 'sport = :8009' | grep -q . -curl --fail --silent --show-error http://127.0.0.1/ >"$response" +curl --retry 15 --retry-all-errors --retry-delay 1 \ + --fail --silent --show-error http://127.0.0.1/ >"$response" grep -q 'TurnKey Tomcat' "$response" grep -q 'href="/manager/html"' "$response" grep -q 'href="/host-manager/html"' "$response" From be3cdede6149dfc1d4b737384182a5c732b65c8f Mon Sep 17 00:00:00 2001 From: Liraz Siri Date: Mon, 24 Aug 2026 13:02:40 +0000 Subject: [PATCH 4/9] Match the Tomcat manager server-info response Tomcat 10.1 returns an authenticated text-manager status line of `OK - Server info`; the acceptance test expected a different label and stopped after otherwise successful manager authentication. Assert the actual status line and the following Tomcat 10.1 version field. A disposable Trixie runtime proved the anonymous denial, both authenticated manager pages, server-info output, and the complete WAR deploy, read, undeploy, and 404 flow before this correction. --- tests/v19.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/v19.sh b/tests/v19.sh index e6b2c6d..48e0859 100755 --- a/tests/v19.sh +++ b/tests/v19.sh @@ -70,7 +70,8 @@ curl --fail --silent --show-error --user "admin:$password" \ grep -q 'Tomcat Virtual Host Manager' "$response" curl --fail --silent --show-error --user "admin:$password" \ "$manager/serverinfo" >"$response" -grep -q '^OK - Server version:' "$response" +grep -Fxq 'OK - Server info' "$response" +grep -q '^Tomcat Version: \[Apache Tomcat/10\.1\.' "$response" grep -q 'username="admin"' /etc/tomcat10/tomcat-users.xml ! grep -q 'password="turnkey"' /etc/tomcat10/tomcat-users.xml From ef9acd8ea4dc8d70737fd60cbfc077bda7bd69a0 Mon Sep 17 00:00:00 2001 From: Liraz Siri Date: Mon, 24 Aug 2026 13:27:37 +0000 Subject: [PATCH 5/9] Use the initialized MariaDB root credential TurnKey firstboot assigns the MariaDB root password from the database credential, so the acceptance roundtrip could not use Debian package-time passwordless access after normal initialization. Authenticate database creation, write, read, deletion, and failure cleanup with `TKL_TEST_DB_PASS`, matching the established v19 MariaDB appliance tests. Tomcat manager authentication and the full WAR lifecycle were already proven separately as the unprivileged service account. Verified with Bash syntax and diff checks against the retained loop 4 evidence from run 20260824t130248z-2552-25810. --- tests/v19.sh | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/v19.sh b/tests/v19.sh index 48e0859..258b199 100755 --- a/tests/v19.sh +++ b/tests/v19.sh @@ -4,6 +4,7 @@ umask 077 result=${TKL_TEST_RESULT:?TKL_TEST_RESULT is required} password=${TKL_TEST_APP_PASS:?TKL_TEST_APP_PASS is required} +db_password=${TKL_TEST_DB_PASS:?TKL_TEST_DB_PASS is required} manager=http://127.0.0.1/manager/text context=/turnkey-v19-test war_root=$(mktemp -d /tmp/tkl-tomcat-war.XXXXXX) @@ -20,7 +21,8 @@ cleanup() { "$manager/undeploy?path=$context" >/dev/null || true fi if $database_created; then - mariadb --execute "DROP DATABASE IF EXISTS $database" || true + mariadb --user=root --password="$db_password" \ + --execute "DROP DATABASE IF EXISTS $database" || true fi rm -rf -- "$war_root" rm -f -- "$war" "$response" "$policy" @@ -101,14 +103,18 @@ dpkg-query -W webmin-mysql >/dev/null curl --insecure --fail --silent --show-error --head \ https://127.0.0.1:12321/ >/dev/null -mariadb --execute "CREATE DATABASE $database" +mariadb --user=root --password="$db_password" \ + --execute "CREATE DATABASE $database" database_created=true -mariadb "$database" --execute \ +mariadb --user=root --password="$db_password" "$database" --execute \ 'CREATE TABLE probe (value VARCHAR(32)); INSERT INTO probe VALUES ("database-ok")' -mariadb --batch --skip-column-names "$database" \ +mariadb --user=root --password="$db_password" --batch --skip-column-names \ + "$database" \ --execute 'SELECT value FROM probe' | grep -Fxq 'database-ok' -mariadb "$database" --execute 'DELETE FROM probe; DROP TABLE probe' -mariadb --execute "DROP DATABASE $database" +mariadb --user=root --password="$db_password" "$database" \ + --execute 'DELETE FROM probe; DROP TABLE probe' +mariadb --user=root --password="$db_password" \ + --execute "DROP DATABASE $database" database_created=false before="$tomcat_package|$tomcat_admin_package|$java_package|$mariadb_package" From 5d73346c3dd53e464f3c335c5080639fa345cf27 Mon Sep 17 00:00:00 2001 From: Liraz Siri Date: Wed, 26 Aug 2026 09:45:56 +0000 Subject: [PATCH 6/9] Report the failing Tomcat acceptance command The exact appliance run could exit from an assertion without identifying which ordinary acceptance check failed. Record the failing line, status, and shell-quoted command while preserving the existing cleanup and avoiding xtrace output that could expose credentials. Verified with bash -n and git diff --check. --- tests/v19.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/v19.sh b/tests/v19.sh index 258b199..9fcbc99 100755 --- a/tests/v19.sh +++ b/tests/v19.sh @@ -15,6 +15,12 @@ database=tkl_tomcat_v19_acceptance deployed=false database_created=false +report_error() { + printf 'test_failure line=%s status=%s command=%q\n' \ + "$1" "$2" "$3" >&2 + exit "$2" +} + cleanup() { if $deployed; then curl --fail --silent --show-error --user "admin:$password" \ @@ -27,6 +33,7 @@ cleanup() { rm -rf -- "$war_root" rm -f -- "$war" "$response" "$policy" } +trap 'report_error "$LINENO" "$?" "$BASH_COMMAND"' ERR trap cleanup EXIT systemctl --quiet is-active tomcat10.service mariadb.service multi-user.target From f20087f4cde2e079c9c4fea1bea0a1edeb2a9f43 Mon Sep 17 00:00:00 2001 From: Liraz Siri Date: Wed, 26 Aug 2026 09:56:12 +0000 Subject: [PATCH 7/9] Match the Tomcat version output label Debian Trixie Tomcat 10.1 reports its numeric release under `Server version number`; the acceptance parser still searched for the older shortened label and produced an empty version. Parse the actual label while retaining the existing 10.1 assertion. The authoritative runtime log reported Tomcat 10.1.55.0 before this test-only failure. --- tests/v19.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/v19.sh b/tests/v19.sh index 9fcbc99..46e1636 100755 --- a/tests/v19.sh +++ b/tests/v19.sh @@ -45,7 +45,7 @@ java_package=$(dpkg-query -W -f='${Version}' openjdk-21-jre-headless) mariadb_package=$(dpkg-query -W -f='${Version}' mariadb-server) java_version=$(java -version 2>&1 | head -n 1) tomcat_version=$(/usr/share/tomcat10/bin/version.sh 2>&1 | \ - awk -F': ' '/Server number/ {print $2}') + awk -F': ' '/Server version number/ {print $2}') grep -q '^10\.1\.' <<<"$tomcat_version" grep -q 'version "21\.' <<<"$java_version" From 7323dd61d1fe75d56afc7831124985aefe278739 Mon Sep 17 00:00:00 2001 From: Liraz Siri Date: Wed, 26 Aug 2026 10:06:51 +0000 Subject: [PATCH 8/9] Parse padded Tomcat version output The Debian Tomcat wrapper reports `Server number:` with aligned whitespace after the colon. Splitting on one literal space left a leading space and caused the anchored 10.1 assertion to fail even though the runtime was Tomcat 10.1.55. Accept the wrapper padding while keeping the exact label and version assertion. Verified against direct Debian Trixie version.sh output, bash syntax, and git diff checks. --- tests/v19.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/v19.sh b/tests/v19.sh index 46e1636..07f50bd 100755 --- a/tests/v19.sh +++ b/tests/v19.sh @@ -45,7 +45,7 @@ java_package=$(dpkg-query -W -f='${Version}' openjdk-21-jre-headless) mariadb_package=$(dpkg-query -W -f='${Version}' mariadb-server) java_version=$(java -version 2>&1 | head -n 1) tomcat_version=$(/usr/share/tomcat10/bin/version.sh 2>&1 | \ - awk -F': ' '/Server version number/ {print $2}') + awk -F':[[:space:]]*' '/^Server number:/ {print $2}') grep -q '^10\.1\.' <<<"$tomcat_version" grep -q 'version "21\.' <<<"$java_version" From e2ae70e038a92961c46a03330ac164ae5b7cfc02 Mon Sep 17 00:00:00 2001 From: Liraz Siri Date: Wed, 26 Aug 2026 10:23:22 +0000 Subject: [PATCH 9/9] Record the accepted Tomcat 19 run Replace the stale pending status with the retained exact acceptance evidence required for release review. The new report ties the tested source and run to the README primary flows, signed APT updater checks, known Docker limits, and deferred compatibility note without changing the appliance or its tests. Verified the retained report checksum, required report fields, Markdown link target, absence of stale pending language, and staged diff formatting. --- TESTING.md | 5 +++- docs/v19.0-testing.md | 67 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 docs/v19.0-testing.md diff --git a/TESTING.md b/TESTING.md index 4f21c6e..46a81f7 100644 --- a/TESTING.md +++ b/TESTING.md @@ -57,7 +57,10 @@ physical hardware. Tomcat adds no behavior at those boundaries, so the Core ## Accepted run -Pending the exact acceptance command above. +The exact acceptance command passed at source commit +`7323dd61d1fe75d56afc7831124985aefe278739`. Run identity, appliance +evidence and known limitations are recorded in +[`docs/v19.0-testing.md`](docs/v19.0-testing.md). ## Deferred minor issues diff --git a/docs/v19.0-testing.md b/docs/v19.0-testing.md new file mode 100644 index 0000000..8324fc0 --- /dev/null +++ b/docs/v19.0-testing.md @@ -0,0 +1,67 @@ +# Tomcat 19.0 test report + +## Accepted candidate + +- Source commit: `7323dd61d1fe75d56afc7831124985aefe278739` +- Run: `20260826t100659z-2340-26438` +- Verdict: `PASS` +- Retained report SHA-256: + `12f5386f7d4fa14237ba3e69db5924abd4b64bda72f971bcc27e831d296fff85` +- Source archive SHA-256: + `20d40f45a0b9bb8f379b108a9aaace6705c7980ca66a03056267a75dfaaef1c1` + +The accepted candidate was built from the recorded source archive, imported +into Docker, booted through the normal systemd and firstboot path, and tested +with the appliance-owned `tests/v19.sh` acceptance script. + +## Exact command + +```sh +/sandboxed-git/turnkey/tools/test-v19-appliance tomcat \ + --source /home/agent/.local/worktrees/turnkey-apps/tomcat/wish-tomcat-v19-trixie +``` + +## Source and updater evidence + +Tomcat 10.1, OpenJDK 21 and MariaDB came from Debian 13 Trixie APT +repositories. Webmin came from the TurnKey Trixie APT repository. The +accepted runtime reported: + +- `tomcat10` and `tomcat10-admin` version `10.1.55-1~deb13u1`; +- OpenJDK package `21.0.12.1+1-1~deb13u1`; +- `mariadb-server` version `1:11.8.6-0+deb13u1`. + +The acceptance script refreshed signed repository metadata with +`apt-get update`, then checked eligible Trixie candidates for `tomcat10`, +`tomcat10-admin`, `openjdk-21-jre-headless` and `mariadb-server`. Installed +versions remained unchanged. Configured Deb822 sources named Trixie, no +Bookworm source remained, and APT accepted the configured repository keyrings. + +## README primary-flow crosswalk + +| README contract | Accepted evidence | +| --- | --- | +| Tomcat 10.1 and OpenJDK 21 from Debian | Package versions, runtime versions and Debian ownership of the Tomcat and Java binaries were checked. | +| Standalone HTTP and HTTPS | The TurnKey Tomcat landing page was fetched directly over ports 80 and 443. | +| Firstboot administrator credentials | Anonymous manager access returned 401. The generated `admin` credential authenticated to Manager, Virtual Host Manager and the text manager API. The historical default password was absent. | +| Deploy applications under `/var/lib/tomcat10/webapps` | A temporary JSP WAR was deployed through Manager, read over HTTP and HTTPS, undeployed, then confirmed absent with HTTP 404. | +| AJP is disabled | No listener existed on port 8009. | +| MariaDB for applications | A temporary database and table were created, written, read and removed using the firstboot root credential. | +| Webmin administration | The Webmin HTTPS endpoint responded and the MariaDB module package was installed. | +| Managed package updates | Signed Trixie metadata refreshed, eligible candidates existed, and installed application versions remained stable. | +| Core administration | Core 19 acceptance run `20260824t010251z-1634-32241` at source `24c82ee3540ce545422742b0e28ba6b687c53ec2` supplies inherited SSH, root and common platform evidence. | + +## Limitations + +Docker runtime acceptance does not exercise the installer, kernel, bootloader +or physical hardware. Tomcat adds no appliance-specific behavior at those +boundaries, so the accepted Core 19 result supplies the inherited evidence. +The Docker kernel rejected the appliance hostname firstboot call and the +`systemd-sysctl` unit; the acceptance run checked the application services +and primary flows explicitly. + +## Deferred minor issues + +- The package plan retains `authbind` and its historical port files. Trixie's + Tomcat systemd unit supplies the low-port capability used for ports 80 and + 443, so the compatibility files do not affect the accepted runtime path.