Version 1.41.0

Released: 2012-06-10

MAILTO for cronjobs (SKINS) new

New field in cronjobs area allowing Users to set option for cron output.

Valid values would be:

username (DA login)

and a blank value (no spaces, no characters), where DA will set:


so no email is generated for any crons.



add new table/form:

<table class=list  cellpadding=3 cellspacing=1>
<form action='/CMD_CRON_JOBS' method='POST'>
<input type=hidden name="action" value="saveemail">
<tr><td class=listtitle colspan=2>Send all Cron output to E-Mail</td></tr>
<tr><td class=list align=left>E-Mail</td><td class=list><input type=text name=email size=48 value="|MAILTO|"></td></tr>
<tr><td class=listtitle colspan=2 align=right><input type=submit value="Save"></td></tr>

CMD_LOGIN_KEYS to Reseller/User Packages (SKINS) ** Manditory Skin Changes ** new

Option CMD_LOGIN_KEYS in the skins.

During the DA update, the will automatically run:

echo "action=addoptions" >> /usr/local/directadmin/data/task.queue

This task will go through all user.conf, reseller.conf and package files.

If the directadmin.conf has login_keys=1, then all of the above files will receive:


else, if login_keys=0 is in the directadmin.conf, then all files will receive:


Note that the internal default in DA is:


even if no value for login_keys is present in the directadmin.conf

Failure to use update skins will result in login_keys being turned off in a package or user.conf/reseller.conf file.

This would disable login_keys for that User.









All files essentially have this 1 line addition after System Info:

<tr><td class=list>Login Keys</td><td class=list align=center><input type=checkbox name=login_keys value="ON" |LOGINKEYSCHECKED|></td><td class=list></td></tr>

user/show_domain.html will have something like:

<a href="/CMD_LOGIN_KEYS">Login Keys</a>

CMD_ADDITIONAL_DOMAINS to list multi-ips new

Related to:


If API is used, add "ips=yes" to the list, to get the IPs, eg:



will be set.

If "no" value is present, then no other values will be available.

If "yes", then you'll see IPs in a double encoded list, eg:



so you'll need to decode the above variables again to list the IPs.

Sample output:


Where, decoded once, it will give you these variables (some of the above output is ignored for the description below):

assigned_ips = assigned_ips0=1:2:0:0:0:0:0:8&assigned_ips1=
available_ips = available_ips0=1:2:0:0:0:0:0:9&available_ips1=
user_ips = user_ips0=1:2:0:0:0:0:0:8&user_ips1=1:2:0:0:0:0:0:9&user_ips2=
shared_ips = shared_ips0=
owned_ips = shared_ips0=
free_ips = shared_ips0=

ignore the example values, as they may not be accurate.

Note that the shared_ips list will also include the server IP, should it be available.

assigned_ips is the list of IPs current assigned to the domain.

available_ips is the list of IPs which can be assigned to the domain.

DEPRECATED: ssl_ignore_when_local new

DEPRECATED: as of 1.62.0

Instead, use a 2nd port for ssl (2222), and main port for non-ssl (2223), eg:

cd /usr/local/directadmin
./directadmin set port 2223
./directadmin set ssl 0
./directadmin set ssl_port 2222
service directadmin restart

and use 2223 for non-ssl, and 2222 for ssl connections.


Option which lets you tell DA to disable ssl if a connection is made on localhost.

The logic is somewhat backwards in that it currently only checks the connecting IP, which will be, if you're connecting to, so ensure you're using that, and not ::1...

as it's been found that the "from" IP, when connecting to ::1 is not ::1 or, but rather the main server IP, which is not considered "local", so this feature doesn't work if your API script is connecting to ::1.

The correct method for this would be to check the sockets themselves to figure out which IP was being connected to, instead of from.

That way we could check if was connected to, or ::1 was connected to, however that code does not currently exist in DA, so DA (At this time) only check the "from" address.. which is going to be anyway, so as long as people are aware of this, it should be ok the way it is.

DNS Admin column for local mail new

Similar to Local Data, a new column will be added to:

Admin Level -> DNS Admin

to determine if the domain is present in the file:


this will help determine quickly if the MX records should be pointing to an external location or not.. or if a User has made an error by unchecking the option.

The column will be labeled:

Local Mail



Some text fields will support AJAX autofill.

At the moment, it's only setup on:

Admin/Reeller Level -> Change Passwords

The internal default for the directadmin.conf is:


If you want to test this new feature, turn it on with:


and restart DA.

IMPORTANT For skin designers:

Please don't start development with these functions yet, as there is a high likelihood of them changing for a future release of DA.

I'm not 100% satisfied with the static output from CMD_AJAX_USERS quite yet.

It may change to be just the usernames, and the javascript/html bits added at the browser level, instead of in DA.

Removed NameVirtualHost from ips.conf if Apache 2.4 is used new

When the file:


is rewritten, DA will now check the contents of:


If the following is found:


(2.4 or higher), then DA will not add the NameVirtualHost entires to the ips.conf file.

Ability to exclude DB data from backup, but include DB Settings (SKINS) new

New option for backups allowing Admin Backup/Transfer and User Site Backup to chose if they want the database data included in the backup.

The old option "Databases" is renamed "Database Settings". All variable names remain the same for this checkbox.

New option called "Database Data" specifies the inclusion of the actual sql data.

DB Settings includes Users, passwords, access hosts, etc..

The "DB Data" is the sql data.

If the DB Data is selected, the DB Settings must be selected (javascript is used to enforce this)

The settings can be selected, and the data not selected, giving the backup the skeleton of the database setup, without any tables or data.

This is useful if you need to transfer a User account to a different server with a large database, and need to transfer the sql data manually (bypassing the DA backup system)

During the update, the old dataskq command:


is run to update the:


to add:


to each cron.. and if the option10=database was present, DA will add option11=database_data.

The database_data_aware option is needed to ensure that when the update is run a 2nd time, if the database_data is missing, it stays missing, as it would be the desired state at that point.

Backup files also change slightly.

The file:


will also have a new option:


if created by this version of DA.

It's needed to tell DA if the backup was created before or after this feature was added.

If database_data_aware does not exist in the backup_options.list, then if database exists, database_data is added internally.

If database_data_aware does exist, and backup, and database exist, but database_data does not, then the sql files will not be restored.

The user_db.conf files will be restored.






The forms to create a backup need the following added:

<input type=hidden name="form_version" value="2">

as well as:

<input type=checkbox name=option11 value="database_data" |DATABASEDATAON| onClick='setSelectedData(); if (this.checked == true) { document.tableform1.option10.checked = true; }'>

A change is needed for the existing "database" checkbox:

<input type=checkbox name=option10 value="database" checked onClick='setSelectedData(); document.tableform1.option11.checked = this.checked;'>

The form_version=2 tells DA that these options exist in the form.

Without form_version=2, DA will assume the skin is old, and if "database" is passed, then database_data is internally turned on.

Ability to reset today's email usage count to allow more sends new

Feature to allow the reset of the current day's email sends, to allow more emails to be sent out.

The file:


exists if the:


file is set to something other than 0, and email has been sent.

Once the usage file becomes the size of the limit, then emails can no longer be sent out.

A new button, located at:


will appear next to:

Sent Emails

if the usage file exists, and the currently logged in user is an Admin (only Admins can use this feature)

The button will read:

Reset Today

For both Resellers and Admins, the "Current Usage" column for "Sent Emails", to the right of the number, it will show:

(Today: 25)

where 25 is showing the size of the usage file.

When you click the "Reset Today" button, the usage file is deleted.

The (Today: 25) text will then disappear, indicating that the count is reset.

Once the User starts to send emails again, this number will show up again in realtime (for each page load)

FileManager icons upgraded and set to transparent png (SKINS) new

Minor changes to the images in the 3 DA skins.

The 4 new files for folder and files have been upgraded to png files, as png's allow for transparency.

This lets us change the background color while having the matching background in the icon (since each line has a different bg color)

While I was at it, I made them look much nicer, including the alpha channel for the shadows (bg color can go through the shadow).

The changes are quite minor, but make it look much more polished, and is far more flexible for different colors/skins.

There are 4 new files:


These will replace the gif versions in the files_user.conf:


I've left the gif files, in case they're being linked to by other language packs, or skins.

Also, the icon column in the FileManager also has align=center in it's <td> tag, to line up the icons in the center of the column.

Added |?HEADER| support to lost_password_email.txt new

Similar to many other email txt files, I've added support to the template file:


such that the top of the file can have:

|?HEADER=Content-Type: text/plain; charset=iso-8859-2|


ability to add your own email headers in welcome messages

Ability to suppress BFM messages new

As brute force attacks are fairly common, and the tools to prevent those attacks are fairly reliable, some admins do not wish to be told about every case of attacks.

Since the trigger of the only happens with notices, I've added an option to prevent the sending of the notices, but still call the scripts normally to block the IP.

The directadmin.conf option will be:


which is the internal default (option disabled, notifications shown)

If you wish to prevent notices from being sent out, but still have the IPs blocked, then set this in your directadmin.conf:

hide_brute_force_notifications=1 new

