How to Install FreeRADIUS on Rocky Linux 10 with MariaDB for Network Authentication

Install FreeRADIUS on Rocky Linux 10 with MariaDB (SQL Auth)

RADIUS is the protocol behind most Wi-Fi WPA2/WPA3-Enterprise logins, 802.1X switch-port authentication, and many VPN gateways. FreeRADIUS is the most widely deployed open-source RADIUS server, and storing users in MariaDB makes it easy to manage accounts, groups, VLANs, and accounting records with ordinary SQL.

This guide installs FreeRADIUS 3.2 on Rocky Linux 10 (the same steps apply to AlmaLinux 10 and RHEL 10), connects it to MariaDB, adds test users, assigns VLANs through group attributes, opens the firewall for only the networks you choose, keeps SELinux enforcing, and tests everything with radtest.

Table of Contents

  1. How RADIUS authentication works
  2. Prerequisites
  3. Step 1: Enable CRB and install packages
  4. Step 2: Install and secure MariaDB
  5. Step 3: Create the RADIUS database
  6. Step 4: Enable the SQL module
  7. Step 5: Activate SQL in the virtual server
  8. Step 6: Generate test certificates
  9. Step 7: Add a client (NAS) and users
  10. Step 8: Start in debug mode and test
  11. Step 9: Run as a service
  12. VLAN assignment with groups
  13. Firewall and SELinux
  14. Password storage options
  15. Troubleshooting
  16. FAQ

1. How RADIUS authentication works

    +---------+   802.1X / WPA-Enterprise   +-----------------+
 | Client  | --------------------------> | NAS / Switch /  |
 | (laptop)|                             | Wi-Fi AP / VPN  |
 +---------+                             +--------+--------+
                                                  | RADIUS Access-Request
                                                  | UDP 1812 (auth), 1813 (accounting)
                                                  | shared secret between NAS and server
                                          +-------v--------+
                                          |  FreeRADIUS    |
                                          |  (radiusd)     |
                                          +-------+--------+
                                                  | SQL queries
                                          +-------v--------+
                                          |    MariaDB     |
                                          | radcheck       |
                                          | radreply       |
                                          | radusergroup   |
                                          | radacct ...    |
                                          +----------------+

The NAS (Network Access Server) is the device that asks FreeRADIUS to authenticate a user. It is not the end user’s computer. Each NAS needs an entry in clients.conf or the nas table, with a shared secret.

TablePurpose
radcheckPer-user check attributes (password, expiry)
radreplyPer-user reply attributes sent back to the NAS
radusergroupMaps users to groups
radgroupcheck / radgroupreplyCheck and reply attributes per group (VLAN, session limits)
radacctAccounting records (sessions, bytes, duration)
radpostauthLog of authentication attempts
nasDynamic client list (optional)

2. Prerequisites

RequirementDetail
OSRocky Linux 10 (AlmaLinux 10 or RHEL 10 work the same way)
Resources2 vCPU, 2 GB RAM minimum for a small deployment
AccessA user with sudo
NetworkA NAS device or test host that can reach UDP 1812/1813
SELinuxEnforcing (we keep it that way)

Update the system first:

sudo dnf -y update
cat /etc/os-release | grep PRETTY_NAME

3. Step 1: Enable CRB and install packages

On current Rocky Linux and AlmaLinux releases the FreeRADIUS MySQL/MariaDB driver (freeradius-mysql) is provided through the CRB (CodeReady Builder) repository, which is disabled by default. If you skip this step the install fails with No match for argument: freeradius-mysql.

sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --set-enabled crb
sudo dnf makecache

sudo dnf install -y freeradius freeradius-utils freeradius-mysql

Check what you got:

radiusd -v | head -3
rpm -q freeradius freeradius-mysql

Note: On RHEL itself, enable the repository with subscription-manager repos --enable codeready-builder-for-rhel-10-x86_64-rpms instead.

4. Step 2: Install and secure MariaDB

sudo dnf install -y mariadb-server
sudo systemctl enable --now mariadb
sudo mariadb-secure-installation

Answer the prompts to set a root password, remove anonymous users, and disallow remote root login.

5. Step 3: Create the RADIUS database

Generate a password for the database user and store it somewhere safe:

DB_PASS=$(openssl rand -hex 24)
echo "radius DB password: $DB_PASS"
sudo mariadb <<EOF
CREATE DATABASE radius CHARACTER SET utf8mb4;
CREATE USER 'radius'@'localhost' IDENTIFIED BY '${DB_PASS}';
GRANT ALL PRIVILEGES ON radius.* TO 'radius'@'localhost';
FLUSH PRIVILEGES;
EOF

Import the schema that ships with FreeRADIUS:

sudo bash -c "mariadb radius < /etc/raddb/mods-config/sql/main/mysql/schema.sql"
sudo mariadb radius -e "SHOW TABLES;"

You should see nas, radacct, radcheck, radgroupcheck, radgroupreply, radpostauth, radreply, radusergroup, and related tables.

6. Step 4: Enable the SQL module

FreeRADIUS enables a module by symlinking it from mods-available into mods-enabled.

