The following modules have been changed.


The SQL configuration has been moved from sql.conf to mods-available/sql. The sqlippool.conf file has also been moved to mods-available/sqlippool.

The SQL module configuration has been changed. The old connection pool options are no longer accepted:


Instead, a connection pool configuration is used. This configuration contains all of the functionality of the previous configuration, but in a more generic form. It also is used in multiple modules, meaning that there are fewer different configuration items. The mapping between the configuration items is as follows:

num_sql_socks			-> pool { max }
connect_failure_retry_delay	-> pool { retry_delay }
lifetime			-> pool { lifetime }
max_queries			-> pool { uses }

The pool configuration adds a number of new configuration options that allow the administrator to better control how FreeRADIUS uses SQL connection pools.

The following parameters have been changed:

trace				-> removed
tracefile			-> logfile

The logfile is intended to log SQL queries performed. Use debugging mode to debug the server. If logfile is set, then all SQL queries will go to logfile.

A NULL SQL database can now be used:

driver = rlm_sql_null

This is an empty driver that will always return "success". It is intended to be used to replace the sql_log module and to work in conjunction with the radsqlrelay program. Simply take the normal configuration for raddb/mods-enabled/sql and set:

driver = rlm_sql_null
logfile = ${radacctdir}/sql.log

All of the SQL queries will be logged to that file. The connection pool does not need to be configured for the null SQL driver. It can be left as-is, or it can be deleted from the SQL configuration file.


The rlm_sql_sybase module has been renamed to rlm_sql_freetds, and the old rlm_sql_freetds module has been removed.

rlm_sql_sybase used the newer ct-lib API, and rlm_sql_freetds used an older API and was incomplete.

The new rlm_sql_freetds module now also supports database selection on connection startup so use statements no longer have to be included in queries.


Queries for post-auth and accounting calls have been re-arranged. The SQL module will now expand the reference configuration item in the appropriate sub-section and resolve this to a configuration item. This behaviour is similar to rlm_linelog. This dynamic expansion allows for a dynamic mapping between accounting types and SQL queries. Previously, the mapping was fixed. Any "new" accounting type was ignored by the module. Now, support for any accounting type can be added by just adding a new target, as below.

Queries from v2.x.x may be manually copied to the new v3.0 dialup.conf file (raddb/sql/main/<dialect>/queries.conf). When doing this, references may also need to be updated to the accounting tables, as their definitions will now be outside of the subsection containing the query.

The mapping from old "fixed" query to new "dynamic" query is as follows:

accounting_onoff_query		-> accounting.type.accounting-on.query
accounting_update_query		-> accounting.type.interim-update.query
accounting_update_query_alt		+> accounting.type.interim-update.query
accounting_start_query		-> accounting.type.start.query
accounting_start_query_alt		+> accounting.type.start.query
accounting_stop_query			-> accounting.type.stop.query
accounting_stop_query_alt		+> accounting.type.stop.query
postauth_query			-> post-auth.query

Alternatively a 2.x.x config may be patched to work with the 3.0 module by adding the following:

accounting {
	reference = "%{tolower:type.%{Acct-Status-Type}.query}"
	type {
		accounting-on {
			query = "${....accounting_onoff_query}"
		accounting-off {
			query = "${....accounting_onoff_query}"
		start {
			query = "${....accounting_start_query}"
			query = "${....accounting_start_query_alt}"
		interim-update {
			query = "${....accounting_update_query}"
			query = "${....accounting_update_query_alt}"
		stop {
			query = "${....accounting_stop_query}"
			query = "${....accounting_stop_query_alt}"

post-auth {
	query = "${..postauth_query}"

In general, it is safer to migrate the configuration rather than trying to "patch" it to make it look like a v2 configuration.

Note that the sub-sections holding the queries are labelled accounting-on (hyphen) and not accounting_on (underscore). The reason is that the names of these sections are taken directly from the Accounting-Request packet and the Acct-Status-Type field. The sql module looks at the value of that field and then looks for a section of that name in order to find the query to use.

That process means that the server can be extended to support any new value of Acct-Status-Type simply by adding a named sub-section and a query. This behaviour is preferable to that of v2, which had hard-coded queries for certain Acct-Status-Type values and ignored all other values.


The LDAP module configuration has been substantially changed. Please read raddb/mods-available/ldap. It now uses a connection pool, just like the SQL module.

Many of the configuration items remain the same, but they have been moved into subsections. This change is largely cosmetic, but it makes the configuration clearer. Instead of having a large set of random configuration items, they are now organized into logical groups.

The old LDAP configuration will need to be migrated manually to the new configuration. Simply copying the old configuration WILL NOT WORK.

Users upgrading from 2.x.x who used to call the ldap module in post-auth should now set edir_autz = yes and remove the ldap module from the post-auth section.

rlm_ldap and LDAP-Group

In 2.x.x the registration of the LDAP-Group pair comparison was done by the last instance of rlm_ldap to be instantiated. In 3.0 this has changed so that only the default ldap {} instance registers LDAP-Group.

If <instance>-LDAP-Group is already used throughout your configuration, then no changes will be needed.

rlm_ldap authentication

In 2.x.x the LDAP module had a set_auth_type configuration item that forced Auth-Type := ldap. This was removed in 3.x.x as it often did not work and was not consistent with the rest of the server. It is generally recommended that LDAP should be used as a database and that FreeRADIUS should do authentication.

The only reason to use Auth-Type := ldap is when the LDAP server will not supply the "known good" password to FreeRADIUS and when the Access-Request contains User-Password. This situation happens only for Active Directory. Forcing Auth-Type := ldap in other situations is very likely to be wrong.

The following is an example of what should be inserted into the authorize {} and authenticate {} sections of the relevant virtual-servers to get functionality equivalent to v2.x:

authorize {
  if ((ok || updated) && User-Password) {
    update control {
      Auth-Type := ldap

authenticate {
  Auth-Type ldap {


The EAP configuration has been moved from eap.conf to mods-available/eap. A new pwd subsection has been added for EAP-PWD.

rlm_expiration & rlm_logintime

The rlm_expiration and rlm_logintime modules no longer add a Reply-Message; the same behaviour can be achieved by checking the return code of the module and adding the Reply-Message with unlang.

if (userlock) {
	update reply {
		Reply-Message := "Your account has expired"


The unix module does not have an authenticate section. Thus, Auth-Type := System cannot be set. The unix module has also been deleted from the examples in sites-available/. Listing it there has been deprecated for many years.

The PAP module can do crypt authentication. It should be used instead of Unix authentication.

The Unix module can still pull the passwords from /etc/passwd or /etc/shadow. This is done by listing it in the authorize section, as is done in the examples in sites-available/. However, some systems using NIS or NSS will not supply passwords to the unix module. For those systems, it is recommended to put users and passwords into a database, instead of relying on /etc/passwd.