Custom script which is called after a DirectAdmin tar.gz backup restore fails.

Script will be at:


Variables to be passed to the script:


Note that owner and source_path will be empty strings if the restore is triggered by the User (User Level -> Create/Restore Backups)

So be sure to check if owner is blank before trying to use the source_path (check it too).

If they are blank, then it's likely going to be:


Note that the reason will include the <br>\ characters in it, as inserted into DA's message.

Display time of last DA restart (SKINS) new

Admin Level -> Admin Settings

will now display the time when DA was last restarted.

This can help determine if DA was restarted after a DA update, or license update.



add this to bottom table:

<tr><td class=list>Last Restart</td><td class=list>|startup_time|</td></tr> and new

Pre/post hook scripts, triggered when the lnk:


is create or set (happens fairly often).





username=bob  #value link is being set to.  #value which is set in the user.conf
old_public_html_link=1|0   #value from the directadmin.conf, will usually be set to 1.  The 0 method is a directory.
apache_public_html=1|0   #Usually will be 0.   Old value of 1 was from when the public_html was chgrp to apache.

If you exit with a non-zero value from, then the entire process will be skipped.

Note that you'd be on your own for handing any issues that may arise from not having the link set. (untested, unknown)

Suspend date new

When a User is suspended, the reason will now be shown on the page:


and only if the User is suspended.

This will add the variable:


to the user.conf when the User is suspended, and the format of the number will be a unix timestamp (seconds since 1970)

Upon unsuspension, the row won't show up on CMD_SHOW_USER, and suspend_date will be deleted from the user.conf.

MD5sum on services.tar.gz new

the will now do an md5sum (or md5 on FreeBSD) on the services.tar.gz after download.

There will be an associated file.tar.gz.md5 file for each services tar.gz file on files*

If the md5sum match fails, a warning it shown, and a 5 second pause is given.

Instruction to delete the services.tar.gz and the md5 file and run the again, will follow.

DA will not automatically delete the tar.gz file, as functionality exists to allow the services.tar.gz to already be present.

If it is, and no md5 file exists, then the install will not do an MD5 check.

If the tar.gz exists, and the md5 file exists, the check will be done.

the md5 file is downloaded first, before the tar.gz.

The reason for this check is that some people abort the DA install, at the moment the services_os.tar.gz file is being downloaded.

This leave the box with an incomplete tar.gz file, and because of the functionality which skips the download if the services.tar.gz exists, this causes the install to be incomplete.

The addition of the feature won't change the functionality, but will throw a warning of a broken services.tar.gz, if the md5 match fails.

This should be sufficient information to prevent much confusion and save time if there is a broken services.tar.gz file.

encode usernames fixed

encode usernames in and brute_log_entries.list to make all characters safe.

The usernames are now hex hencoded, eg %12 where characters need to be.

They're decoded during viewing, then converted to html safe characters for the html page.

remove IP with IPv6 fixed

/sbin/ifconfig reports IPv6 IPs in condensed form, but the removeip script was looking for the expanded form.

Updated the removeip script to have a 2nd command (the condensed form IP), so it has a matching value to look for.

dovecot 2.1.0 logging change for BFM fixed

Updated the brute_filter.list to accommodate the slightly changed logging entry for dovecot.

Essentially renamed dovecot1 to dovecot2, and added a new dovecot1 with a more restricted match to handle the 2.1.0 case.

Note that the BFM will still find the entries in 2.1.0, but the attempts per entry will be off. The fix addresses the attempts count.

internal mimtypes.txt wasn't being used fixed

The mimetypes.txt internal text wasn't being used because the "Send" class was loading up before the Config was, so the "en" language wasn't yet set.

Since Send doesn't need any of the texts in the mimetypes class, a flag was added to the Send init to skip the internaltext loading (which was failing), so it's left to later on, when all language settings are properly loaded (eg: "en")

ssl_port is ignored when running in debug mode fixed

Fix, was to consolidate the forking into a new function.

Call it from setAsDaemon, but also call it in debug mode. to check max_username_length fixed

The did not respect the directadmin.conf setting:


so if you change a username to a value longer than this setting, you'd run into issues within DA where the User wouldn't show up or work correctly.

Fix runs "./directadmin c" to check the current limit and compares the length of the new user string.

Changing password when quotas are full can break ~/.shadow fixed

On some systems (proven on a simfs quota system), the system will prevent root from chowning a file to a User, if that User is over quota. (not observed on CentOS).

The solution is, when saving a password when quotas are full, to save to:


as root.

Attempt a chown on the temp. If the file is not owned by the user after the chown, set the quotas to 0 (off), chown the file, rename the file to ~/.shadow and turn quotas back on.

