2026-02-10
v10.32.1
Summary
Add top-level init{} blocks for configuration lifecycle tasks
Add stop action for halting AAA pipeline execution while preserving the current result
Management UI logs view now displays and supports filtering by structured log fields
Add reply action for sending RADIUS responses immediately while continuing pipeline execution
Add cache.increment() Lua method for atomic counter operations
Add /api/v1/caches/summary endpoint and /app/caches UI page
Documentation sidebar now displays hierarchical tree navigation with collapsible sections
Added full-text search to the management UI and documentation site with indexing and result highlighting
Management UI now displays TimeSpent metrics as per-request averages in dedicated charts
Automatic loading of default RADIUS dictionary when no dictionary is configured
Improved dashboard accessibility for monitor users with dedicated API endpoints and streamlined layout
Fixed configuration editor showing unwanted color preview boxes for hex values
Added short form syntax for the
tryaction to simplify error-to-ignore conversionParser warnings now use structured logging instead of direct stderr output
Added new
countfilter to return the number of values in a multivalueImproved policy selection to try the next policy when no matching handler is found
Add
aaa.caught_errorsvariable to track all errors caught by try actionsAdded warnings for policies and handlers without conditions blocks
Add support for named RADIUS constants in configuration conditions for clearer, more maintainable configs
Fixed template and configuration file contents not updating when switching between items
Configuration import and export now support filtering by content type (db, tls, lua, templates, licenses, management, ui-settings)
SQLite database auxiliary files are now excluded from configuration operations
Added server-side template rendering for configuration templates.
Added CLI template rendering via the
template rendersubcommand.RADIUS backend now supports independent queries for sending custom RADIUS requests from any protocol handler
The unsaved changes dialog now includes a Save button, and the template form's submit button was renamed from Update to Save for consistency
Add experimental servers and backends configuration viewers to the Management UI
Fixed file upload fields not working correctly when nested two or more levels deep in template groups
Fixed spurious 404 error notifications when template file_upload fields specify paths that don't exist yet
Added favicon to the Management UI
Add short form syntax for single-line
modifystatementsAdd optional random jitter parameter to sleep action for retry logic and load testing
Management UI sessions are now preserved across API-initiated server restarts
Top-Level Init Blocks
Top-level init{} blocks allow you to execute pipeline actions when configuration is loaded or reloaded. Multiple init blocks can be defined and execute sequentially in the order they appear in the configuration.
Key Features:
- Executes on initial configuration load and every subsequent reload/restart
- Multiple blocks supported - they execute in order
- Variables are isolated to each init block
- Cache is shared across all init blocks within the same execution
- Useful for logging, cache initialization, and resource setup
Documentation:
init- Complete reference with examples
Example:
init {
log "SYSTEM" {
json {
"event" "configuration_loaded";
"timestamp" datetime.timestamp;
}
}
}
Stop Action
New stop action halts pipeline execution immediately without changing the current result. This allows explicit control over pipeline flow by preventing subsequent actions from running.
Example
accept;
stop;
reject;
In this configuration, the pipeline accepts the request and stops. The reject action never executes, so the final result is accept.
Documentation
Display structured log fields
The Application Logs view in the Management UI now automatically detects and displays structured fields from log entries as additional columns. These dynamic columns are sortable and filterable, making it easier to analyze logs with custom context fields.
Reply Action
New reply action sends the RADIUS response immediately without waiting for the rest of the pipeline to complete. This enables fast acknowledgment of requests while performing background processing such as database writes, logging, or dynamic authorization.
Example
accounting {
# Send reply immediately
reply;
# Background processing - client already received response
backend {
name "SQL";
query "INSERT_ACCOUNTING";
}
}
The reply action is useful in accounting pipelines where quick acknowledgment improves client behavior, and in scenarios where post-reply actions like dynamic authorization requests should not delay the response.
Documentation
Cache Increment for Atomic Counters
A new cache:increment() method has been added to the Lua cache API for atomic counter
operations. This is particularly useful for implementing rate limiting, request counting,
and other scenarios requiring atomic integer operations.
The method returns the new value after increment and is atomic and thread-safe. Cache timeout behavior now implements fixed window semantics where timeouts are only set when a key is first created or explicitly provided.
See scripts.context.cache for documentation and examples.
New Cache Summary Endpoint and UI
A new Management API endpoint GET /api/v1/caches/summary provides an overview of all
configured caches, including:
- Cache name
- Current key count
- Default timeout
The Management UI now includes a /app/caches page displaying this information in an
interactive table with formatted timeout values.
Breaking Change: Inline Lua Script Syntax
The syntax for inline Lua scripts has changed from content { ... --END } blocks to
triple-quoted strings (content """...""";).
Old syntax (no longer supported):
lua "example" {
content {
local context, previous = ...
return previous
--END
}
}
New syntax:
lua "example" {
content """
local context, previous = ...
return previous
""";
}
The new syntax uses Python-style triple-quoted strings which automatically remove
common leading indentation. This eliminates the need for the --END marker and
provides cleaner, more readable inline scripts.
Migration
Update any inline Lua scripts in your configuration files:
- Replace
content {withcontent """ - Remove the
--ENDmarker - Add closing
""";
See scripts for updated documentation and examples.
Documentation Search
The management UI and documentation site now includes a full-text search feature accessible from the toolbar.
Features
- Full-text search: Search across all documentation pages including articles, configuration references, and action documentation
- Smart result previews: Search results show contextual previews with matched terms highlighted
- Page highlighting: When navigating to a search result, matched terms are highlighted on the target page with a visual flash animation
- Keyboard support: Navigate the search matches with cursor keys and enter. Press
Escapeto clear search highlights on any target page
TimeSpent displayed as per-request average
The Management UI statistics charts now show TimeSpent values as per-request averages instead of cumulative totals. TimeSpent data is displayed in a dedicated chart below the main handler statistics chart for clearer visualization.
When using time bucket aggregation on TimeSpent charts, values are averaged rather than summed, which is more meaningful for latency metrics.
Default Dictionary Loading
When no dictionary configuration is present, the server will automatically attempt to load the default RADIUS dictionary from /opt/radiator/server/dictionary. If the file does not exist, the server continues to operate without a dictionary.
Short Form try Action
The try action now supports a short form syntax that makes it easier to convert errors to ignore results without needing a full try/catch block.
Structured Parser Warnings
Parser warnings in configuration files (including deprecation warnings) are now emitted through the structured logging system instead of being written directly to stderr.
- Warnings include proper log levels and can be filtered like other log messages
- Location information is included as a structured field
- Warnings integrate with existing log collection infrastructure
Log Output Format
When parser warnings are detected, they are logged at the WARN level with the following fields:
warning_message: The specific warning messagelocation: File path and line number where the issue was found
Disabling Parser Warnings
To suppress parser warnings, set the environment variable:
RADIATOR_PARSER_WARNINGS=0
Improved Policy and Handler Selection
When no explicit policy is specified, the policy selection logic now considers both the policy conditions and handler conditions together. If a policy matches but none of its handlers match, the system will now continue to try the next policy instead of failing immediately.
This change improves flexibility in configurations with multiple policies where handlers have restrictive conditions. Previously, if the first matching policy had no matching handler, the request would fail even if another policy could have handled it successfully.
Behavior Change
| Scenario | Previous Behavior | New Behavior |
|---|---|---|
| First policy matches, no handler matches | Error: "No handler found for policy" | Tries next policy |
| No policies have matching handlers | Error: "No handler found for policy" | Error: "No matching policy with handler found" |
When a specific policy is explicitly selected (via policy_id), the behavior
remains unchanged - if no handler matches within that policy, an error is
returned.
Example Configuration
aaa {
policy "SPECIALIZED" {
handler "SPECIAL_AUTH" {
conditions all {
aaa.identity == "special-user";
}
@execute {
# Handle special user
}
}
}
}
aaa {
policy "DEFAULT" {
handler "DEFAULT_AUTH" {
@execute {
# Handle all other users
}
}
}
}
With this configuration, requests for users other than "special-user" will now correctly fall through to the "DEFAULT" policy instead of failing when the "SPECIALIZED" policy's handler conditions don't match.
Error History Tracking with aaa.caught_errors
A new aaa.caught_errors variable is now available to track all errors caught by try actions during request processing. Previously, only the most recent error was accessible via aaa.caught_error. The new variable maintains a complete history of all caught errors.
Documentation
See try action documentation for more details.
Warnings for Policies and Handlers Without Conditions
The configuration parser now emits warnings when policies or handlers are
defined without conditions blocks. This helps identify potential configuration
issues where policies or handlers may be more permissive than intended.
Policy Without Conditions Warning
A warning is emitted when a policy has no conditions block, as all requests
will match such a policy:
aaa {
policy "TOO_PERMISSIVE" {
# Warning: Policy 'TOO_PERMISSIVE' has no 'conditions' block.
# All requests will match this policy.
handler "AUTH" {
@authentication { accept; }
}
}
}
Handler Without Conditions Warning
A warning is emitted when a handler has no conditions block, as all requests
matching the policy will use that handler:
aaa {
policy "EXAMPLE" {
conditions all { true == true; }
handler "HANDLER_1" {
# Warning: Handler 'HANDLER_1' has no 'conditions' block.
@authentication { accept; }
}
handler "HANDLER_2" {
# Warning: Handler 'HANDLER_2' has no 'conditions' block.
@authentication { reject; }
}
}
}
When Warnings Are Suppressed
To avoid noisy warnings in common valid configurations, warnings are suppressed in these cases:
-
Single handler with policy conditions: When a policy has conditions and only one handler, no warning is emitted for that handler (since the policy conditions already filter requests)
-
All handlers have conditions: When all handlers in a policy have their own conditions blocks, no warning is emitted for the policy itself (since the handlers provide the necessary filtering)
RADIUS Constants Support
Configuration conditions can now use named RADIUS constants for packet type codes instead of magic numbers, making configurations more readable and self-documenting.
Available Constants
Packet Type Codes:
radius.ACCESS_REQUEST,radius.ACCESS_ACCEPT,radius.ACCESS_REJECTradius.ACCOUNTING_REQUEST,radius.ACCOUNTING_RESPONSEradius.ACCESS_CHALLENGE,radius.STATUS_SERVERradius.DISCONNECT_REQUEST,radius.DISCONNECT_ACK,radius.DISCONNECT_NAKradius.COA_REQUEST,radius.COA_ACK,radius.COA_NAK
See Execution Context - RADIUS Constants for the complete list of available constants and their values.
Attribute Enum Values
For attribute enum values like Acct-Status-Type or Service-Type, use the radius.dict.* syntax
which provides access to all dictionary-defined values:
# Instead of magic numbers, use dictionary values:
radius.request.attr.acct-status-type == radius.dict.Acct-Status-Type.Start # 1
radius.request.attr.acct-status-type == radius.dict.Acct-Status-Type.Stop # 2
radius.request.attr.acct-status-type == radius.dict.Acct-Status-Type.Alive # 3
radius.request.attr.service-type == radius.dict.Service-Type.Login-User # 1
Example Usage
Before:
if all {
radius.request.code == 1;
} then {
# What does 1 mean?
}
After:
if all {
radius.request.code == radius.ACCESS_REQUEST;
} then {
# Clear and self-documenting
}
Fixed a bug where navigating between different templates or configuration files in the management UI would show stale content from the previously viewed item.
Configuration import and export filters
Configuration exports and imports can now include or exclude specific content directories. This provides finer control over what is transferred when moving configurations between environments.
Export options:
includeDb- Database files (db/) - default: trueincludeTls- TLS certificates and keys (tls/) - default: trueincludeLua- Lua scripts (lua/) - default: trueincludeTemplates- Templates (templates/) - default: trueincludeLicenses- Licenses (licenses/) - default: falseincludeManagement- Management configuration (management/) - default: falseincludeUiSettings- UI settings (ui-settings/) - default: false
Import options:
The same content types can be controlled during import. Additionally, templates support three import modes via templateImportMode:
append(default) - Merge with existing templatesreplace- Delete existing templates before importingignore- Skip template import entirely
Content that is not imported from the ZIP archive is automatically copied from the active configuration to preserve existing settings.
SQLite auxiliary files exclusion:
SQLite database auxiliary files (.db-wal, .db-shm, .db-journal and their .sqlite/.sqlite3 equivalents) are now automatically excluded from configuration exports, imports, directory listings, and backups. These are runtime state files that should not be transferred between environments.
- Template rendering can be performed via CLI by running:
radiator template render <TEMPLATE_FILE> <VALUES_FILE> [OUTPUT_FILE] - When
OUTPUT_FILEis omitted, the rendered output is written to stdout.
RADIUS backend query support
The RADIUS backend now supports a query mode that allows sending independent RADIUS requests from any protocol handler. This enables issuing RADIUS requests from HTTP, TACACS+, or other protocols, not just from RADIUS request contexts.
See RADIUS backend configuration for complete documentation.
Experimental Servers and Backends Configuration Viewers
The Management UI now includes read-only viewers for Servers and Backends configuration. These are experimental features and subject to change in future releases. Both items are accessible from the Main section in the navigation drawer.
Nested Group File Upload Fix
Fixed an issue where file upload fields nested in two or more levels of groups would not properly associate uploaded files with the correct group instance. Previously, only single-level group nesting was correctly handled for file uploads. Now file uploads work correctly at any nesting depth.
Suppressed 404 Errors for Non-Existent Upload Paths
Template file_upload fields often specify directories that don't exist until
files are actually uploaded (e.g., tls/custom-certs). Previously, the form
would show error notifications when trying to list these directories. These
errors are now suppressed since an empty directory listing is the expected
behavior for new uploads.
Favicon
The Management UI now displays the Radiator logo as a favicon in the browser tab.
Fixed set action behavior
The set action previously used an insert-unless-exists strategy, meaning it
would only assign a value if the target variable was not already set. This was
inconsistent with the documented behavior and with the replace action.
The set action now unconditionally assigns the value to the target variable,
correctly overriding any previously set value. This makes set and replace
behave identically — both always override the current value.
Before (broken)
set vars.greeting "hello";
set vars.greeting "goodbye";
# vars.greeting was "hello" (second set was ignored)
After (fixed)
set vars.greeting "hello";
set vars.greeting "goodbye";
# vars.greeting is now "goodbye"
If you need the previous behaviour, use the modify action with the ?= operator:
modify vars.greeting ?= "hello";
Documentation
- set — updated to clarify unconditional assignment behavior
Short form modify syntax
The modify action now supports a short form syntax for single-line
assignments. Instead of requiring a block with curly braces, you can write
the assignment directly after modify:
modify vars.foo = "bar";
This is equivalent to the block form:
modify {
vars.foo = "bar";
}
The short form supports all assignment operators (=, ?=, +=) and
improves configuration readability for simple cases. The existing block
syntax remains fully supported for multiple assignments.
Documentation
- Updated modify action documentation with short form syntax description and examples
Sleep Action Random Jitter
The sleep action now accepts an optional second parameter to add random jitter to the sleep duration.
Syntax
sleep <duration> <random>;
The actual sleep time will be duration + random(0, random) inclusive. This is useful for:
- Adding jitter to retry logic to prevent thundering herd problems
- Simulating variable network latency in tests
- Load testing with realistic timing variations
Example
try {
backend my_backend;
} catch {
# Sleep 1s to 3s (1s base + 0-2s random)
sleep 1s 2s;
backend my_backup_backend;
}
Documentation
Sessions persisted across restarts
Previously, triggering a server restart from the management UI would invalidate all active sessions, forcing users to log in again. Sessions are now preserved across API-initiated restarts, so users remain logged in seamlessly.
Known Issues
When the /var/lib/radiator directory has 15_certificates.radconf file, and the file has not been edited once, the rpm package upgrade will show a warning warning: file /var/lib/radiator/15_certificates.radconf: remove failed: No such file or directory. The warning is harmless and can be ignored, as the 15_certificates.radconf file has been renamed.