sudo ln -s /etc/raddb/mods-available/sql /etc/raddb/mods-enabled/sql
sudo chgrp -h radiusd /etc/raddb/mods-enabled/sql

Edit the module configuration:

sudo vi /etc/raddb/mods-available/sql

Change these settings (the file is long; use search):

sql {
    # Default ships as rlm_sql_null, which connects to nothing
    driver = "rlm_sql_mysql"
    dialect = "mysql"

    server = "localhost"
    port = 3306
    login = "radius"
    password = "PASTE_DB_PASSWORD_HERE"
    radius_db = "radius"

    # Read NAS devices from the 'nas' table as well as clients.conf
    read_clients = yes
    client_table = "nas"

    mysql {
        # The default file ships with an active tls { } block pointing to
        # certificate files that do not exist. For a local socket connection,
        # comment out the whole tls block.
        #tls {
        #    ca_file = "/etc/ssl/certs/my_ca.crt"
        #    ...
        #}
    }
}

Validate the configuration syntax before going further:

sudo radiusd -XC
# Look for "Configuration appears to be OK"

7. Step 5: Activate SQL in the virtual server

Defining the module is not enough. The default virtual server must call sql in the right sections.

sudo vi /etc/raddb/sites-enabled/default

Make sure sql (or -sql, where the leading dash means “do not fail if the module is missing”) is uncommented in these sections:

SectionWhy
authorize { ... }Looks up the user’s password and attributes
accounting { ... }Writes session records to radacct
session { ... }Optional: simultaneous-use checks
post-auth { ... }Writes to radpostauth; also the Post-Auth-Type REJECT block

Quick check:

sudo grep -nE '^\s*-?sql\s*$' /etc/raddb/sites-enabled/default

If you use the inner-tunnel virtual server for EAP (PEAP, TTLS), apply the same authorize and post-auth changes in /etc/raddb/sites-enabled/inner-tunnel.

8. Step 6: Generate test certificates

Recent packages no longer create TLS certificates automatically, and the EAP module will refuse to load without server.pem.

