# ToughRADIUS is a RADIUS server with an EAP registry and a web console

> ToughRADIUS is a Go RADIUS server for ISPs, enterprise networks and carriers, with a pluggable EAP handler registry covering EAP-MD5, EAP-MSCHAPv2, EAP-TLS, PEAPv0 and EAP-TTLS, RadSec over TLS, and a React admin interface. It suits an operator running 802.1X access, and it carries a clear warning about the older MS-CHAP based methods.

**talkincode/toughradius** — A powerful, open-source RADIUS server designed for ISPs, enterprise networks, and carriers. Supports standard RADIUS protocols, a full EAP / 802.1X authentication suite (EAP-TLS, PEAPv0/EAP-MSCHAPv2, EAP-TTLS), RadSec (RADIUS over TLS), and a modern Web management interface.

- Repository: https://github.com/talkincode/toughradius
- Website: http://www.toughradius.net/
- Stars: 695 · Forks: 300
- Language: Go
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/talkincode-toughradius

## The EAP handler registry is the part that distinguishes it

A pluggable EAP handler registry covers both challenge and tunneled methods, and that is the mechanism the project is built around. Five handlers are registered out of the box. eap-md5 is a challenge method and the default, described as a password challenge under RFC 3748. eap-mschapv2 is an MS-CHAPv2 password challenge. eap-tls is a tunneled certificate method doing certificate based mutual authentication with a TLS handshake, fragmentation reassembly and certificate to identity mapping under RFC 5216. eap-peap is PEAPv0 with inner EAP-MSCHAPv2, aimed at Windows and AD networks. eap-ttls is a TLS tunnel carrying inner PAP or MS-CHAPv2 under RFC 5281, and the documentation gives its purpose as onboarding LDAP and legacy credential stores without a per client certificate rollout. Two settings control the behaviour. radius.EapMethod sets the preferred method offered on EAP-Identity and defaults to eap-md5, and radius.EapEnabledHandlers is a comma separated allow list, with an asterisk to enable all registered handlers. That combination lets an operator disable unwanted methods without interrupting the service.

## The documentation tells you to prefer EAP-TLS over the legacy methods

The compatibility note is worth reading twice, because a security tool that quietly recommends a weak method is a liability. PEAP and EAP-MSCHAPv2 are described as compatibility-first methods, and MS-CHAPv2-style exchanges carry an NTLMv1-like attack surface, with a pointer to Microsoft guidance. The advice is to use them to serve legacy devices and AD users, and to prefer EAP-TLS for new deployments where you control the client certificate estate. A second warning repeats the point for the configuration keys, naming eap-mschapv2, eap-peap and TTLS inner MS-CHAPv2 as compatibility-oriented and carrying the same attack surface. The default of eap-md5 deserves a note of its own for the same reason, since it is a challenge response over an unencrypted RADIUS transport. A deployment that leaves the defaults alone inherits the weakest options in the list.

## RadSec and the standard ports are the network surface you must plan

The protocol support is broad on paper. Standard RADIUS gets full support for the RFC 2865 and RFC 2866 authentication and accounting protocols. RadSec is TLS encrypted RADIUS over TCP under RFC 6614. Multi-vendor support is claimed for major network devices including Cisco, Mikrotik and Huawei, and there is a multi-vendor VSA capability listing Huawei, Mikrotik, Cisco and H3C. The configured ports come from the radiusd section, and the values are the standards. The authentication port is 1812, the accounting port is 1813, and RadSec uses 2083, while the web management interface listens on 1816. The configuration binds the RADIUS listener to 0.0.0.0, so the host firewall is the boundary that matters. Note that the classic RADIUS ports carry the shared secret in clear text inside the datagram, which is the reason RadSec exists, and an operator who enables both should think about which devices can actually speak RadSec.

## Configuration is one YAML file, and production mode has guard rails

The runtime configuration is a single YAML file. You copy the template and edit the copy, and the file is laid out in four blocks. The system block carries the appid, the location and the workdir, which is where runtime data is written. The database block selects sqlite or postgres, and the commented lines show the PostgreSQL host, port, user and password keys. The radiusd block enables the service and sets the host and the three ports. The web block sets the management interface host and port. The guard rails are the interesting part. For any deployment exposed beyond a local development host, the documentation says to set web.secret or TOUGHRADIUS_WEB_SECRET to a long random value before starting, because it signs the management API JWTs. Production mode, meaning system.debug=false or logger.mode=production, refuses to start when the built-in placeholder or an empty JWT secret is still configured. The environment variable file carries the same keys in a TOUGHRADIUS_ prefixed form, including a separate TLS listener on 1817.

## The admin account is bootstrapped with a generated password, not admin

The bootstrap story is handled carefully and is a good sign about how the project thinks about default credentials. The username is admin, and the password is generated on first start and written to a file under the work directory named admin-bootstrap-password, with mode 0600, and the documentation states plainly that it is never toughradius. If you want to pick the initial password yourself, you set TOUGHRADIUS_ADMIN_PASSWORD before the first start. Lost passwords can be reset with cmd/reset-password. Upgrades that still carry the historical default password rotate it automatically and log the replacement once. The design point is that there is no well known default password to guess, which matters for a service that is by default listening on all interfaces and that holds the credentials for your network users. It also means your deployment checklist has to include reading that file on first boot, because the password is not in the interface you will open in a browser.

