Skip to content

NETWAYS/rt-extension-healthendpoint

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RT::Extension::HealthEndpoint

Unauthenticated, session-free HTTP health-check endpoints for Request Tracker 6:

  • A fast liveness ping for load balancers — no I/O, proves the web worker process is alive, independent of database or Redis health.
  • A slower, extended status check for monitoring systems like Icinga — checks database connectivity and, if RT stores web sessions in Redis, Redis connectivity too.

Both endpoints are guaranteed to never create a session record, in Redis or any other session store.

Why not a /NoAuth/ Mason page

RT::Interface::Web::HandleRequest ties a web session (and sends a Set-Cookie header) for every request that reaches Mason — including /NoAuth/ pages — before it even checks whether the page is a NoAuth page. Without an already-valid session cookie (the normal case for every load balancer or Icinga probe), this creates a brand new session record the moment it's tied, regardless of whether the page ever touches %session. A probe hitting the page every few seconds would flood the session store with a fresh key per hit.

The only way to guarantee zero session interaction is to intercept the request before Mason ever sees it — at the PSGI layer, via RT's documented, version-stable per-plugin PSGIWrap hook (the same mechanism RT::Extension::ReverseProxy uses):

for my $plugin (RT->Config->Get("Plugins")) {
    my $wrap = $plugin->can("PSGIWrap") or next;
    $app = $wrap->($plugin, $app);
}

This extension's PSGIWrap answers matched paths directly with a PSGI response, without ever calling the wrapped Mason/REST2/static application.

Installation

perl -I. Makefile.PL
make
make install

Edit /opt/rt/etc/RT_SiteConfig.pm:

Plugin('RT::Extension::HealthEndpoint');

Clear the Mason cache and restart the webserver:

rm -rf /opt/rt/var/mason_data/obj

Configuration

All optional; sensible defaults apply. Changes require a webserver restart.

Set($HealthEndpoint_PingPath,   '/healthz/ping');    # default
Set($HealthEndpoint_StatusPath, '/healthz/status');  # default

# undef (default) = auto-detect Redis via $WebSessionClass; 0 = never; 1 = always
Set($HealthEndpoint_CheckRedis, undef);

Only the server key of %WebSessionProperties is used to connect. If your Redis requires a password or a unix socket, the health check will not pass it through and will report fail for an otherwise-healthy Redis.

Response format

PingGET/HEAD /healthz/ping always returns 200 with body pong (empty for HEAD). No I/O, never fails.

StatusGET/HEAD /healthz/status returns:

{"checks":{"database":"ok","redis":"ok"},"status":"ok"}

status is ok only if every executed check is ok; skipped (Redis not configured) never degrades it. HTTP status mirrors this: 200 for ok, 503 otherwise. Only the fixed tokens ok/fail/skipped ever reach the caller — failure details are logged server-side via RT->Logger->error.

Any method other than GET/HEAD on either path returns 405.

Security

Both endpoints are unauthenticated by design. The response body is deliberately minimal. Add IP allowlisting at the reverse proxy or firewall layer if the endpoints should not be publicly reachable.

Author

NETWAYS GmbH support@netways.de

License and copyright

This software is Copyright (c) 2026 by NETWAYS GmbH

This is free software, licensed under:

The GNU General Public License, Version 2, June 1991

About

Unauthenticated, session-free HTTP health-check endpoints for Request Tracker (LB ping + Icinga status)

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages