https://github.com/work-systems-ltd/freeradius-k8s-operator
Declarative FreeRADIUS in kubernetes for ISPs
https://github.com/work-systems-ltd/freeradius-k8s-operator
freeradius freeradius-kubernetes freeradius-server kubernetes kubernetes-operator radius radius-server
Last synced: 2 months ago
JSON representation
Declarative FreeRADIUS in kubernetes for ISPs
- Host: GitHub
- URL: https://github.com/work-systems-ltd/freeradius-k8s-operator
- Owner: Work-Systems-Ltd
- Created: 2026-04-08T22:16:50.000Z (3 months ago)
- Default Branch: master
- Last Pushed: 2026-04-10T06:27:02.000Z (3 months ago)
- Last Synced: 2026-04-12T10:13:40.065Z (3 months ago)
- Topics: freeradius, freeradius-kubernetes, freeradius-server, kubernetes, kubernetes-operator, radius, radius-server
- Language: Go
- Homepage: https://work-systems-ltd.github.io/freeradius-k8s-operator/
- Size: 72.6 MB
- Stars: 3
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
Awesome Lists containing this project
README
# FreeRADIUS, the Kubernetes-native way.
A Kubernetes operator built for ISP BNG and broadband subscriber management at scale. It turns RADIUS clusters, NAS clients, and unlang policies into native custom resources — so the AAA layer behind your BNGs lives in Git, rolls out with `kubectl apply`, and scales like everything else in your cluster.
[](https://go.dev)
[](https://kubernetes.io)
[](LICENSE)
[](https://Work-Systems-Ltd.github.io/freeradius-k8s-operator/)
[](https://discord.gg/gKQz4kpM)
[**Quick Start**](#quick-start) · [**Why?**](#why-this-exists) · [**Examples**](example/) · [**Docs**](https://Work-Systems-Ltd.github.io/freeradius-k8s-operator/)
---
> [!WARNING]
> This project is under active development and is **not yet production-ready**. APIs, CRD schemas, and behaviors may change without notice. Star the repo to follow along — we're close.
## How it works
```mermaid
flowchart LR
subgraph Git["GitOps / kubectl apply"]
CR["RadiusCluster
RadiusClient
RadiusPolicy"]
end
subgraph K8s["Kubernetes Cluster"]
OP["FreeRADIUS
Operator"]
CFG["Rendered ConfigMap
radiusd.conf
clients.conf
sites / modules"]
SEC[("Secrets
shared keys
DB creds
TLS certs")]
subgraph FR["FreeRADIUS Pods"]
P1["auth"]
P2["acct"]
P3["CoA"]
end
OBS["Metrics
ServiceMonitor
Alerts"]
end
subgraph Net["Network Edge"]
BNG["BNGs / OLTs
NAS devices
WiFi APs"]
SUB["Subscribers
PPPoE / IPoE / 802.1X"]
end
CR -->|watches| OP
OP -->|renders| CFG
OP -.->|mounts| SEC
CFG --> FR
SEC -.-> FR
OP -->|scrapes| OBS
FR <-->|RADIUS
auth / acct / CoA| BNG
SUB <--> BNG
classDef crd fill:#0c0c0f,stroke:#22c55e,stroke-width:1px,color:#fafafa
classDef op fill:#0c0c0f,stroke:#22c55e,stroke-width:2px,color:#fafafa
classDef pod fill:#0c0c0f,stroke:#a1a1aa,stroke-width:1px,color:#fafafa
classDef edge fill:#0c0c0f,stroke:#71717a,stroke-width:1px,color:#a1a1aa
class CR crd
class OP op
class CFG,SEC,OBS pod
class P1,P2,P3 pod
class BNG,SUB edge
```
You declare what you want in YAML. The operator watches your CRDs, renders a complete FreeRADIUS config (`radiusd.conf`, `clients.conf`, sites and modules), mounts secrets from Kubernetes Secrets, and rolls out pods behind split-mode Services for auth / accounting / CoA — all with HPA, PDBs, and Prometheus metrics wired up. Your BNGs and NAS devices talk to the resulting Service exactly like any other RADIUS server.
## Why this exists
RADIUS is the quiet workhorse behind every ISP on the planet. Every PPPoE session, every IPoE lease, every DHCP hand-off, every CoA bandwidth change — it all flows through RADIUS and into a BNG. And yet in 2026, running AAA for a BNG fleet still means SSH'ing into pet VMs to hand-edit `radiusd.conf`, copy-pasting `clients.conf` across replicas every time a new OLT shows up, and rolling shared secrets by restarting RADIUS servers one at a time. HA is whatever you cobble together with keepalived and cron. CoA for live PPPoE sessions is an afterthought.
Kubernetes solved this for web apps a decade ago. This operator brings the same experience to ISP-grade RADIUS: declarative specs, GitOps-friendly rollouts, automatic config rendering, secret mounting, HPA, PDBs, split auth/accounting/CoA services, and Prometheus metrics — all behind three simple CRDs purpose-built for BNG subscriber AAA.
```yaml
apiVersion: radius.operator.io/v1alpha1
kind: RadiusCluster
metadata:
name: bng-aaa
spec:
image: freeradius/freeradius-server:3.2.3
replicas: 6
autoscaling:
enabled: true
minReplicas: 6
maxReplicas: 30
modules:
- name: sql
type: rlm_sql
enabled: true
sql:
dialect: postgresql
server: postgres.aaa.svc.cluster.local
port: 5432
database: radius
login: radius
passwordRef:
name: sql-db-credentials
key: password
services:
auth: { type: LoadBalancer }
accounting: { type: LoadBalancer }
coa: { type: LoadBalancer } # scale each independently
```
`kubectl apply -f` and you have a scaled, self-healing, observable RADIUS tier sitting behind your BNGs.
## How it compares
| | Hand-rolled FreeRADIUS | Helm chart | **This operator** |
|---|:---:|:---:|:---:|
| Declarative clients & policies as CRDs | — | — | **Yes** |
| Automatic config rendering + rollout | — | partial | **Yes** |
| Structured unlang policy engine | — | — | **Yes** |
| Secrets from K8s Secrets (not ConfigMaps) | manual | partial | **Yes** |
| HPA, PDB, split-mode services | manual | partial | **Yes** |
| Prometheus exporter + ServiceMonitor + alerts | manual | — | **Yes** |
| GitOps-native | manual | **Yes** | **Yes** |
Every backend you actually use is supported out of the box: SQL (MySQL, PostgreSQL, SQLite, MSSQL, Oracle, Mongo), LDAP, REST, Redis, Files, and EAP (TLS/TTLS/PEAP) — with shared connection-pool tuning.
## Quick Start
```bash
# 1. Install the operator (chart ships the CRDs, RBAC, Deployment, and metrics Service)
helm install freeradius-operator ./charts/freeradius-operator \
--namespace freeradius-system --create-namespace
# 2. Deploy a FreeRADIUS instance — either with Helm...
helm install bng-prod ./charts/freeradius-cluster \
--namespace radius-prod --create-namespace
# ...or straight from a ready-to-apply example
kubectl apply -f example/basic/
# 3. Watch it come up
kubectl get radiusclusters,radiusclients,radiuspolicies -A
```
> CRDs are installed from the operator chart's `crds/` directory and are **not** upgraded by `helm upgrade`. To update CRDs, re-apply `config/crd/` or the chart's `crds/` directory with `kubectl apply -f`.
### Two charts, two jobs
| Chart | Installs | When to use |
|---|---|---|
| [`charts/freeradius-operator`](charts/freeradius-operator/) | CRDs, RBAC, operator Deployment, metrics Service | Once per cluster. Owns the controller that watches and reconciles RadiusCluster / RadiusClient / RadiusPolicy resources. |
| [`charts/freeradius-cluster`](charts/freeradius-cluster/) | A RadiusCluster + any number of RadiusClients, RadiusPolicies, and inline Secrets | Once per FreeRADIUS instance. Thin pass-through around the CRD specs — every field of `RadiusClusterSpec` is available under `cluster.spec` in values. |
The workload chart is optional. If you prefer plain manifests or GitOps with Kustomize, apply files from [`example/`](example/) directly and skip the second chart entirely.
Ready-to-apply examples live in [`example/`](example/), organized by scenario:
| Example | What it shows |
|---|---|
| [`basic/`](example/basic/) | Minimal files-backed auth with VLAN assignment policy |
| [`sql/`](example/sql/) | PostgreSQL-backed auth with a tuned `rlm_sql` connection pool |
| [`rest-api/`](example/rest-api/) | Authentication via an external REST API |
| [`ldap/`](example/ldap/) | LDAP / Active Directory authentication |
| [`ha-redundant/`](example/ha-redundant/) | Redundant SQL failover with autoscaling and PDB |
| [`split-mode/`](example/split-mode/) | Independent scaling for auth, accounting, and CoA |
| [`raw-override/`](example/raw-override/) | Escape hatch for custom modules and raw unlang |
For a full walkthrough — deploying, scaling, managing clients and policies, troubleshooting, and observability — see the **[documentation](https://Work-Systems-Ltd.github.io/freeradius-k8s-operator/)**.
## Who is this for?
- **ISPs running BNGs at scale** — PPPoE, IPoE, DHCP option-82, CoA bandwidth changes, subscriber accounting. The primary use case.
- **WISPs and altnets** managing hundreds of OLTs, BNGs, and edge NAS devices across regions and POPs.
- **Network teams** running campus WiFi, 802.1X, or guest portals and tired of hand-editing config files.
- **Platform engineers** bringing legacy carrier-grade AAA into a GitOps workflow.
- **Homelabbers** who want real RADIUS without pets.
## Community
- **[Documentation](https://Work-Systems-Ltd.github.io/freeradius-k8s-operator/)** — getting started, concepts, CRD reference, guides, troubleshooting
- **[Discord](https://discord.gg/gKQz4kpM)** — chat with the maintainers and other operators
- **[Issues](../../issues)** — bug reports and feature requests
- **[Discussions](../../discussions)** — questions, ideas, show-and-tell
If this project saved you an afternoon of `radiusd.conf` wrangling, **give it a star** — it's the single biggest thing you can do to help others find it.
## Contributing
Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow, local kind setup, code standards, and PR guidelines. First-timers: look for issues labeled `good first issue`.
## License
Licensed under the [Apache License 2.0](LICENSE).
Built with care by [Work Systems Ltd](https://github.com/Work-Systems-Ltd) and contributors.