cd /etc/raddb/certs
sudo make          # generates ca.pem, server.pem, client.pem and related files
sudo chown -R root:radiusd /etc/raddb/certs
sudo chmod 640 /etc/raddb/certs/*.pem /etc/raddb/certs/*.key 2>/dev/null

Production warning: These are test certificates for lab use. For real 802.1X deployments, issue the server certificate from your internal CA or a trusted CA, and distribute the CA certificate to clients so they can validate the server.

9. Step 7: Add a client (NAS) and users

Add a NAS. For a lab, the default localhost client in /etc/raddb/clients.conf (secret testing123) is enough. For a real access point or switch, add it to the nas table (because read_clients = yes):

sudo mariadb radius <<'EOF'
INSERT INTO nas (nasname, shortname, type, secret, description)
VALUES ('192.168.10.1', 'sw-core', 'other', 'REPLACE_WITH_LONG_RANDOM_SECRET', 'Core switch');
EOF

Use a long random shared secret per device. The same value goes into the switch or access point configuration.

Add a test user with a cleartext password attribute:

sudo mariadb radius <<'EOF'
INSERT INTO radcheck (username, attribute, op, value)
VALUES ('testuser', 'Cleartext-Password', ':=', 'TestPass123');
EOF

10. Step 8: Start in debug mode and test

Always run the first test in debug mode, where FreeRADIUS prints every decision to the terminal.

sudo systemctl stop radiusd
sudo radiusd -X

Wait for Ready to process requests. In a second terminal:

radtest testuser TestPass123 127.0.0.1 0 testing123

Expected result:

Sent Access-Request Id 123 from 0.0.0.0:41234 to 127.0.0.1:1812 length 79
        User-Name = "testuser"
        ...
Received Access-Accept Id 123 from 127.0.0.1:1812 to 127.0.0.1:41234 length 20

Try a wrong password to confirm rejection:

radtest testuser WrongPass 127.0.0.1 0 testing123
# Received Access-Reject

Press Ctrl+C in the debug terminal when finished. Test an accounting packet as well:

echo "User-Name=testuser, Acct-Status-Type=Start, Acct-Session-Id=abc123, NAS-IP-Address=127.0.0.1" \
  | radclient -x 127.0.0.1:1813 acct testing123

sudo mariadb radius -e "SELECT username, acctsessionid, acctstarttime FROM radacct;"

11. Step 9: Run as a service

sudo systemctl enable --now radiusd
sudo systemctl status radiusd --no-pager
sudo journalctl -u radiusd -n 30 --no-pager

12. VLAN assignment with groups

A common 802.1X use case is placing users on different VLANs based on their group. FreeRADIUS returns standard tunnel attributes to the switch.

sudo mariadb radius <<'EOF'
-- Group reply attributes for the "staff" group (VLAN 20)
INSERT INTO radgroupreply (groupname, attribute, op, value) VALUES
 ('staff', 'Tunnel-Type', ':=', 'VLAN'),
 ('staff', 'Tunnel-Medium-Type', ':=', 'IEEE-802'),
 ('staff', 'Tunnel-Private-Group-Id', ':=', '20');

-- Put the test user in that group
INSERT INTO radusergroup (username, groupname, priority) VALUES ('testuser', 'staff', 1);
EOF

Run radtest again and look for the three Tunnel-* attributes in the Access-Accept. Your switch must support dynamic VLAN assignment and have the VLAN defined locally.

13. Firewall and SELinux

firewalld. FreeRADIUS uses UDP 1812 (authentication) and 1813 (accounting). A predefined service covers both:

sudo firewall-cmd --permanent --add-service=radius
sudo firewall-cmd --reload

That opens the ports to every source in the active zone. A tighter option is a rich rule limited to your network devices’ subnet:

sudo firewall-cmd --permanent --remove-service=radius
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" service name="radius" accept'
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

For more recipes, see firewalld on Rocky Linux 10: Zones, Rich Rules & Real-World Recipes.

SELinux. Keep it enforcing. The packaged policy lets radiusd talk to MariaDB over its local socket. If you place the database on another host, check for denials:

sudo ausearch -m avc -ts recent | grep radiusd
sudo sealert -a /var/log/audit/audit.log   # if setroubleshoot is installed

Do not run setenforce 0 as a fix. Our SELinux troubleshooting guide for Rocky Linux 10 shows how to read denials and apply a targeted fix.

14. Password storage options

Cleartext passwords are the simplest way to start, and they are required for some authentication methods. Know the trade-offs before you go to production.

AttributeWorks withStored formNotes
Cleartext-PasswordPAP, CHAP, MS-CHAPv2, EAP-MD5, PEAP-MSCHAPv2Plain textMost compatible; protect the database tightly
NT-PasswordMS-CHAPv2, PEAP-MSCHAPv2NT hashCompatible with Wi-Fi PEAP; hash is weak by modern standards
SSHA2-256-Password (and similar salted hashes)PAP onlySalted SHA-2Safer at rest, but cannot be used with CHAP/MS-CHAP
Crypt-style hashesPAP onlySalted hashSame limitation

Choose according to the authentication methods your NAS devices and clients use. For PEAP-MSCHAPv2 Wi-Fi, you generally need Cleartext-Password or NT-Password. Restrict the radius database account to localhost, encrypt backups, and monitor access to radcheck.

15. Troubleshooting

SymptomCauseFix
No match for argument: freeradius-mysqlCRB repository disabledsudo dnf config-manager --set-enabled crb then reinstall
Failed to load certificate file server.pem / EAP won’t loadNo certificates generatedRun make in /etc/raddb/certs and fix group ownership
rlm_sql (sql): Failed to load driver / uses rlm_sql_nulldriver not changed in mods-available/sqlSet driver = "rlm_sql_mysql" and dialect = "mysql"
SQL connection fails with TLS or certificate errorsDefault tls { } block references missing filesComment out the tls block inside the mysql { } subsection
Access-Reject for a valid user, “No Auth-Type found”sql not enabled in authorize, or no password attributeUncomment sql in the site; check radcheck row and := operator
Ignoring request to auth address * port 1812 from unknown clientNAS not definedAdd it to nas table (restart needed) or clients.conf
Received packet from X with invalid Message-Authenticator / shared secret mismatchSecret differs on NAS and serverRe-enter the identical secret on both sides
Permission denied reading mods-enabled/sqlSymlink or file not readable by radiusd groupchgrp -h radiusd the symlink; chgrp radiusd the target
Can't connect to local MySQL server through socketMariaDB stoppedsystemctl status mariadb
Works in radiusd -X but not as a serviceDifferent environment, SELinux, or file permissionsCheck journalctl -u radiusd and ausearch -m avc
Packets arrive but no replyFirewallVerify firewall-cmd --list-all includes UDP 1812/1813 for your source subnet

Debug workflow: stop the service, run radiusd -X, reproduce the failure, and read the last 20 lines before the reject. FreeRADIUS shows exactly which module said no.

16. FAQ

Can I use PostgreSQL instead of MariaDB?
Yes. Install freeradius-postgresql, use the PostgreSQL schema under mods-config/sql/main/postgresql/, and set driver = "rlm_sql_postgresql" and dialect = "postgresql".

Which FreeRADIUS version will I get?
Rocky Linux 10 ships the FreeRADIUS 3.2 series in its repositories. Run radiusd -v to see the exact build.

Do I need a web interface?
No. Everything here works with SQL and the command line. If you want a GUI, daloRADIUS is a popular PHP front end that sits on the same database.

How do I monitor the server?
Export system and service metrics with Prometheus and Grafana; see Prometheus and Grafana on Rocky Linux 10. Also watch the radpostauth table for reject spikes.

Is cleartext password storage acceptable?
It is common and sometimes required for MS-CHAPv2-based methods. Compensate with a locked-down database, encrypted backups, and a dedicated database host for larger deployments.

Can I authenticate against Active Directory or LDAP instead?
Yes. Install freeradius-ldap (and Samba/winbind for ntlm_auth with AD) and configure the ldap module. The SQL setup above can still hold accounting data.

(Visited 1 times, 1 visits today)

You may also like