How to Set Up a RADIUS Provider in authentik: Complete Configuration Guide
RADIUS providers in authentik enable external applications to authenticate users via the RADIUS protocol through a containerized outpost that enforces centralized policies.
Setting up a RADIUS provider involves three interconnected layers: defining the provider model in authentik's database, exposing it through REST APIs, and deploying a dedicated outpost container. This guide walks through each layer using actual source paths and working code examples from the goauthentik/authentik repository.
Understanding the RADIUS Provider Architecture
The authentik RADIUS implementation follows a clean separation between configuration, policy evaluation, and protocol handling. All three layers work together to ensure user authentication requests are validated against your existing authentik policies before a RADIUS response is generated.
Data Model Layer
The RadiusProvider model in authentik/providers/radius/models.py extends both Provider and OutpostModel to inherit core provider functionality while enabling outpost deployment capabilities.
Key fields stored by the model include:
- Shared secret — the pre-shared key used to authenticate RADIUS clients
- Client networks — CIDR-notation allowed source IP ranges
- TLS certificate — optional certificate for secure communication
- MFA support flag — enables multi-factor authentication flows
The model also defines its UI component (component = "ak-provider-radius-form") and icon for the authentik admin interface.
REST API Layer
Two viewsets in authentik/providers/radius/api/providers.py expose RADIUS functionality:
RadiusProviderViewSet — handles CRUD operations using RadiusProviderSerializer. This serializer reads and writes all provider fields including the sensitive shared secret.
RadiusOutpostConfigViewSet — supplies minimal configuration for outpost initialization: provider name, application slug, shared secret, and network bindings.
The critical check_access action on the viewset performs policy evaluation. When called with an app_slug parameter, it:
- Builds a policy engine for the target application
- Runs all configured policies against the requesting user
- On success, returns a Base64-encoded RADIUS packet containing attribute mappings
This centralizes all access decisions in authentik rather than distributing logic to outposts.
Outpost Deployment Layer
Radius outposts run as containerized services that bridge RADIUS UDP traffic to authentik's HTTP API. The deployment is managed through:
RadiusDockerController(authentik/providers/radius/controllers/docker.py)RadiusKubernetesController(authentik/providers/radius/controllers/kubernetes.py)
These controllers create containers exposing UDP port 1812, mount the shared secret as configuration, and bind any configured TLS certificates. The outpost image is built from lifecycle/container/radius.Dockerfile.
Creating a RADIUS Provider via API
Use authentik's Python client to programmatically create a provider with MFA support and restricted client networks:
from goauthentik.client import AuthentikClient
from goauthentik.models import RadiusProvider
client = AuthentikClient(
base_url="https://auth.example.com",
token="YOUR_API_TOKEN"
)
provider = RadiusProvider(
name="Corporate VPN RADIUS",
client_networks="10.0.0.0/8, 192.168.0.0/16",
shared_secret="super-secret-key-min-16-chars",
mfa_support=True,
)
created = client.providers.radius.create(provider)
print(f"Provider created with ID: {created.pk}")
Linking to an Application
After creating the provider, associate it with an application to enable policy evaluation:
app = client.applications.create(
name="Corporate VPN",
slug="corp-vpn"
)
# Link the RADIUS provider
app.provider = created.pk
client.applications.update(app)
# Now policies applied to "corp-vpn" will evaluate during RADIUS authentication
Testing Policy Evaluation Directly
The check_access endpoint can be called independently to verify configuration before deploying an outpost. This is useful for debugging attribute mappings:
import requests
import base64
BASE = "https://auth.example.com/api"
TOKEN = "YOUR_API_TOKEN"
PROVIDER_ID = 42
APP_SLUG = "corp-vpn"
url = (
f"{BASE}/outposts/radius/{PROVIDER_ID}/"
f"check_access/?app_slug={APP_SLUG}"
)
resp = requests.get(
url,
headers={"Authorization": f"Bearer {TOKEN}"}
)
data = resp.json()
if data["access"]["passing"]:
# Decode the RADIUS packet with injected attributes
packet = base64.b64decode(data["attributes"])
print(f"Access granted, packet size: {len(packet)} bytes")
else:
print("Access denied by policy evaluation")
print(f"Messages: {data['access']['messages']}")
The response includes the full policy evaluation result and pre-built RADIUS packet, eliminating guesswork about what attributes will be sent to clients.
Deploying the RADIUS Outpost
Docker Deployment
Run the official outpost container with environment-based configuration:
docker run -d \
--name authentik-radius \
-e AUTHENTIK_URL=https://auth.example.com \
-e AUTHENTIK_TOKEN=YOUR_API_TOKEN \
-e AUTHENTIK_INSECURE=false \
-p 1812:1812/udp \
ghcr.io/goauthentik/dev-radius:latest
The container automatically discovers all RADIUS providers your token can access and begins listening on UDP 1812.
Kubernetes Deployment
For production Kubernetes environments, the RadiusKubernetesController generates a Deployment with the correct pod specification:
- UDP port 1812 exposed on the pod
- Token mounted via Secret
- Resource limits configured for network throughput
The controller watches for provider changes and rolls out updates automatically.
Authentication Flow Deep Dive
When a RADIUS client sends an Access-Request packet, this sequence executes:
- Outpost receives UDP packet on port 1812
- Packet forwarded to authentik's
check_accessendpoint with the target application slug - Policy engine evaluates all policies attached to the application
- Attribute mappings execute if policies pass, injecting custom RADIUS attributes
- Encoded response returned to outpost as Base64 RADIUS packet
- Outpost transmits response back to the original client
This flow guarantees that all policy decisions remain centralized — the outpost acts only as a protocol converter, not an authorization authority.
Property Mappings for Custom Attributes
RADIUS attribute injection uses dedicated property mappings defined in authentik/providers/radius/api/property_mappings.py. These mappings let you transform authentik user data into vendor-specific RADIUS attributes.
Example mapping that injects group membership:
from goauthentik.models import RadiusProviderPropertyMapping
group_mapping = RadiusProviderPropertyMapping(
name="RADIUS Groups",
expression="""
return {
"Class": user.ak_groups.all().values_list("name", flat=True)
}
"""
)
The expression field accepts Python code that returns a dictionary of RADIUS attribute names to values. All standard RADIUS attribute types are supported.
Key Source Files Reference
| Component | Source File |
|---|---|
| Provider model definition | authentik/providers/radius/models.py |
| REST API viewsets and serializers | authentik/providers/radius/api/providers.py |
| Property mapping API | authentik/providers/radius/api/property_mappings.py |
| Docker deployment controller | authentik/providers/radius/controllers/docker.py |
| Kubernetes deployment controller | authentik/providers/radius/controllers/kubernetes.py |
| Outpost image build | lifecycle/container/radius.Dockerfile |
| Outpost task orchestration | authentik/outposts/tasks.py |
Summary
- RADIUS providers in authentik combine a database model, REST API, and containerized outpost to deliver centralized authentication
- The
RadiusProvidermodel stores shared secrets, client networks, and MFA configuration inauthentik/providers/radius/models.py - Policy enforcement happens centrally through the
check_accessendpoint inauthentik/providers/radius/api/providers.py - Outposts operate as stateless containers that convert UDP RADIUS traffic to HTTP API calls, keeping secrets and decisions server-side
- Property mappings enable custom attributes by transforming authentik user data into RADIUS response fields
Frequently Asked Questions
What UDP port does the RADIUS outpost use?
The RADIUS outpost listens on UDP port 1812 by default. This is configured in both the Docker controller (RadiusDockerController) and the outpost container specification. The port mapping is defined as 1812:1812/udp in generated deployments.
Can I restrict which IP addresses can send RADIUS requests?
Yes. The client_networks field on RadiusProvider accepts comma-separated CIDR notation. For example, "10.0.0.0/8, 192.168.1.0/24" limits requests to those networks. Invalid source IPs are rejected at the outpost level before reaching the authentik API.
How does MFA work with RADIUS authentication?
When mfa_support=True is set on the provider, authentik's policy engine evaluates MFA requirements during the check_access call. If MFA is required but incomplete, the RADIUS Access-Reject response includes appropriate error attributes. The actual MFA challenge/response happens through authentik's standard flows, not within the RADIUS protocol itself.
Can I run multiple RADIUS outposts for high availability?
Yes. Each outpost independently polls the authentik API for configuration and can serve identical provider definitions. Deploy multiple containers or pods behind a load balancer distributing UDP 1812 traffic. No session state is stored in the outpost — all authentication state lives in authentik's database.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →