Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
86a2ccd
Add manager2 webapp as a module
Sep 15, 2026
2a7d10c
Add remove upgrade protocol
Sep 15, 2026
2663205
Merge branch 'apache:main' into main
rmaucher Sep 15, 2026
36aa7f5
Add lifecycle operations to the component tree
rmaucher Sep 15, 2026
c3b807d
Add UpgradeProtocol configuration
rmaucher Sep 15, 2026
6b60aec
Fix some properties issues for resources
rmaucher Sep 15, 2026
daeea6d
Merge branch 'apache:main' into main
rmaucher Sep 15, 2026
cbe4336
Merge branch 'apache:main' into main
rmaucher Sep 16, 2026
b515e8b
Merge branch 'apache:main' into main
rmaucher Sep 16, 2026
4d34d87
Remove patch
rmaucher Sep 16, 2026
6463f5a
Improve webapp reactive behavior significantly
rmaucher Sep 16, 2026
4f93c52
Add download for logs
rmaucher Sep 16, 2026
1c2b804
Merge branch 'apache:main' into main
rmaucher Sep 16, 2026
f08b3d3
Update to use the new StoreConfig layout restoration
rmaucher Sep 16, 2026
aa4a835
Fold side bar to save space
rmaucher Sep 16, 2026
8748e71
UI tweaks and content optimizations
rmaucher Sep 17, 2026
a875bba
Add CPU and memory cards to the Monitoring page
rmaucher Sep 17, 2026
8601f9e
Full localization of missing items
rmaucher Sep 17, 2026
b621125
Merge branch 'apache:main' into main
rmaucher Sep 17, 2026
dab61a7
Merge branch 'apache:main' into main
rmaucher Sep 17, 2026
02a7db7
Update for new context flag to avoid saving to server.xml
rmaucher Sep 17, 2026
89ee4f2
Merge branch 'apache:main' into main
rmaucher Sep 17, 2026
960fee1
Add missing localization
rmaucher Sep 18, 2026
6843c98
Optimize instanceof
rmaucher Sep 18, 2026
553d6d0
Fix alignment when sidebar pops out
rmaucher Sep 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions java/org/apache/catalina/connector/Connector.java
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,13 @@ public String getExecutorName() {
public void addSslHostConfig(SSLHostConfig sslHostConfig) {
if (protocolHandler != null) {
protocolHandler.addSslHostConfig(sslHostConfig);
// A connector with at least one SSL host configuration is an
// SSL connector, whatever the path used to configure it
// (server.xml, the Manager or the embedded API).
if (protocolHandler instanceof AbstractHttp11Protocol http11
&& !http11.isSSLEnabled()) {
http11.setSSLEnabled(true);
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions java/org/apache/coyote/http11/AbstractHttp11Protocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,15 @@ public void addUpgradeProtocol(UpgradeProtocol upgradeProtocol) {
upgradeProtocols.add(upgradeProtocol);
}

/**
* Remove specified upgrade protocol.
* @param upgradeProtocol the upgrade protocol
* @return <code>true</code> if the protocol was removed
*/
public boolean removeUpgradeProtocol(UpgradeProtocol upgradeProtocol) {
return upgradeProtocols.remove(upgradeProtocol);
}

@Override
public UpgradeProtocol[] findUpgradeProtocols() {
return upgradeProtocols.toArray(new UpgradeProtocol[0]);
Expand Down
15 changes: 12 additions & 3 deletions java/org/apache/tomcat/util/net/AbstractEndpoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,12 @@ public SSLHostConfig removeSslHostConfig(String hostName) {
// internally because they are used as keys in a ConcurrentMap where
// keys are compared in a case-sensitive manner.
String hostNameLower = hostName.toLowerCase(Locale.ENGLISH);
if (hostNameLower.equals(getDefaultSSLHostConfigName())) {
// The default host configuration is the fallback for handshakes
// without a matching SNI name, so it cannot be removed while the
// endpoint is still serving TLS. Once TLS is switched off (for
// example to remove the last remaining host configuration) the
// guard no longer applies.
if (isSSLEnabled() && hostNameLower.equals(getDefaultSSLHostConfigName())) {
throw new IllegalArgumentException(sm.getString("endpoint.removeDefaultSslHostConfig", hostName));
}
SSLHostConfig sslHostConfig = sslHostConfigs.remove(hostNameLower);
Expand Down Expand Up @@ -823,11 +828,15 @@ private SSLHostConfigCertificate selectCertificate(SSLHostConfig sslHostConfig,


/**
* Initialise the SSL configuration.
* Initialize the SSL implementation and (re-)create the SSL context
* of every SSL host configuration. Called from {@code bind()} but
* also made available to components that switch an already bound,
* running endpoint to TLS after the initial bind (which is when the
* SSL implementation and contexts are validated and created).
*
* @throws Exception If an error occurs while initializing SSL
*/
protected void initialiseSsl() throws Exception {
public void initialiseSsl() throws Exception {
if (isSSLEnabled()) {
sslImplementation = SSLImplementation.getInstance(getSslImplementationName());

Expand Down
15 changes: 15 additions & 0 deletions java/org/apache/tomcat/util/net/NioEndpoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,21 @@ protected SynchronizedStack<NioChannel> getNioChannels() {
}


@Override
public void setSSLEnabled(boolean SSLEnabled) {
if (SSLEnabled != isSSLEnabled() && nioChannels != null) {
// The channel cache may contain channels of the previous
// type (secure or plain) which must not be re-used once the
// SSL state of the endpoint has changed.
NioChannel channel;
while ((channel = nioChannels.pop()) != null) {
channel.free();
}
}
super.setSSLEnabled(SSLEnabled);
}


/**
* Returns the poller instance.
*
Expand Down
1,155 changes: 1,155 additions & 0 deletions modules/manager2/LICENSE

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions modules/manager2/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Apache Tomcat Manager2
Copyright 2026 The Apache Software Foundation

This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
123 changes: 123 additions & 0 deletions modules/manager2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Tomcat Manager2

`manager2` is an experimental, self-contained replacement for the classic
`/manager` and `/host-manager` web applications, extended with live runtime
monitoring. It is a single web application deployed at `/manager2` that
combines:

- **Web application management** — list, deploy (server-side path or upload),
start, stop, reload, undeploy, and session management (list, detail,
attributes, invalidate).
- **Virtual host management** — list, add, start, stop, remove and persist
hosts.
- **Runtime monitoring** — JVM, memory and thread-pool gauges, per-connector
worker statistics, per-application detail, plus diagnostics (memory leaks,
global resources, VM info, thread dump, SSL ciphers/certificates).

The interface is a dependency-free JavaScript SPA (no JSPs, no build step)
backed by a small JSON API. This module is experimental: it is not included
in the default distribution and its API is not yet stable.

## Layout

```
modules/manager2/
build.xml Standalone Ant build (jar, war, deploy, test)
build.properties.default Version + main-build location properties
resources/MANIFEST.MF Jar manifest (bundle metadata)
src/main/java/org/apache/tomcat/manager2/
AppsApiServlet.java /api/apps/*, /api/ssl/*, /api/leaks,
/api/resources, /api/diagnostics/*
(extends HTMLManagerServlet)
HostsApiServlet.java /api/hosts/* (extends HostManagerServlet)
StatusApiServlet.java /api/info, /api/csrf, /api/status, /api/status/*
StatusHistory.java Rolling history of status samples, collected in
the background and served by /api/status/history
StatusSnapshot.java MBean collection for the status endpoints
CsrfFilter.java Per-session CSRF token (X-CSRF-Token header)
HeadersFilter.java Content-Security-Policy / Referrer-Policy
HomeServlet.java / + SPA deep links: login gate / SPA shell
LoginServlet.java /login: renders the login page, keeps the
post-login redirect at the app root
LogoutServlet.java /logout: invalidates the session
ErrorServlet.java /error: renders the 403/404 pages
Html.java Template rendering (base element injection)
Api.java, Json.java, Constants.java, LocalStrings.properties
src/test/java/org/apache/tomcat/manager2/
TestManager2Webapp.java Integration tests (TomcatBaseTest)
webapp/
index.html SPA shell
login.html Login page template (served by LoginServlet)
error-403.html Error page templates (served by ErrorServlet)
error-404.html
css/manager2.css Design system (light/dark, responsive)
js/*.js SPA (vanilla ES modules, no dependencies)
WEB-INF/web.xml Servlets, filters, constraints, login-config
META-INF/context.xml Privileged context + hardened cookie processor
```

The servlet package is `org.apache.tomcat.manager2` rather than
`org.apache.catalina.manager2`: classes whose names start with
`org.apache.catalina` are always loaded by the container class loader
(`DefaultInstanceManager`), which would make the web application's own jar
unreachable for them.

## Requirements

- A main Tomcat build with `${tomcat.home}/output/build/lib` populated
(run `ant` in the main tree first).
- Ant, and a JDK matching the main build.
- For `ant test`: the main tree's `output/testclasses` (from `ant test` or a
full build) and the JUnit/HAMCREST jars in `${user.home}/tomcat-build-libs`.

## Building

```sh
cd modules/manager2
ant # produces output/manager2.jar and output/manager2.war
ant deploy # additionally copies manager2.war into output/build/webapps
ant test # builds, deploys and runs the integration tests
```

`build.properties` (local, not committed) can override the properties from
`build.properties.default`, in particular `tomcat.home`/`tomcat.build` if the
main build lives elsewhere.

The WAR is self-contained: the servlets ship in `WEB-INF/lib/manager2.jar`.
The context is configured via `META-INF/context.xml` to run privileged
(required by the management servlets) with a hardened `Rfc6265CookieProcessor`
(`SameSite=Strict`) and, for convenience in development, a
`RemoteCIDRValve` allowing loopback only.

## Using

Deploy `manager2.war` (or the unpacked directory) and create users with the
usual `manager-gui` role in `conf/tomcat-users.xml`; `manager-status` grants
read-only access to the status endpoints. Log in at `/manager2/` (HTTP FORM
authentication). State-changing API calls require the per-session
`X-CSRF-Token` header, which is returned in the `X-CSRF-Token` response
header of every API response.

The Dashboard charts are driven by `GET /api/status/history`. The web
application collects a sample in the background (on the server utility
executor, from deployment time because the `StatusApi` servlet is
load-on-startup) and keeps the samples of the configured window, so the
charts always show the last window of server activity regardless of when
the page was opened. The collection period and the window are configured
with the `tickMs` and `windowMs` init parameters of the `StatusApi` servlet
(defaults: `2000` ms and `600000` ms, i.e. 300 samples; `tickMs` must be at
least `500` and `windowMs` at least one tick).

## Testing

`ant test` runs `TestManager2Webapp`, a `TomcatBaseTest` that deploys the
built WAR into a throw-away Tomcat instance and drives it over HTTP:

- FORM login flow (including a bad-password case)
- CSRF token issuance and rejection of mutations without a token
- Role separation (`manager-status` is read-only)
- Application list, stop/start/undeploy lifecycle and a deploy from a
server-side WAR
- Session list/detail/invalidate against a JSP-created session
- Status, status history, workers and per-application detail endpoints
- Hosts endpoint
63 changes: 63 additions & 0 deletions modules/manager2/build.properties.default
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# -----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# -----------------------------------------------------------------------------
#
# Build properties for the Tomcat Manager2 module.
#
# Copy this file to "build.properties" (in this directory) and customize it
# for your local environment. Values in "build.properties" override the
# values here.
# -----------------------------------------------------------------------------

# ----- Version -----
version.major=1
version.minor=0
version.build=0
version.patch=0
version.suffix=-SNAPSHOT

# ----- Base path of the Tomcat source tree -----
# The module is built against a Tomcat build (ant) from the main source
# tree. By default the main tree is assumed to be two levels up.
tomcat.home=${basedir}/../..

# Build output of the main Tomcat build (ant) in the main tree. The
# manager2 module needs the built lib/ jars (catalina.jar, servlet-api.jar,
# tomcat-util.jar) to compile and the built distribution to deploy into.
tomcat.build=${tomcat.home}/output/build

# ----- Base path for dependent packages (main tree) -----
# Must match the main tree's build.properties "base.path" so that the
# JUnit/Hamcrest jars used by the main build can be found for testing.
base.path=${user.home}/tomcat-build-libs

junit.version=4.13.2
junit.home=${base.path}/junit-${junit.version}
junit.jar=${junit.home}/junit-${junit.version}.jar

hamcrest.version=3.0
hamcrest.home=${base.path}/hamcrest-${hamcrest.version}
hamcrest.jar=${hamcrest.home}/hamcrest-${hamcrest.version}.jar

# ----- Compile settings (keep in sync with the main tree) -----
compile.release=21
compile.debug=true
compile.deprecation=false
encoding=UTF-8

# ----- Test settings -----
test.entry=
test.reports=${tomcat.output}/reports
Loading
Loading