Version 1.60.4

Released: 2020-02-27

MySQL: New var: default_mysqldump_options=--single-transaction new

New variable for both Mysql/MariaDB mysqldump calls:


which is the internal default.

If you set or add this to the directadmin.conf, it will override the internal default.

This is meant to be the "base" set of optional variables.

The extra_mysqldump_options (blank by default) is for addition variables that you with to add, to compliment the base set of options.

We've added the --single-transaction option to avoid innodb locking issues.

The --skip-lock-tables has not been added to ensure data consistency.


Subdomain: per-sub php version selection new

Making use of the new subdomain DocumentRoot override file feature:

Subdomain DocumentRoot override file (TEMPLATES)

this file has been expanded to also support a php selection, eg:


There is not yet a GUI for this feature.

Requires allow_subdomain_docroot_override=1, which is already enabled by default.

Also requires at least 2 php versions to be enabled in the custombuild options.conf.



where the format will extend the existing data, and allow you to add:


depending on your settings in CustomBuild options.conf.

Where if you set php1_select=2, for example, this will make use of the:

php2_release and php2_mode, for this subdomain.


Contents of the file is one subdomain per line.

If you have, a sample line might look like:


or if there are also public_html/private_html overrides, it might look like:


where the data after the first = character is URL encoded.


The Enhanced style skins that insert a pre-made table will have the php version added in the DocumentRoot column, below any private_html/public_html overrides, if they exist.

Else, just the php override will be present.. and if no override exists for this subdomain at all, the "Default" value will be shown.


user_limit.txt: new tokens for which limit has been exceeded new

DirectAdmin 1.44.0 has a token for the user_limit.txt template:


However, if multiple limits are in the same tally, still only 1 REASON is offered.

This change is to compliment this feature by including the following tokens when a limit is hit:




Each token, set to yes, will only appear if that limit is reached.

As a reminder, the "exceeded" wording refers to the threshold in order to generate the warning email, not necessarily a 100% usage, diretadmin.conf settings in percents:




Create User: option to create User with crypted password new

When creating a User with one of the following commands:







When passing the "passwd" field, if you also set:


this will allow you to set:


during the account creation.

Useful when creating an account with an API, for a restore, when the plain-text password is not known, for one example.

Allow per-reseller user_limit.txt new

The new check order for a given User's limit has been exceeded.

  1. /usr/local/directadmin/data/users/CREATOR/user_limit.txt

  2. /usr/local/directadmin/data/data/templates/custom/user_limit.txt

  3. /usr/local/directadmin/data/data/templates/user_limit.txt

Where #1 is the new check.

Compile time: Feb 21 2020 at 00:03:12+

Default Change: pointers_own_virtualhost=1, system_user_to_virtual_passwd=1 on new installs new

Default changes for new installs:



set in the data/templates/directadmin.conf.

Existing installs will not be affected.

DNS: action=dns&do=add|delete: allow domain to be sub-value, DA will find the parent zone new

We already have task.queue commands, which allow for adding/removing records, eg:

echo 'action=dns&do=add&' >> /usr/local/directadmin/data/task.queue

which would add an CNAME:

smtp CNAME mail

This change allows DA to do some work if you're not 100% sure where the closest zone is.. say a subdomain is a full zone or just an A record in a parent zone.

So for example, say you wanted to do something similar:


where you wanted the CNAME effective value, but don't want to hunt if there's a zone or zone.

If sub is a subdomain under the zone (just an A record), then for the above command, DA will notice there is no file, and find the to use.

The resulting values would internally be converted to:


where DA:

  1. Moves from left to right, to find the lowest zone.. in this case '' and sets the domain as such.

  2. for the name, if there is no trailing dot, the removed leading domain portion is appended to the end of the name

  3. for the value, if there is no trailing dot, the removed leading domain portion is appended to the end of the value

2 and 3 only apply to types CNAME, NS, and MX records.



if you're curious to see how DA converts the domain,name, and value, you can add:


to your task.queue request and DA will output the effective data, eg:

[root@es6-64 directadmin]# echo 'test=yes&action=dns&do=add&' > data/task.queue.cb; ./dataskq d530 --custombuild

Debug mode. Level 530

root priv set: uid:0 gid:0 euid:0 egid:0

pidfile written

starting queue

dataskq: command: test=yes&action=dns&do=add&

Named::taskq_dns: found local sub-zone from

Loaded parameters for add

 0: action=dns

 1: do=add



 4: test=yes

 5: type=CNAME


done queue

[root@es6-64 directadmin]#

User limit check locking fixed