If the chown worked, then the .temp file is renamed normally.

Note that all systems will use the temp file & rename method now.

The disabling of quotas only happens if the chown didn't stick.

SIGTERM not killing all child processes if numservers>20 fixed

If you've got something like numservers=30 and restart DA by only sending a SIGTERM to the parent DA process, the child processes over 20 didn't get the message, so kept on running.

New code uses the newer container class for pids instead of an old pid array.

anonymous ftp doesn't work with secure_access_group fixed

It appears as though proftpd is running as "ftp" when doing the chdir/chroot, prior to dropping the privileges to that of the user.

This caused an error for the anonymous ftp account, as mentioned below.

The fix is to add "ftp" to the "access" group, eg:

usermod -G access ftp

and then restart proftpd.

For any new systems where the access group does not yet exist, the ftp value will be added to the access group autmatically.


Apr  2 23:29:43 server proftpd\[12843\]: (\[\]) - FTP session opened.
Apr  2 23:29:47 server proftpd\[12843\]: (\[\]) - notice: unable to use '~/' \[resolved to '/home/testuser/domains/'\]: Permission denied
Apr  2 22:29:47 server proftpd\[12843\]: (\[\]) - Preparing to chroot to directory '~/'
Apr  2 22:29:47 server proftpd\[12843\]: (\[\]) - chroot to '~/' failed for user '': Operation not permitted
Apr  2 22:29:47 server proftpd\[12843\]: (\[\]) - error: unable to set default root directory
Apr  2 22:29:47 server proftpd\[12843\]: (\[\]) - FTP session closed.

Add timestamp hour offset for FileManager fixed

Removed in DirectAdmin 1.666.

pureftpd not in brute_filter.list fixed

pureftpd is not in the brute_filter.list.

New brute_filter.list entry:

pure-ftpd1=binary=pure-ftpd&text=[WARNING] Authentication failed for user&ip_after=(?@&ip_until=)&user_after=user%20[&user_until=]

Also, new directadmin.conf entry (internal default):


Where it's assumed the pure-ftpd entries are made there.

If they're made elsewhere, then set the brute_force_messages_log entry in the directadmin.conf with the correct path.

Sample log entry used:

May 1 02:37:23 hostname pure-ftpd: (?@ [WARNING] Authentication failed for user [admin]

login-as to support more than 1 level down (SKINS) fixed

If you're logged in as an Admin, then login as a Reseller, and then try to login as a User (below Reseller), it would previously just stay at the Reseller login.

This is because the session holds the admin password, not the reseller password, so when reseller|user is used in the form, the password match fails.

The simple solution is to change the form from using:


(when logged in as the reseller) to show:


instead, even though we're logged in as "reseller" (via the login-as from admin).

This forces a password lookup on admin, which is the value in the session file, so it then works correctly.

Note that when "Logout" is clicked, it will drop straight to admin, and not reseller.





<input type=hidden name=username value="|USERNAME|||user|">

to be:

<input type=hidden name=username value="|LOGIN_AS_MASTER_NAME|||user|">

Backup to allow tar exit code 256 (--ignore-failed-read) fixed

Similar to this change:

Allow tar exit code 1

We've added exit code 256 as a valid tar return code, which is commonly generated when:


is used but the file is still fine.

security: encoding of domain output on CMD_DOMAIN fixed

In response to this report:

the domain output on the 2 mentioned pages will now be html encoded.

Regarding the security level of this bug, it's low to non-existent.

The report makes this reported statement, which is false:

The vulnerability allows an attacker with privileged user account to hijack customer/moderator/admin sessions with high required user inter

action. Successful exploitation can result in account steal or client side context manipulation when processing affected module

application requests.

Because of this feature which was added in 1.34.5:

Security check on Referer header

which prevents the "cross-site" aspect of the cross-site-scripting report.

We could say then, than all versions older than 1.34.5 would be affected.

Reset count on IP in BFM during unblock fixed

The IP values from the file:


will be removed when an unblock is done.

The unblock button only shows up if the scripts are present, eg:

subdomain_owner_check: Allow if is already in list fixed


1 - is owned by user2

2 - is already created under user1

3 - user1 is trying to create

Previously, point 3 would fail because the subdomain_owner_check only found, and noted that it didn't belong to user1.

With this change, an additional check is done with, starting with to see if it exists in the domains.list file of user1.

If a subdomain exists in the domains.list of user1 (, then a double-subdomain ( is now allowed to be created by user1.

This change is not affected with the check, when a new User is being created... which makes sense, since a new User won't yet have any domains anyway.

Last Updated: