Expiring Redis web sessions for Request Tracker 6 — plus cryptographically strong session IDs.
RT 6 can keep web sessions in Redis with
$WebSessionClass = 'Apache::Session::Redis'. That backend writes every key
with a plain SET and no expiry, so session keys pile up in Redis forever
(a busy instance ends up with hundreds of thousands of dead keys). $AutoLogoff
makes idle sessions functionally invalid but never deletes their data, and
rt-clean-sessions only reaps SQL-backed sessions.
This extension ships a drop-in $WebSessionClass, RT::Session::RedisTTL, that
keeps the proven Apache::Session::Redis serialization (Base64/Storable, hex IDs
— so a blessed RT::CurrentUser survives the round trip) but:
- writes keys with a Redis expiry (
SET … EX), defaulting the TTL to$AutoLogoff, so idle sessions expire on their own; and - by default generates session IDs from the system CSPRNG instead of the
weak
md5(time/rand/pid)the stock backend uses.
Only the store driver and (optionally) the ID generator change. The serialized
payload and ID format are identical to Apache::Session::Redis, so existing
sessions stay readable and valid — rolling this out logs nobody out.
It supports a TTL out of the box, but is hardcoded to a JSON serializer
(to_json without convert_blessed). RT stores a blessed RT::CurrentUser in
the session; JSON silently drops it on the round trip, so the session comes back
broken. The problem is purely the serializer — so this extension keeps
Base64/Storable and adds the TTL at the store layer instead.
perl -I. Makefile.PL # -I. is required: modern Perl drops "." from @INC
make
make install # may need rootThen add to /opt/rt/etc/RT_SiteConfig.pm:
Plugin('RT::Extension::SessionStoreRedisTTL');
Set( $WebSessionClass, 'RT::Session::RedisTTL' );
Set( %WebSessionProperties, server => '127.0.0.1:6379' );Activating the plugin is required — it puts the extension's lib/ on
@INC, which is how the store driver gets found (it is loaded by name at
request time). Then clear the Mason cache (rm -rf /opt/rt/var/mason_data/obj)
and restart the webserver.
The key TTL (seconds) is resolved in this order:
- an explicit
TTLin%WebSessionProperties—TTL => 0opts out (plainSET, no expiry); - else
$AutoLogoff * 60— the idle window after which RT logs the user out — if$AutoLogoffis set and non-zero; - else an 8h floor. RT's
$AutoLogoffdefaults to0(off), so this guarantees keys always expire instead of accumulating forever.
Set( %WebSessionProperties,
server => '127.0.0.1:6379',
TTL => 43200, # seconds; optional, see resolution order above
);update is aliased to insert, so the TTL is refreshed on every write — a
sliding idle expiry; active sessions are never reaped. Pick a TTL >= $AutoLogoff so an idle key does not vanish before RT's own logout window.
Session IDs are drawn from the system CSPRNG. To fall back to the legacy MD5 generator:
Set( $RedisSessionSecureID, 0 );The stock generator, Apache::Session::Generate::MD5, builds the ID as
md5_hex(md5_hex( time() . {} . rand() . $$ )). Its unpredictability comes
only from Perl's rand() (a non-cryptographic drand48 PRNG), an anonymous
hash's address, the pid and the wall-clock second. The MD5 step adds no entropy
— and switching to SHA-256 or any other digest would not help, because a
hash of low-entropy input is still low-entropy. (RT's own
RT::AuthToken::_GenerateToken uses the same time/rand/{} pattern with
SHA-512.)
So this extension sources IDs from the OS CSPRNG (Crypt::URandom:
getrandom(2) / /dev/urandom) by default, keeping the 32-hex-character format
so the inherited validator still accepts old MD5 IDs. It is a strict security
improvement with no compatibility cost.
The TTL value comes from configuration ($AutoLogoff or an explicit TTL),
never from anything client-supplied, and is validated to a positive integer
before it reaches Redis.
Old keys written without a TTL persist until they are next written (then they gain one). To retire the accumulated keyspace in one go, flush the session DB during a maintenance window before cutover — this only logs everyone out, it does not lose ticket data:
redis-cli -n 0 FLUSHDB- RT 6.0.0 or later
Apache::Session::Redis(provides the NoSQL/Redis store chain this extends)RedisCrypt::URandom(CSPRNG source)
GPL v2. Copyright (c) 2026 NETWAYS GmbH.