## Building it means a frontend build and a Go build

The prerequisites are Go 1.25 or later for building from source, PostgreSQL or SQLite, and Node.js 18 or later for frontend development. The documented build sequence clones the repository, installs and builds the web frontend with npm, then compiles the backend:

```bash
# Clone repository
git clone https://github.com/talkincode/toughradius.git
cd toughradius

# Build frontend
cd web
npm install
npm run build
cd ..

# Build backend
go build -o toughradius main.go
```

Pre-compiled versions are also published on the releases page, which is the faster route for a first evaluation. The Go module metadata records a module path of github.com/talkincode/toughradius/v9 and a Go directive of 1.26.0, and the dependency set shows the shape of the server. The Echo framework and echo-jwt handle the HTTP and management API layer, GORM with a PostgreSQL driver and a pure-Go SQLite driver cover storage, robfig/cron schedules recurring work, and panjf2000/ants provides the worker pool. The LDAP client, layeh.com/radius, gocarina/gocsv and the excelize library cover directory backends, CSV and spreadsheet import.

## The Docker image crosses compile platforms and drops the binary into Alpine

The Dockerfile in the repository shows a three stage build that is designed for multi architecture images. The first stage builds the React frontend on node:20-bookworm, running npm ci and then npm run build, with a directory listing printed at the end. The second stage compiles the server on golang:1.26-bookworm using the TARGETOS and TARGETARCH build arguments, copying the frontend output in first and then verifying that the built admin page exists with a test on the file, failing the build if the frontend is missing. The Go build is done with CGO_ENABLED=0 and static external linker flags. The final stage is alpine:latest with curl, ca-certificates and tzdata added, the binary copied to /usr/local/bin and made executable, and the ports exposed explicitly. The comment lists them: 1816 for the web and admin API over TCP, 1812 and 1813 for RADIUS authentication and accounting over UDP, and 2083 for RadSec over TCP. The entrypoint is the binary itself, so container orchestration passes the config through arguments.

## Where ToughRADIUS is the wrong tool

Three situations argue against it. The first is a small deployment with simple needs. If you have a handful of access points and want PAP or CHAP with a shared secret and a user list, the configuration surface here, with a web console, a JWT secret, a bootstrap password, a database choice and a plugin registry, is larger than the job. The second is an environment where you cannot run Postgres or SQLite with the privileges this service wants, since the accounting and audit history grows and the accounting port writes continuously, and SQLite is a convenience rather than a plan for a carrier scale deployment. The third is a team that is uncomfortable with the legacy methods. The project ships EAP-MD5 as the default and supports MS-CHAPv2 in three places, and while the documentation is honest about the risk, the presence of those handlers means your configuration and your review process have to account for them. A hardened alternative in the same family is to use a server that only offers certificate based methods and refuse to register the rest, which is the configuration ToughRADIUS supports through its allow list but does not enforce by default.

## Conclusion

Adopt ToughRADIUS when you are an operator who needs 802.1X and RADIUS accounting across mixed vendor gear, and steer to it for EAP-TLS deployments where you control the client certificate estate. Skip it if your requirements are limited to PAP or CHAP on a handful of devices, where the configuration surface is larger than the job. Verify first which EAP handlers you enable in radius.EapEnabledHandlers, and set web.secret or TOUGHRADIUS_WEB_SECRET to a long random value before any deployment beyond a local host, because production mode refuses to start with the placeholder secret.

## FAQ

### Which EAP methods does ToughRADIUS support?

The registered handlers are eap-md5, eap-mschapv2, eap-tls, eap-peap and eap-ttls. The first two are challenge based, the last three are tunneled, with eap-tls doing certificate based mutual authentication and eap-ttls carrying inner PAP or MS-CHAPv2 for onboarding legacy credential stores.

### How do I choose which EAP methods ToughRADIUS offers?

Set radius.EapMethod for the preferred method offered on EAP-Identity, which defaults to eap-md5, and radius.EapEnabledHandlers as a comma separated allow list, for example eap-md5,eap-mschapv2,eap-tls, or an asterisk to enable all registered handlers.

### What is the initial admin password for ToughRADIUS?

The username is admin and the password is generated on first start, written to admin-bootstrap-password under the work directory with mode 0600, and it is never toughradius. You can choose it yourself by setting TOUGHRADIUS_ADMIN_PASSWORD before the first start, and reset a lost one with cmd/reset-password.

### Which ports does ToughRADIUS use?

The RADIUS authentication port is 1812, the accounting port is 1813, RadSec uses 2083, and the web management interface listens on 1816. The environment file also defines a separate management TLS listener on port 1817.

### Is ToughRADIUS still maintained?

The repository is not archived and the last push was on 2026-10-16, with releases v9.4.0 on 2026-10-08, v9.3.0 on 2026-08-11 and v9.2.0 on 2026-07-15. The licence is MIT, and the Go module path is github.com/talkincode/toughradius/v9.

## Sources

- [License: MIT](https://github.com/talkincode/toughradius/blob/main/LICENSE)
- [Project website](http://www.toughradius.net/)
- [README](https://github.com/talkincode/toughradius/blob/main/README.md)
- [Releases](https://github.com/talkincode/toughradius/releases)
- [talkincode/toughradius on GitHub](https://github.com/talkincode/toughradius)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/talkincode-toughradius