Improved locking for possible race conditions on some User limits.

Locks will be created under the:


where %s is replaced with the area being worked on.

If there are any stray locks (there shouldn't be), will be void after they're 60 seconds old, and will be overwritten by the next process trying to get that lock.

Credit: phnix_sec


./ not swapping snidomains fixed

The /etc/virtual/snidomains must swap the username if called by


Compile time: Feb 10 2020 at ~22:53:06

Better User deletion accountability logging fixed

To help in debugging who deleted what User when, in addition to the logs already added to the system.log, extra info for where the deletion came from has been added.

This saves the need for cross-referencing the 2020-Feb-08.log style request logs, which can be off by a few seconds.


2020:02:12-00:30:23: User deleteuser removed by admin: accountability='Command call 1: caller=admin ip= api=0'

There are other ways to delete Users, such as via the task.queue during a background-push (in case the account is too large), so in that event, it would reference the dataskq, instead of the Command call.


phpMyAdmin User SSO: use per-db format fixed

For DA User phpMyAdmin one-click SSO logins that can view all current DBs, instead of using user_\% in the mysql.db column, duplicate the da_sso user for each DB and access host.


Custom hook filtering (SECURITY) fixed

Extra checks when calling custom hooks.

Details intentionally left blank.

Credit: Bartosz Kwitniewski

PMA_SSO: remote mysql server caused blank page fixed

Fix for the phpMyAdmin single-sign-on in both custombuild and directadmin:

  1. If custombuild (rev: 2408+) notices the conf/mysql.conf has a host value set in it, it will now also regex the phpMyAdmin/direct_login/index.php to swap out the localhost value, which gets set in the SSO session.

  2. DirectAdmin will now add it's own server IP as an access host, if the conf/mysql.conf does not have host=localhost, and assuming "access_host" isn't set, just as a fallback for this case.

When a remote host is used and the access_host IS present, then DA relies on this value entirely (plus access_host1, access_host2, etc,, if set)

Be sure to:

./build update

./build version

./build phpMyAdmin

after getting the latest build and DA binaries.

View the direct_login/index.php file, to ensure the $host value was swapped to the host value set in the /usr/local/directadmin/conf/mysql.conf.

CUSTOM token not setting tokens for other CUSTOM tokens fixed

If you're using, for example:


with code, say:


#some code


and then you go to:

Admin Level -> Custom Httpd Config ->

and add this in the CUSTOM token:


The tokens available just before the call to, would have had:


but YOURDOMAINFLAG would not have been set into the available tokens until the CUSTOM token is actually inserted into the template.



Changed the code around so it's tokenzing the CUSTOM token right away, so immediately after the Custom Httpd Config CUSTOM token is loaded, the available (related) tokens would look like:



So that when the call to is made, YOURDOMAINFLAG is actually ready to be checked, and "#some code" gets inserted correctly.

Before the fix, the CUSTOM value wasn't tokenzied, it was raw text, and the if-then-endif was never processed.



subdomain documentroot override: path enforcement and backup/restore fixed

Relating to feature:

Subdomain DocumentRoot override file (TEMPLATES)

The file at this location, if exists:


will be backed up to the location:


And during the restore, if subdomains are selected, will be restored back to the original location.

However, the file is not directly copied.

Each value is sanitized, such that the public_html/private_html paths, if set, must be under /domains/.

You can point your subdomains to other domains under this user, but must be below the ~/domains folder.

DNS: Allow reading/viewing of $GENERATE records fixed

The DNS class is now able to read $GENREATE style records.

They can be viewed in the dns manager.

It will not currently let you add them, so if you need them, manually add them to the zone.

This may change in a future release.



DNS: SPF: change User IP to do a surgical swap fixed

Previously, the "Change IP" for User would rely on the default dns_txt.conf to during an IP swap, losing any customization of the TXT spf record.

This change will break the SPF record into chunks, go through each one to decide if that chunk should be swapped to the new IP or not.

For the default case where there's only 1 listed ip4: where is the server IP, this will remain as it is, even if the zone was on and is being moved to

However, any other values, or repeated server IP values will be swapped correctly, and other settings such as include, ranges, or -all, will be respected.

If the new IP is an IPv6, and the old ip4: is present (where might be the domain's IP, but not the server IP), the ip4: will be swapped to ip6:<ipv6value>

Usually, you're not going to need to have your domain's IP listed here, as the "a" part of the spf value will also do this lookup.

So the main benefit will just be to maintain any other settings, but also to swap matched IPs, when possible (while maintaining the server IP if was there)


Last Updated: