Version 1.36.1

Released: 2010-09-08

backup/restore apache owned files new

create a list of apache owned files, and reset them as such after a backup is restored. Excessive checks for symbolic and hard links, and other trickery.

This will be enabled by default, set to 1 internally.

To disable it, set:


in the directadmin.conf, and restart DA.

This setting also applies to the restores, both backup and restores will work with the apache owned files if this is enabled (set to 1).

The file in the backups will be stored in the path:


The format is relative below the /home/user/domains directory, so if:


is chowned to apache before the backup, the path in the apache_owned_files.list will look like:

one entry per line.

Although I went to great lengths to optimize this code as much as it can be optimized, all files and directories below the domains are checked during the backup.

This will slow down the process.

For restores, each line of the apache_owned files is checked for about 6 different things, ranging from file ownership, links in the path, hard links at the file, symbolic links, path syntax, etc..

These checks will also slow things down, but are required to maintain security.

If you're not worried about security and mainly use apache owned files.. you can disable this option in the directadmin.conf file.

Note that both the backup system and restore system need to be 1.36.1 or newer for this to work.

The apache_owned_files.list is a config file, one entry per line, with the values U, UG or G after the file.

This specifies if the ownership should be apache:user, apache:apache or user:apache when restored.

If you notice any files that are not being chowned to apache as you were expecting, run the dataskq in debug mode level 100.

Level 100 is where the errors for these checks are set at.

./dataskq d100

translate internal ftp text new

translate internal ftp.txt

Ability to skip mysql in User backups new

Global directadmin.conf option to skip mysql in User Backups. Would apply to all Backup Levels. (except 'System Backup' which is a different system)

To enable this skip, add:


to your directadmin.conf file, and restart DirectAdmin.

The internal default value is set to 0, which includes the databases in the backup.

Bandwidth only tally: action=bandwidthtally&value=all new

Custom task.queue command for only computing bandwidth and count totals.

Same idea as action=quotatally, except for bandwidth.


echo "action=bandwidthtally&value=all" >> /usr/local/directadmin/data/task.queue

You can also run action=bandwidthtally&value=user&type=username for a per-user bandwidth-only tally.

Allow SNI for shared IP SSL certificates new



but if you want to allow ssl certificates to be added to shared IPs, set:


Enabling sni will simply disable the check for owned IPs when adding certificates.

DirectAdmin does not make any special changes to allow SNI to work.

Also, if a User account has more than 1 IP in his user_ip.list file, the check for the main domain for SSL will be disabled. This is because he could have 2 IPs for ssl, both valid (either owned IPs or with sni enabled) thus there isn't much point in enforcing the main domain to be the only domain for ssl under a User account.

Related apache document:


CentOS 5 and Debian 5 come with versions of OpenSSL that do not support SNI.

Updating to a newer OS, like CentOS 6 would likely be required.

As of May 2015, we're guessing about 95% of client browsers support SNI.

However, this means that 5% of people who connect will get SSL errors.

The 5% would be browsers that are very old, like IE with windows XP.

Openssl version 0.9.8j should have the SNI compile flag enabled by default, but it's not guaranteed that it's actually enabled for your given libraries.

Option to skip ftp uploads if backup creation fails new

By default, DA will upload a tar.gz file, even if some portion of the tar.gz was not created correctly. For example, if mysql was down and the sql file didn't get correctly dumped, by default, the tar.gz will still be uploaded to the backup server.

This option allows the admin to not upload tar.gz backups if they don't want incomplete data.

The default options is 0

To skip the ftp upload, set:


in your directadmin.conf, and restart DA.


this only works for incremental ftp uploads (which 99% of people should be using anyway, as incremental ftp uploads are enabled by default)


** If you are not using incremental ftp uploads (incremental_ftp=0), this setting will not have any effect.

The reason is that with the group ftp upload, where the upload is done at the end, after creating all tar.gz files, DA only knows if there was an error.. but not for which User. Thus this option will not have any effect (I decided not to make it prevent all backups from being uploaded, if one tar.gz creation failed)

Give warning about deleting Users when removing Resellers and Admins new

When deleting an Admin or Reseller, any User accounts created by those accounts will be removed. This change simply provides a warning to the administrator telling them how many User accounts that will be deleted as a result of their action.

Text (the number changes depending on how many Users will be removed):

*** WARNING ***

You are deleting Admin or Reseller accounts that have 1 Users under their control.

If you proceed, these User accounts, which are not listed here, will also be removed.

This will be displayed on the confirmation screen before deleting the accounts.

If there are 0 hidden Users to be deleted, then no warning will be shown. (Eg: if the Reseller controls no Users below him)

Extra option for mysqldump calls new

If you need to insert extra command line bits to the mysqldump call, you can now add this value to your directadmin.conf file:


The default is set to null internally, so you must add the above line to use it.

The option is appended to the tail end of the mysqldump command, but before the name of the database.


extra_mysqldump_options=--skip-add-locks --skip-lock-tables

June 12, 2014:

Report of mixing MyISAM and InnoDB tables can cause confusing lock issues:

Try and stick with one table type in your database to avoid confusion.

Added 'top' output to load checker new

Related to:

System Load checker

This addition will dump out the 30 first lines from "top" if the load checker message is triggered.

The new token in the load_check_message.txt template is called |TOP|

This should aid in determining what process was causing the high load.

awstats doesn't compute last day of month fixed

if day=1, take date for day-1.

-month and -year must be passed.

Changes in the


DAY=`date +%e`
if [ "$DAY" -eq 1 ]; then
        YYMM=`date --date='yesterday' +%y%m`

