Radiator Server Documentation — v10.33.1
2026-04-01

v10.33.0

Summary
  • New minimal configuration based installation packages

  • Counter views now show inline P95 histogram sparklines, category-based color coding, and Prometheus histogram percentile metrics

  • Health endpoint now includes a boot_id that changes on every restart

  • Radconf parse errors now point to the correct file and line when a block is left unclosed across multiple included files

  • The license block in the configuration is now optional

  • License changes can now be applied without restarting the server

  • Added systemd Type=notify readiness notification support

  • Added trace logging for low-level RADIUS packets and EAP messages

  • Log counter statistics now visually distinguish counter categories with colored counts and sparklines

  • Fix DNS-SD RadSec backend TLS certificate verification failure caused by trailing dot in SRV record hostnames and missing hostname for TLS server name

  • Fix DNS-SD RadSec backend incorrectly forwarding realm name as RADIUS query name, causing 'Unknown RADIUS query' errors on proxied requests

  • Fix log table displaying entries in wrong order when sorting by non-timestamp columns while streaming

  • Configuration ZIP import no longer preserves stale directories from the active configuration when the ZIP lacks them

  • License import now supports Ignore, Append, and Replace modes, matching the existing template import modes

  • Radiator now logs a startup warning and drops packets when a server references a policy name that is not defined

  • Fix variables set during inner EAP authentication (EAP-TTLS, PEAP) not being visible in the outer context

  • Inner EAP context errors are now propagated to the parent context

  • Added YubiKey OTP authentication support with cloud and offline validation paths

  • SQL statement bindings now support radius.request.attrs for storing all RADIUS request attributes as JSON

  • RADIUS attribute log entries now include dictionary type field

  • Added tacacsplus.request.password execution context variable for reading TACACS+ request passwords

  • Fixed UI not refreshing sidebar and other data after deploying configuration with server restart

  • Fix map action match order with multivalue items

New minimal configuration based installation packages

Due to changes in the default configuration, the upgrade process for this package is not available. To change from older Radiator version to this new version a maintenance break is required.

Once installed, the existing configuration backup can be imported and taken back into use.

Instructions for the deb package

  1. Backup the existing configuration
  2. Remove existing installation with apt-get remove --purge radiator-server If apt-get lists any directories as not removed, clear them out manually with rm -rf <directory>
  3. Install new package with apt install radiator-server
  4. Restore the configuration from the backup

Instruction for the RPM package

  1. Backup the existing configuration
  2. Remove existing installation with dnf remove radiator-server If apt-get lists any directories as not removed, clear them out manually with rm -rf <directory>
  3. Install new package with dnf install radiator-server
  4. Restore the configuration from the backup

Richer counter views with inline histogram sparklines and category colors

The Management UI counter table and details pages have been significantly improved. Histograms are now first-class citizens throughout the UI and the Prometheus exporter.

Category-based color coding

Each counter row is now colored according to its semantic category:

  • Success (green) — accepted requests, successful replies, cache hits
  • Error (red) — processing errors, protocol failures, backend failures
  • Warning (orange) — denied clients, timeouts, rejected requests
  • Info (blue) — throughput metrics, active sessions
  • Default (gray) — informational counters without explicit category

Categories can be inferred automatically from well-known counter names, or set explicitly via register_counter_meta.

Inline histogram P95 sparklines

Histogram namespaces now render a compact P95 sparkline directly in the counter table, giving an at-a-glance view of latency history without navigating away from the table. Hovering the sparkline shows timestamps and the exact P95 value.

Rebuilt counter details page

The counter details page has been rebuilt on top of the unified clog tree API. Scalar counters display a bar chart, histograms display a latency chart with autoscaled Y-axis (µs → ms → s), and both share the same namespace sidebar.

System dashboard card

A new system dashboard card shows live memory usage, CPU utilisation, and AAA pipeline latency sparklines. Clicking the card opens the system counters view.

Prometheus histogram percentiles

The Prometheus exporter now publishes P50, P95, and P99 quantile gauges for every histogram, grouped as radiator_histogram{unit_suffix} with namespace, name, and quantile labels.

Clearer radconf error messages for unclosed blocks

When a radconf block (e.g. management { ... }) is left without a closing brace and the configuration is split across multiple included files, the parse error is now reported at the file and line containing the unclosed brace instead of an unrelated file loaded after it.

The error message wording has also been improved: Unexpected EOF while reading is now Unexpected end of file for clarity.

License block is now optional

The license block in the configuration file is now optional.

Existing configurations with an explicit license block continue to work unchanged.

License changes are now applied on configuration reload without requiring a server restart.

See license configuration for details.

Systemd readiness notification

Radiator Server now supports the systemd Type=notify protocol. When running as a systemd service with Type=notify, Radiator sends a READY=1 notification after configuration has been loaded and all subsystems are initialized.

See Linux systemd support for details.

RADIUS packet and EAP message trace logging

Radiator Server now emits structured trace log entries for low-level RADIUS packets and EAP messages. This provides visibility into protocol-level details that are not captured by AAA authentication logs, including EAP negotiation exchanges and Status-Server packets.

See Log storage and formatting for details.

Color-coded log counter statistics

The Statistics page now color-codes log counters based on their category. Error counters are shown in red, warning counters in orange, success counters in green, and info counters in blue. The sparkline charts also use the corresponding color. Counters with the default category remain unstyled.

Configuration import improvements

When importing a configuration ZIP archive, directories that are enabled for import but missing from the ZIP are no longer incorrectly preserved from the active configuration. Previously, importing a ZIP without e.g. a tls/ directory would copy the active tls/ into the pending configuration, even though the user intended to import from the ZIP. Now, the pending configuration only contains what is in the ZIP (for enabled content types), and a warning is shown when the ZIP lacks an expected directory.

License files now support the same three import modes as templates:

  • Ignore (default) — preserve licenses from active configuration
  • Append — merge licenses from the ZIP with existing licenses
  • Replace — use only licenses from the ZIP, removing any existing licenses

The API accepts a new licenseImportMode query parameter with values ignore, append, or replace.

See Configuration Import and Export for updated documentation.

Server with undefined policy reference now warns and drops packets

Previously, if a server's policy directive named a policy that was not defined in the configuration, the server silently fell back to selecting the first matching policy. This masked configuration errors and caused unexpected behavior.

Radiator now validates policy name references at startup. If a server's policy directive names a policy that does not exist, a warning is logged at startup. At request time, the packet is dropped and a debug log entry is emitted (upsampled to a warning once per minute).

Note: the previous fallback behavior - where omitting the policy directive causes Radiator to iterate policies in configuration file definition order and use the first one with matching conditions and a matching handler - is unchanged.

See servers.policy for updated documentation.

Fix variable modifications in inner EAP context

Variables set or modified during inner EAP authentication (e.g. inside eap-ttls or eap-peap blocks) are now immediately visible to the outer authentication context after the EAP block completes.

Previously, the inner authentication context received a deep copy of the parent's variables. Any modifications made inside the inner context were lost once the inner authentication finished, because changes were never propagated back to the outer context.

Now the inner and outer contexts share the same variable storage, so a modify vars.inner = "value" inside an EAP-TTLS @authentication block can be read via vars.inner in the outer handler after the eap block.

Example

@authentication {
    eap {
        eap-ttls {
            tls {
                # ...
            }

            @authentication {
                backend {
                    name "USERS";
                    query "FIND_USER";
                }
                pap;

                # Copy the client certificate email to a variable
                if any {
                    cert.subject_alt.email != none;
                }
                then {
                    modify vars.certemail = cert.subject_alt.email;
                }
            }
        }
    }

    # vars.certemail is now available here — previously it was lost
    # when the inner EAP context was discarded
    assert "hello@example.com" vars.certemail;
}

Propagate inner EAP context errors to the parent context

Errors raised during inner EAP authentication are now propagated to the parent context when using EAP.

Previously, an error inside an inner EAP context could be handled only within that inner context. Now those errors are also visible to the parent context, which makes it easier to handle EAP failures consistently in outer authentication logic.

YubiKey OTP Authentication

Radiator now supports Yubico OTP authentication with two validation paths:

  • Cloud validation — The yubikey HTTP backend forwards OTPs to an external Yubico KSM-compatible server (such as api.yubico.com) with HMAC-SHA1 signed requests and verified responses. See the HTTP backend reference.
  • Offline validation — The yubikey action decrypts and validates OTPs locally using a stored AES-128 key. No network call is made. See the yubikey action reference.

Both paths support two-factor authentication by combining a static password with the YubiKey OTP using the range parameter on the pap and yubikey actions.

For a complete walkthrough including backend schema, configuration examples, and replay protection, see the YubiKey Authentication article.

SQL bindings support for radius.request.attrs

The radius.request.attrs binding can now be used in SQL statement bindings to store all RADIUS request attributes as a flat JSON object into a database column. This works with SQLite, MySQL, and PostgreSQL backends.

Example configuration:

statement "STORE_ACCOUNTING" {
    statement "INSERT INTO accounting (attrs) VALUES (?)";
    bindings {
        radius.request.attrs;
    }
}

When stored through SQL backends, the attributes are serialized as a flat JSON object keyed by lowercase attribute name. Repeated attributes are stored as JSON arrays. Existing logging and trace output continues to use the JSON array format.

Dictionary type included in RADIUS attribute logs

RADIUS attribute entries in authentication and accounting log output now include a "type" field that shows the dictionary datatype of each attribute. The JSON array format used in logging and tracing changed from {"name": "...", "value": ...} to {"name": "...", "type": "...", "value": ...}.

The type value is the dictionary datatype string such as "string", "enum32", "ipv4addr", etc. For unknown attributes that are not found in the dictionary, the type is null.

Example log entry:

{"name": "user-name", "type": "string", "value": "mikem"}
{"name": "service-type", "type": "enum32", "value": "framed-user"}
{"name": "26.99999.1", "type": null, "value": "deadbeef"}

Added tacacsplus.request.password context variable

A new read-only execution context variable tacacsplus.request.password is now available for TACACS+ authentication processing. This allows accessing the password from incoming TACACS+ authentication requests as a masked password value.

This enables LDAP bind authentication for TACACS+ by passing the request password directly to an LDAP bind query:

backends {
    ldap "LDAP" {
        bind "BIND_USER" {
            dn vars.dn;
            password tacacsplus.request.password;
        }
    }
}

See Execution Context for the full list of available TACACS+ context variables.