/usr/bin/perl ${AWSTATS}/tools/ -config=${DOMAIN} -configdir=${DATA_DIR} -update -diricons=icon -awstatsprog=${AWSTATS}/cgi-bin/ -dir=${STATS_DIR} $BD


if [ "$DAY" -eq 1 ]; then
        MAIN_FILE=awstats.${DOMAIN}.\`date --date='yesterday' +%y%m\`.html
        MAIN_FILE=awstats.${DOMAIN}.\`date +%y%m\`.html

security with ~/.shadow fixed

improved checking when working on ~/.shadow

Bug Report Courtesy of

Create non-jailed command for awstats viewing in DA fixed

As of 1.36.0, the awstats icon directory has been linked to:

icon -> /usr/local/awstats/wwwroot/icon

This will save 2 meg of space, per domain.

When viewing your stats through apache, you'll see everything normally.

When viewing through DA, because it's jailed, the icons will not show up.

This fix is to add a custom command for awstats:


such that it can view the icons outside of the jail (likely simply won't jail it, but will have very specific path checks to ensure it's safe)

Note the jail is only skipped if the icons directory is in the path, the icons directory is a directory link, and that link points to:


If any of the above is not true, the chroot will not be skipped.

A workaround would be to remove the link in:



if [ ! -h $ICON ]; then

        rm -rf $ICON

        ln -sf ${AWSTATS}/wwwroot/icon $ICON


Replace it with:

if \[ -h $ICON \]; then
        rm -f $ICON
        cp -Rp ${AWSTATS}/wwwroot/icon ${STATS_DIR}

where you'd remove the ! character before the -h, remove the r from -rf, and remove the ln line.

move check of /usr/local/bin/php into fixed

The php binary check is currently at the end of the If the install fails (the calls, the reason the install failed will be displayed in the output of the, but the tail end of the will still be run, thus the check for php is done anyway, which is pointless if the abort happened before the php binary compile was even attempted.

The fix (to avoid confusion) is to add the php check to the end of the, such that if the aborts for a particular reason, the last message seen will be the actual error, and not the redundant php check.

replace chown with lchown fixed

We usually don't want to follow links when setting ownership on a file, so we've swapped chown with lchown.

As well, for all configfile and listfile class writes (almost all data files), an fchmod is run after the fopen is called to create the temp file. This is to set the temp file to 600, instead of letting the system decide what it should be. After the temp file is filled, it's renamed to the original and chmod to whatever it's set to be normally.

For anyone who still uses Frontpage, it's been end-of-life for about half a decade. We don't recommend it's use for production systems.

For those who still need to use it, we've added more checks to try and make it more secure by traversing the public_html directory looking for links (hard or symbolic) before running the frontpage installer. stats and awstats links are ignored. didn\'t swap new multi-ip files fixed

Update to swap the user_ip.list and domains/ files.

The new User loop in the looks like this:


for i in \`ls $ULDDU/users\`; do

        if \[ ! -d $ULDDU/$i \]; then

        swapfile $ULDDU/$i/user.conf
        swapfile $ULDDU/$i/httpd.conf

        if \[ -e $ULDDU/$i/ip.list \]; then
                swapfile $ULDDU/$i/ip.list

        swapfile $ULDDU/$i/user_ip.list

        for j in \`ls $ULDDU/$i/domains/*.conf; ls $ULDDU/$i/domains/*.ftp; ls $ULDDU/$i/domains/*.ip_list\`; do
                swapfile $j

Fixed path to gunzip on for mysql restores fixed

Previously, the gz files were extracted with /usr/bin/gunzip.

On non-FreeBSD systems, the path should be /bin/gunzip.

This was resolved in the code with some #ifdef calls to check the OS, and setting some #define calls for the true gunzip path.

Also a check for this file is done first to ensure it's actually there, or it will throw an error.

Mysql Backup for mysql 4.0 systems fixed

Related to this previous fix:

myslqdump: use --create-options instead of soon to be depreciated --all

It introduced issues for old mysql 4.0 systems.

This new fix checks the mysqld version.

If it's mysql 4.0, then --all will be used.

If it's anything else, then --create-options will be used in the mysqldumps.

ftp users not removed when moving between shared and owned IPs fixed

If you're changing the IP of a User from an owned to shared, or vice versa, the ftp accounts will be left in the previous ftp password file. This fix removes them from the previous file. If moving from owned to shared, the ftp.passwd is simply emptied since an account which isn't on an owned IP won't have any accounts.

Update html for hardcoded data in filemanager to use correct syntax (SKINS) fixed

This change won't change much for most people. It mainly only applies to people who have script parsers on the hardcoded data in the skins.


<img ... >
<input ... >


<img ... />
<input ... />
value="text" or value='text'

The changes were made mainly only for the filemanager (because it is chrooted and cannot be parsed/modified), however some of the changes made there are in global classes, so for example, all dynamic tables in DA will also be updated with these syntax changes.

Ensure random passwords are generated with upper and lower case characters (SKINS) fixed

A previous fix ensured there are numbers in the random passwords.

This change to the javascript.html will ensure that in addition to numbers, random passwords also have upper and lower case digits, something the difficult_password_enforcement option requires.



function has_lower_case(pass)
        var num_count = 0;

        for (i=0; i<pass.length; i++)
                if ('a' <= ch && ch <= 'z')

        return num_count;

function has_upper_case(pass)
        var num_count = 0;

        for (i=0; i<pass.length; i++)
                if ('A' <= ch && ch <= 'Z')

        return num_count;

and in the random_pass() function:

if (!has_number(pass) || !has_lower_case(pass) || !has_upper_case(pass)) wasn\'t being called fixed

Related: custom scripts for databases

The script was in place of the script. Corrected it so is called for user creation, and is called for database creation.

Last Updated: