Version 1.51.0
Released: 2017-02-09
new
Backup/Restore mysql charsetsBackup and restore of databases should maintain same character-sets.
Related query for backup:
SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'username_dbname';
mysqldump -uUSERNAME -pPASSWORD --default-character-set=utf8 USER_DATABASE > backup.sql
Related restore:
mysql -uUSERNAME -pPASSWORD --default-character-set=utf8 USER_DATABASE < backup.sql
New directadmin.conf option:
extra_mysql_restore_options
internal default is null (unset), but you can add it to your directadmin.conf, to add extra options, eg:
extra_mysql_restore_options=--default-character-set=utf8
new
LetsEncrypt: disable auto-renew (SKINS)(LANG)Added a button to allow Users to prevent the automatic Lets-Encrypt renewal.
This does not affect the current cert/key pair, it simply disables the renewal.
Also, deleting the domain will clear the same files as well.
The button will delete these files if they exist:
- /usr/local/directadmin/data/users/username/domains/domain.com.san_config
- /usr/local/directadmin/data/users/username/domains/domain.com.cert.creation_time
- /usr/local/directadmin/data/users/username/domains/domain.com.csr
API
The API can also make the call:
CMD_API_SSL
method: POST
domain=domain.com
action=save
disable_letsencrypt_autorenew=any text
SKINS:
user/ssl.html
<div style='padding-bottom: 20px'><input type=submit name='disable_letsencrypt_autorenew' value="|LANG_LE_DISABLE_AUTORENEW|"></div>
LANG:
lang/en/user/ssl.html
LANG_LE_DISABLE_AUTORENEW=Disable Auto-Renew
lang/en/internal/ssl.txt
40=Error Deleting %s
lang/en/internal/command.txt
575=LetsEncrypt files have been cleared
576=Error clearing LetsEncrypt files
new
skin.conf (SKINS)New feature for skins, with a file called:
skin.conf
which can exist in the skin's folder in order to affect how DA creates some tokens internally, eg:
/usr/local/directadmin/data/skins/enhanced/skin.conf
Options:
ALL_DOMAINS_SELECT=clean
Causes the domain select that appears on all User Level pages to not have any javascript, and to have the value:
id='all_domain_select'
allowing actions to be controlled by external javascript, like ajax.
TABLES=div
Causes the internal Table class to generate <div>
output, instead of <tables>
.
new
commands_force_deny to override allowed/deny commandsRelating to both features:
commands.allow/commands.deny files:
commands.allow and commands.deny for per-user control
and login key allow/deny files:
http://help.directadmin.com/item.php?id=523
For both cases, the allow will always override the deny, as it is for various other rues (eg: /etc/hosts.allow vs /etc/hosts.deny), so that logic will not change.
However there are some cases where that's very inconvenient, like where you want to allow a User to run all commands, except denied a few.
A command example would be to:
allow: ALL_USER
deny: CMD_LOGIN_KEYS CMD_API_LOGIN_KEYS
in the above example, previously Login Keys would be allowed because CMD_LOGIN_KEYS is a subset of ALL_USER, and allow overrides deny.
New feature to override the allow, and force a deny command.
Internal default:
commands_force_deny=CMD_LOGIN_KEYS:CMD_API_LOGIN_KEYS
where any commands listed in the commands_force_deny will override the command being in the allow.
The variable is a list of commands, seaparated by a colon.
The feature really only has any effect when commands are listed in both the allow and the deny.
It's basically used as a tie-breaker, to force deny, when a tie would previously allow the command.
new
CustomBuild to manage letsencrypt.shUpdate: Aug 3rd, 2016:
We've added the letsencrypt.sh script into CustomBuild, but it will simply download it and copy it over to:
/usr/local/directadmin/scripts/custom/letsencrypt.sh
it will not live in the custombuild/configure/letsnecrypt/letsencrypt.sh location.
As it seems that the LetsEncrypt project continues to receive many updates/changes as time goes on,
rather than requiring a whole new DA update for each change to the letsencrypt.sh script, we've moved it to CustomBuild.
For backwards compatibility, the custom folders will override the defaults.
The checking order for which script to use is as follows, higher has priority:
- /usr/local/directadmin/custombuild/custom/letsencrypt/letsencrypt.sh
- /usr/local/directadmin/scripts/custom/letsencrypt.sh
- /usr/local/directadmin/custombuild/configure/letsencrypt/letsencrypt.sh
- /usr/local/directadmin/scripts/letsencrypt.sh
So if you have a custom script from the older directadmin/scripts/custom/letsencrypt.sh location, it will still trump custombuild/configure/letsencrypt/letsencrypt.sh
new
CMD_AJAX_SEARCH jsonNew search tool to find data quickly.
Command:
CMD_AJAX_SEARCH
GET options:
search=your query
Optional values:
search_default=0|1
user_level=0|1
search_users=0|1
search_admins=0|1
search_resellers=0|1
search_domains=0|1
search_email=0|1
search_ftp=0|1
search_db=0|1
If set, the search_default will initialize all variables to 1 or 0. Else all search_* variables are initialized to 1.
If user_level is passed, this applies the settings on email, ftp, and db. Doesn't touch Admin/Reseller items (users/domains)
Any search_* value will set to that value, after all above conditions are finished being set.
If only a basic "search" is done, without any variables:
Admin/Resellers: every thing is searched
Users: User Level items are searched.
For any array type, if there are no items, the array won't be passed at all, so make sure to ensure the array exists before starting to read it.
directadmin.conf
new variable:
ajax_search_max_time=2.0
uses a floating point number to determine how long the search is allowed to run.
It doesn't use an interrupt, but rather just does a check in between items, and inside loops.
So for example, if the email search takes 3 seconds, ftp and databases won't be searched at all.
Sample output:
{
"users":
{
"CMD_SHOW_USER?user=testresell", "testresell",
"CMD_SHOW_USER?user=testshared", "testshared",
"CMD_SHOW_USER?user=testuser", "testuser"
}
,"resellers":
{
"CMD_SHOW_RESELLER?user=testresell": "testresell",
"CMD_SHOW_RESELLER?user=testshared": "testshared"
}
,"domains":
{
"CMD_SHOW_USER?user=shareduser": "User shareduser : sharedomaintest.com",
"CMD_SHOW_USER?user=templtes": "User templtes : templates-test.com",
"CMD_SHOW_USER?user=testresell": "User testresell : testreseller.com",
"CMD_SHOW_USER?user=testshared": "User testshared : testshared.com",
"CMD_SHOW_USER?user=userofres": "User userofres : sub.testreseller.com"
}
,"dbs":
{
"CMD_DB?name=user_test": "Database user_test"
}
}
new
php_fpm_restarts to override reload/gracefulSome reports of issues with the default actions for php-fpm.
systemd: reload
init.d: graceful
If you're having issues with php-fpm not executing the above command properly for your system, you can add this value:
php_fpm_restarts=1
to your directadmin.conf (internal default is 0), so that it calls a full "restart" for the php-fpmXX service(s).
new
CMD_FILE_MANAGER action=json_dirs action=json_files action=json_alljson_dirs: generate a json output for the list of directories in the current path
json_files: generate a json output for the list of files in the current path
Note, if "linkpath" is not empty, eg: "", then the file or folder is a link.
Command:
CMD_FILE_MANAGER
path=/ or path=/some/path
or
CMD_FILE_MANAGER/some/path
GET
action=json_dirs|json_files
optional:
api_flags=0|1
default for this function is 1.
(CMD_API_FILEMANAGER default is 0, but can use api_flags=1 in the GET for more info in the API result)
The api_flags variable is a bitmask for the following options:
#define FM_F_PROTECTABLE 1
#define FM_F_RENAME 2
#define FM_F_COPY 4
#define FM_F_RESET_OWNER 16
#define FM_F_RESET_OWNER_RECURSIVE 32
#define FM_F_HIDE_CHECKBOX 64
#define FM_F_EDITABLE 128
#define FM_F_EXTRACTABLE 256
so to figure out which action a folder can have, check the the bitwise & for the given item.
Example, to determine if a folder is protectable, check:
if (api_flags & 1)
console.log("folder is protectable");
The json_files can use the ipp=10&page=4 method to limit the output, just like tables.
All table search/sorting/filtering is available, same as Advanced Search for tables.
But the "sub_directories" and "files" variables are not search/sort-able, as they're appended to the data afterwards.
Page/row info is added to the "info" data item at the end of the list.
There shouldn't be any conflicts with /filenames as all files/paths start with a forward slash, and "info" does not.
SEARCH / SORTING
The json_dirs/json_files output is actually all run by the existing table class.
So anything you can do with a table, you should be able to do with this output.
The difference is the column names and column order is not the same as the Enhanced "Advanced Search" so the column numbers won't be the same.
Note that the columns of json_dirs and json_files ARE NOT THE SAME, so please see the samples for the column number you want.
If we add colums in the future, I'll make sure they're appended to the end, so the numbers for existing columns remains the same.
Use the sample output below for json_dirs / json_files column numbers, below.
api_flags is column 1, and count up from there.
Eg: for json_dirs, to search for a .txt file, you'd want column 6 (path), eg:
comparison6=contains&value6=.txt
You can specify single rules on multiple columns at the same time, if you want to execute a boolean "AND" comparison.
For example:
comparison6=contains&value6=.txt&comparison9=atleast&value9=1024000
will show all files that have .txt in their name, and who's size is 1MB or larger.
So when searching, the comparisonX values can be:
- equals
- atleast
- atmost
- contains
- startswith
with the given valueX set to what you're looking for.
Make sure the atleast/atmost are only searching on number type columns, else you'd be doing it on strings, eg: a<=b which isn't as useful.
You can then sort, and sub-sort at desired, eg:
sort1dir=1&sort1=6
where sort1dir is either 1 (ascending) or -1 (descending)
And sort1 is the column to sort.
You can then do a sub-sort if you want, eg:
sort2dir=1&sort2=9
which is the sorting done when a row in sort1 matches. (usually not required)
PAGES
Json "info" output sample for json_dirs:
"info":
{
"columns":
{
"api_flags": "1",
"date": "2",
"gid": "3",
"linkpath": "4",
"name": "5",
"permission": "6",
"showsize": "7",
"size": "8",
"truepath": "9",
"uid": "10"
},
"current_page": "1",
"ipp": "50",
"rows": "10",
"total_pages": "1"
}
columns: is a sub-set showing which column each item is at, useful for figureout out which comparison row to work on. (json_dirs != json_files column #s)
Items per page:
If you want to control how many items are returns, set a value:
ipp=50
but usually isn't required.
DA has an internal default of 50.
rows shows the total number of items in the table.
You can pass:
page=2
to see page 2, and then you'd see current_page=2
total_pages shows the number of pages available for the given ipp values (internal default, skin.conf value, or get ipp override)
An override recomputes the total number of pages, so would affect the current page, etc..
========================================
Sample output for / path:
{
"/Ù…ØÂمود":
{
"api_flags": "6",
"date": "1474348180",
"gid": "admin",
"islink": "0",
"linkpath": "",
"name": "Ù…ØÂمود"
"permission": "755",
"showsize": "4.06k",
"size": "4155",
"truepath": "/Ù…ØÂمود",
"uid": "admin",
"sub_directories": "1",
"files": "1"
}
,"/.php":
{
"api_flags": "54",
"date": "1476144611",
"gid": "apache",
"islink": "0",
"linkpath": "",
"name": ".php"
"permission": "770",
"showsize": "4.00k",
"size": "4096",
"truepath": "/.php",
"uid": "admin",
"sub_directories": "0",
"files": "10"
}
,"/Maildir":
{
"api_flags": "6",
"date": "1475065659",
"gid": "mail",
"islink": "0",
"linkpath": "",
"name": "Maildir"
"permission": "770",
"showsize": "1.34M",
"size": "1409098",
"truepath": "/Maildir",
"uid": "admin",
"sub_directories": "6",
"files": "5"
}
,"/admin_backups":
{
"api_flags": "6",
"date": "1476075968",
"gid": "admin",
"islink": "0",
"linkpath": "",
"name": "admin_backups"
"permission": "711",
"showsize": "711.5M",
"size": "746046021",
"truepath": "/admin_backups",
"uid": "admin",
"sub_directories": "20",
"files": "15"
}
,"/domains":
{
"api_flags": "6",
"date": "1475246669",
"gid": "1003",
"islink": "0",
"linkpath": "",
"name": "domains"
"permission": "750",
"showsize": "298k",
"size": "304861",
"truepath": "/domains",
"uid": "admin",
"sub_directories": "9",
"files": "0"
}
,"/imap":
{
"api_flags": "6",
"date": "1475246669",
"gid": "mail",
"islink": "0",
"linkpath": "",
"name": "imap"
"permission": "770",
"showsize": "4.32k",
"size": "4428",
"truepath": "/imap",
"uid": "admin",
"sub_directories": "5",
"files": "0"
}
,"/public_html":
{
"api_flags": "6",
"date": "1475246669",
"gid": "admin",
"islink": "1",
"linkpath": "./domains/testing2domain.com/public_html",
"name": "public_html"
"permission": "777",
"showsize": "0.04k",
"size": "40",
"truepath": "/public_html",
"uid": "admin",
"sub_directories": "1",
"files": "10"
}
,"/user_backups":
{
"api_flags": "6",
"date": "1463077334",
"gid": "admin",
"islink": "0",
"linkpath": "",
"name": "user_backups"
"permission": "711",
"showsize": "355.8M",
"size": "373067818",
"truepath": "/user_backups",
"uid": "admin",
"sub_directories": "0",
"files": "2"
}
,"info":
{
"columns":
{
"api_flags": "1",
"date": "2",
"gid": "3",
"linkpath": "4",
"name": "5",
"permission": "6",
"showsize": "7",
"size": "8",
"truepath": "9",
"uid": "10"
},
"current_page": "1",
"total_pages": "2",
"rows": "15",
"ipp": "8"
}
}
sample json_files:
{
"/.bashrc":
{
"api_flags": "6",
"date": "1430061718",
"gid": "admin",
"linkpath": "",
"name": ".bashrc"
"permission": "644",
"showsize": "0.09k",
"size": "89",
"truepath": "/.bashrc",
"uid": "admin"
}
,"info":
{
"current_page": "1",
"total_pages": "1",
"rows": "1",
"ipp": "50"
}
}
sample json_all:
exactly the same as json_dirs, except each file/folder entry has one of:
type: "file"
type: "directory"
and where type=file won't provide extra files/sub_directories values.
new
json output for CMD_FILE_MANAGERFor any CMD_FILE_MANAGER request, if you include:
json=yes
with your GET or POST variables, any "dynamic" page output will be in json format, rather than html.
Will be either a success:
{
"result": "/test/apache",
"success": "File ownership reset"
}
or error:
{
"error": "An Error Occurred",
"result": "No files have been selected for upload."
}
for any CMD_FILE_MANAGER command that generates the dynamic output (aka: the template.html skin file).
Errors generate:
500 Internal Server Error
This is handy for ajax type calls to rename/copy files/folders, manage the clipboard, etc.. without needing to reload the whole page.
For the list of commands, see the CMD_API_FILE_MANAGER pages, as they're pretty much the same.
The main reason for making this json version was because the API might be disabled for a User, but the new skin requires ajax type requests of CMD_FILE_MANAGER for in-page file/folder management.
new
CMD_API_DB_USER list Users for all databasesWhen creating a database in the GUI, there is a dropdown to use an existing User.
You could either call the CMD_API_DB_USER?db=user_dbname for each database to find all Users,
or you could use this new call to get all Users without all of the other work.
CMD_API_DB_USER
GET:
action=all_users
eg:
CMD_API_DB_USER?action=all_users
this will exclude the system account username from the list, even though it's probably on the DB.
Sampel return value:
admin%5Fadmin=admin&admin%5Fasdfg=asdfg&admin%5Fdb=db&admin%5Fdropu=dropu&admin%5Flong=long&admin%5Ftest=test
Where it's a standard url.
The name's are:
username_fred
while the values are just:
fred
where 'fred' is the value you'd be passing for the username when creating a DB.
new
CustomBuild and DA to add linked IPs to httpd-vhosts.conf and nginx-vhosts.confWhen you're on a LAN or have linked IPs, anything set to the server IP should also apply to those linked values.
For the normal templates, we used the already present MULTI_IP token.
But for the httpd-vhost.conf and nginx-vhosts.conf, they're not created by DA, only by CustomBuild, so we needed another swap.
The CustomBuild 2.0 build script release 1588 will have:
configure/ap2/conf/extra/httpd-vhosts.conf
configure/nginx/conf/extra/httpd-vhosts.conf
with new tokens:
|LINKEDIP|
|LINKEDIPSSL|
where the dataskq will tokenize them.
The build script will also swap them to blank "" in case the dataskq doesn't support it yet.
To confirm the dataskq has it, type:
./dataskq h
and you should see:
./dataskq --linked-ips :Output the server IP's linked IPs. Skip all other tasks.
in the output.
CustomBuild uses a modified version of that.
For apache and the httpd-vhosts.conf:
./dataskq --linked-ips=2
For nginx and the nginx-vhosts.conf:
./dataskq --linked-ips=3
and it will tokenize those files, respectively.
new
CMD_FILE_MANAGER div to have iconsFor the new skin, the Filemanager names will be displayed like:
<i class="icon icon-pdf-small"></i>
<span>file.pdf</span>
so the skin.conf will have a new variable:
filemanager_icons=pdf:zip:gz:tar:php:txt:jpg:png:gif:html
which tells DA which icons to support.
DA will set the given extension into the icon-XXX-small css value, eg:
icon-php-small
allowing you to setup those css sprites, as desired.
For any extension not setup in the filemanager_icons list, DA will default to:
icon-file-small
so ensure you have that css set for a generic file icon.
new
SNI for per-domain Dovecot SSL certificates (BETA)DEPRECATED!!! Use mail_sni instead of dovecot_sni:
mail_sni for dovecot and exim sni certificates
==================================
Feature related to this guide:
https://help.directadmin.com/item.php?id=573
Allowing DA to create/manage per-domain SNI files for dovecot in:
/etc/dovecot/conf/sni/9DOMAIN.conf
via:
/etc/dovecot/conf.d/95-sni.conf
Because dovecot requires the CA cert to be in the .cert file (that's how we'll do it anyway), if you have:
user/domains/domain.com.cert
user/domains/domain.com.cacert
DA will auto generate:
user/domains/domain.com.cert.combined
for use in the dovecot config.
(Nginx also uses this .combined file)
TO ENABLE
The internal default is:
dovecot_sni=0
so set:
dovecot_sni=1
in your directadmin.conf, and restart DA.
Go to the:
User Level -> SSL Certificates
and if you currently have a pasted cert/key, simply hit "save" to regenerate the dovecot config for that domain.
Then setup the configs:
cd /usr/local/directadmin/custombuild
./build update
./build dovecot_conf
TEMPLATE
/usr/local/directadmin/data/templates/dovecot_sni.conf
where it will use this template several times for each domain, to add SNI for:
domain.com, mail.domain.com, pop.domain.com and imap.domain.com
TASK QUEUE
If you want to tell all live SSL domains to have their dovecot configs written, type;
echo "action=rewrite&value=dovecot_sni" >> /usr/local/directadmin/data/task.queue
this will create the sni/domain.com.conf for each SSL domain, plus one for the system hostname.
*** IMPORTANT ***
If you run:
./build dovecot_conf
If you need to add a custom file, create it
/usr/local/directadmin/custombuild/custom/dovecot/cond/sni/YOURCUSTOMDOMAIN.COM.conf
which will be set with the ./build dovecot_conf.
If you make SSL certificate changes in DA, DA may resave that file, so you'd need to:
./build rewrite_confs
again to reset any overrides.
If you custom file was extra, and not matching any existing file, then it should be fine in the custom/dovecot/conf.d/95.. method.
=========================
Related thread for doing the same thing in a different way:
http://forum.directadmin.com/showthread.php?t=53967
new
zip_bin unzip_bin to allow zip/unzip binary overrideNew directadmin.conf options:
zip_bin=(null)
unzip_bin=(null)
both are null (unset) by default.
If the values are added to the directadmin.conf, they should hold the path to the zip/unzip binaries, eg:
zip_bin=/usr/bin/zip
unzip_bin=/usr/bin/unzip
adjusted as desired.
If the values are set to null (aka: not in the directadmin.conf at all), then DA will look for /usr/bin/zip else /usr/local/bin/zip to use for compression.
The purpose of this is to allow an override if in case you need to add a wrapper to unzip, in such cases as extraction of UTF-8 files, eg:
unzip_bin=/usr/bin/unzip2
With unzip2 containing:
#!/bin/bash
export LANG=en_US.UTF-8
exec /usr/bin/unzip $@
exit $?
new
FileManager recursive filename/folder searchjson output for query:
CMD_FILE_MANAGER
Method: GET or POST
action=recursive_search
path=/
search=txt
where path can be any folder name to search in.
Keep in mind that /imap and /Maildir can be huge, so don't search them if you don't need to.
optional value:
type=files
or
type=directories
will search only for that type, and not show the other type.
Sample json output :
"files":
{
"/domains/demo.com/awstats/.data/awstats052013.demo.com.txt": "6188",
"/domains/demo.com/public_html/rc.txt": "4424"
}
,"directories":
{
"/domains/demo.com/public_html/txt_files": "4096"
}
,"info":
{
"completed": "1",
"path": "/"
}
If there is a MAJOR error, always first check for the "error" value, eg:
{
"error": "Error with search",
"result": "search length out of bounds: 2 < || > 128n"
}
where there are 3 arrays, files, directorties, and info.
The files/directories will have matched substring path and the file/folder size. (folders are usually 4096 bytes, but can be larger if there are many inodes inside)
The info array contains the path that was requested and a "completed" value.
The info['completed] value will be a number:
0 - all files/folders searched. If matched, it will be in the list.
1 - the size of the list maxed out before finishing.
2 - the maximum time passed before finishing.
3 - some error occurred and info['error'] will contain a string showing the error(s). (there could be multiple, one per line)
The max time is specified by the directadmin.conf option:
ajax_search_max_time=2.0
The max list size is specified by the directadmin.conf option:
ajax_list_max=20
new
difficult_password.php can be translated (LANG)The script:
/usr/local/directadmin/scripts/difficult_password.php
previously couldn't be translated: it's output was what was shown.
This changes creates a new internal language pack at:
/usr/local/directadmin/data/skins/enhanced/lang/en/internal/difficult_password.txt
which can be translated into new languages.
The number codes in the .txt file are directly linked to the exit code of the script.
So exit code 0 (success) lines up with:
0=Password OK
etc..
Note that 1= uses %d characters, so this is the only special case where DA passes the integers into the translation class, so #1 must contain that string, eg:
1=Password is too short (%d). Use at least %d characters
the >2 don't matter, and you can add more if you want if you create a custom difficult_password.php file with higher exit codes.
If any codes are missing from the internal/difficult_password.txt, then scripts output is used instead.
But if the .txt for your language is completely missing, as per other internal/*.txt files, it will revert to the default language, usually the en folder.
Also, there will be an environmental variable:
language=en
which should show the User's current language, in case you'd instead want to control the scripts output for items not included in the internal/difficult_password.txt.
new
dnssec.sh to use RSASHA256Changed the do_keygen() function in the script:
/usr/local/directadmin/scripts/dnssec.sh
to use:
RSASHA256
instead of:
RSASHA1
but only if the script can see "RSASHA256" in the keygen, eg if:
/usr/sbin/dnssec-keygen -h 2>&1 | grep -c RSASHA256
is greater than 0.
If it's 0, then it's an older setup, so it will still use RSASHA1.
new
Ability to disable reload/HUP of apache/nginx after rotationNew variable:
reload_apache_after_rotation=1
with internal default of 1, will control if DA sends an HUP signal to the pid file set in the directadmin.conf setting:
apache_pid=/var/run/httpd.pid
or if nginx=1, DA internally sets it to:
apache_pid=/var/run/nginx.pid
via the nginx_pid variable.
DA will read that value, and send a root call to:
kill(pid, SIGHUP);
If you do not wish to have the post-rotation send the HUP, you can set:
reload_apache_after_rotation=0
in your directadmin.conf, and the HUP won't be sent.
*** HOWEVER *** the HUP is sent for a reason.
This is used to re-open all rotated logs and bytes logs.
So if apache/nginx does not get the HUP, you may have logging issues.
If needed, immediately after that HUP is sent, the hook script:
tally_rotation_post.sh
is called if it exists.
So if you disable the HUP, you can take any other desired actions with that script.
new
file_manager_upload_post.shCustom hook script to run after a User has finished uploading a file in the CMD_FILE_MANAGER or CMD_API_FILE_MANAGER.
Would be useful if you'd like to run ClamAV on a given file after the upload.
Exit with a 0 code if checks are ok.
Exit with a non-zero result if there was an error.
Note that DA doesn't take any special actions on the files based on the output, other than throwing an error in the result upload message.
If you exit with a non-zero result, be sure to echo some text to clarify what the problem is.
Eg: if there was a virus (as decided by ClamAV), you might want to delete the uploaded file in your script, echo a notice about that, and exit 1;
Environmental variables:
file=/home/fred/path/to/uploaded/file.exe
home=/home/fred
username=fred
SECURITY
ENSURE that you're fully quoting the $file variable.
This script does run as root and files can have spaces or other strange things.
It's your responsibility as a script writing to handle security validation.
new
ability to change favicon.icoIf any request is made to DA for:
1.2.3.4:2222/favicon.ico
DA will send them the file at:
|DOCSROOT|/images/favicon.ico
Where DOCSROOT is from:
cd /usr/local/directadmin/
./directadmin c | grep ^docsroot=
Usually:
/usr/local/directadmin/data/skins/enhanced/images/favicon.ico
New directadmin.conf variable:
favicon_ico=favicon.ico
which allows you to specify some other file, such that you'd just place it in the images directory with a different name, and specify it in the directadmin.conf, and restart DA, eg:
/usr/local/directadmin/data/skins/enhanced/images/my_favicon.ico
favicon_ico=my_favicon.ico
Your "my_favicon.ico" would be safe from overwrites, since the enhanced skin does not include that file.
new
new "suspended" template directory for new Admin/Reseller accountsNew directory:
/usr/local/directadmin/data/templates/suspended
Can be customized if copied to:
/usr/local/directadmin/data/templates/custom/suspended
used for new Admin and Reseller accounts at:
/home/reseller/domains/suspended
It will include the same index.html that was previously generated by DA.
It will also now include an .htaccess file to prevent any caching of the html/htm/js/css files,
so that the moment a domain is unsuspended, the client's browser won't use the suspended cache.
new
database_user_password_change_pre.sh database_user_password_change_post.shCustom scripts called if a DB User's password is set:
/usr/local/directadmin/scripts/custom/database_user_password_change_pre.sh
/usr/local/directadmin/scripts/custom/database_user_password_change_post.sh
Environmental variables:
username=fred
name=fred_dbname
user=fred_dbuser
passwd=newpass
For database_user_password_change_pre.sh if you exit with non-zero, DA will add your output and abort the change.
new
Accountability for domain setting changeFor any User making changes to their domain at:
User Level -> Domain Setup -> domain.com
Any changes in the domain.com.conf file will now be logged, eg:
2016:11:23-20:10:01: fred:1.2.3.4: Domain test.com php changed from 'ON' to 'OFF'
2016:11:23-20:11:14: fred:1.2.3.4: Domain test.com bandwidth changed from 'unlimited' to '1002'
The accountability has been added as Users sometimes set their domain settings to a low bandwidth limit, which they forget about, causing their domain to be suspended, then deny they had made the change.
This offers Admins some recourse to verify when it was changed, and by who/IP, etc..
new
DNSSEC: automate adding subdomain's DS and NS records to parent zoneFeature to automate this guide:
https://help.directadmin.com/item.php?id=652
If you're creating sub.domain.com has domain.com is already signed, sub.domain.com will be immediately keyed & signed.
If you've just signed the DNSSEC sub.domain.com zone, and domain.com exists on the server, if enabled DA will add the DS and NS records from sub.domain.com to domain.com
Internal default value is enabled:
dnssec_add_subdomain_ds_to_parent=1
requires dnssec to be enabled.
new
Max upload size to use larger typePreviously, the max size you could set was a "long" type with a max size of 2147483647 bytes (~2.1 gig)
Changed to use a "long long" type for a max value of 9223372036854775807, which is still something like 9,223,372,036 Gig..
I don't think you've got anything that large to upload but that's the new maximum limit that you can specify in the Admin Settings.
I've also set the new internal default for max upload size from 10 Meg to 500 Meg.
new
Enable direct_imap_backup by defaultAfter sufficient time in the wild without any major issues, I've now enable this feature:
Backup: direct_imap_backup for direct inclusion of imap folder into tar.gz
to be on by default.
This will greatly speed up backup times for server with a lot of email data, because it includes the imap folder directly into the final tar.gz file, rather than first copying it, then including the copy.
If you do not want it, you can turn it off by adding this to your directadmin.conf:
direct_imap_backup=0
new
CMD_API_SUBDOMAIN?domain=all to show subdomains for all domainsNew option for CMD_API_SUBDOMAIN, if you specify domain=all with no other action, DA will create a URL encoded list of domains.
The value of each domain will be a list of subdomains, separated by colons.
Eg:
domain1.com=sub1:sub2&domain2.com=sub1:sub4
new
json_out for CMD_TICKET_MANAGE & CMD_TICKETYou can add:
&json=yes
or:
&json=yes&last_messages=5
to the end of:
CMD_TICKET_MANAGE?action=view&number=000001234&type=ticket
To get json output for a given ticket.
Another similar option added for DA 1.51.4
&json=yes&start_message=5
which sets which message to start with.
But if you set last_messages, this overrides the start_message, so pick one or the other.
The first message is start_message=0, so if there are 5 messages in the ticket, you'd use start_message=4.... or last_messages=1
The last_messages can be any positive int, and will show the last X number of messages in that ticket.
Can use a value higher than the number of messages, it won't hurt anything.
Output is very similar to CMD_API_TICKETS, but is json, and uses sub-arrays.
There is also an "info" array.
Note that each message index is it's array position, so the first message is item 0.
The info['start'] item will be the starting array position, and varies if you set last_messages.
The message[0]['user'] would be similar to the "to" value. If it's set to "creator" it's from the User.
{
"0":
{
"from": "fred",
"level": "user",
"message": "Help me me me.",
"name": "fred",
"priority": "20",
"status": "open",
"subject": "This is my ticket!!",
"time": "1479974898",
"type": "ticket",
"user": "creator"
},
"1":
{
"from": "admin",
"level": "admin",
"message": "Yes, I can help.nPlease delete yourself.",
"name": "admin",
"priority": "none",
"status": "open",
"subject": "Re: This is my ticket!!",
"time": "1479976365",
"type": "reply",
"user": "fred"
},
"info":
{
"num_messages": "2",
"start": "0"
}
}
new
Append Path for Reseller Backups (SKINS)Relating to the:
Admin Level -> Admin Backup/Transfer -> Backup : where : append path
option, a similar Reseller version is now available.
SKINS:
reseller/backup_modify.html
reseller/backups.html
for both, add the JS function:
function set_custom_path()
and the 2 <tr>
sections for the append path, in the same manner as the admin_backup.html and admin_backup_modify.html
new
CREATOR token in dns templates (eg: dns_a.conf)There might be cases where you'd want to know the creator of a User, when a new zone is added for a domain.
The CREATOR token has been added for the dns_a.conf style dns_*.conf templates.
Note that the value will not exist if a zone is created at the DNS Administration area, since it's not below a User.
new
edit_files.txt now requires root authentication to edit php.ini filesThe Admin Level "File Editor", when used to edit php.ini files, now has &secure=yes added to the end of each php.ini, so that root auth is required.
Because some php scripts are run as root, some settings would allow security risks in the php.ini for a non-root account.
fixed
SpamAssassin whitelist wildcards added to filterRelating to feature:
Add the SpamAssassin Whitelist to the domain filter to also whitelist SPAM Filter (TEMPLATES)
support now added for wildcards in the form:
*@domain.com
*domain.com
which would use this in the filter:
or $sender_address contains "@domain.com"
or $sender_address contains "domain.com"
fixed
Dovecot logging format updateDovecot 2.2.20 and older used format similar to this:
Aug 11 19:38:49 testserver dovecot[7384]: imap(test@directadmin.com): Disconnected: Logged out bytes=132/9977
Versoins newer thatn 2.2.;0 use this:
Aug 11 19:38:49 testserver dovecot[775]: imap(test@directadmin.com): Logged out in=1317 out=13696
Oct 15 19:38:49 testserver dovecot[123]: imap(test@directadmin.com): Disconnected for inactivity in=588 out=1775
and the da-popb4smtp script isn't correctly catching this scenario.
fixed
directadmin_imap_backup without domains directory throws errorRelating to this feature:
Backup: direct_imap_backup for direct inclusion of imap folder into tar.gz
If you use it, but do not select the "Domains Directory" option,
the inclusion of the "imap" folder will be referencing a wrong path because "-C /home/user" wasn't added to the end of the tar string before "imap" was added.
For the non-domains-directory option, when adding the "imap" folder, it will now add the full " -C /home/user imap" option.
Before, it was using (for example):
-C /home/admin/admin_backups/username backup imap
which isn't where it lives, hence the error.
The error generated is:
Error Compressing the backup file user.admin.username.tar.gz : /bin/tar:
imap: Cannot stat: No such file or directory
/bin/tar: Error exit delayed from previous errors
fixed
Two-Step auth cannot have spaces in "name=" for issuerIf you change the name=DirectAdmin to a value with a space in the directadmin.conf, this will break the "issuer" variable in the QR code image.
The name will have all spaces replaced with underscores: _
fixed
backup_crons.list now url encodedWhen making a change to the backup_crons.list, the given entry will now be url encoded.
Report issue of an ftp username with a + character being replaced with a space when read in, as it would be url decoded.
Shouldn't affect anything unless you're manually editing that file.
created a new bug where the append_path was double encoded.
Found/fixed before this change made it to production.
fixed
Automatically detected and set Filemanager timezoneBecause the FileManager is chrooted, it cannot read the /etc/localtime file.
We had cerated the fm_hour_offset variable which could be manually set.
This addition simply does 2 time checks, one before, and one after the chroot, to detect the offset, and will automatically set the fm_hour_offset variable.
The fm_hour_offset must be set to its default state of 0 in order for this to have an effect.
Debut 2500 will show this if it's doing anything:
Filemanager: timezone offset detected. Setting fm_hour_offset=-6
fixed
rename_username.sh to dump/restore databasesPrevious method was proposed to use the RENAME TABLE syntax,
but we ended up just using the full mysqldump followed by a mysql restore, as it's more reliable, and covers more things like SUPER PRIVILEGES functions, stored procedures, etc..
Affected files:
/usr/local/directadmin/scripts/change_username.sh
/usr/local/directadmin/scripts/change_database_username.php
/usr/local/directadmin/scripts/rename_database.sh
With the new rename_database.sh script, a database can be easily renamed, eg:
./rename_database.sh user_old user_new
But it doesn't update the 'user' portion of user_new, so at the moment shouldn't be used to fully transfer a DB between Users without change the username,
so if you try and run:
./rename_database.sh user1_db user2_db
the DB will be moved, but it won't correct update the Users that need to access it. causing a bit of a cross-User mess.
The change_database_username.php is only for moving all Database that belong to a User, and not to move single DBs between Users.
fixed
ftp_list.php support ftp output with fewer fieldsThe ftp_list.php was originally expecting ftp servers to output something like this:
-rwxr-xr-x 1 admin admin 503 Mar 3 2016 file1.txt
-rw-r--r-- 1 admin admin 1028 Aug 8 2015 file2.txt
-rwxr--r-- 1 admin admin 5747 Sep 14 2012 file3.txt
But some ftp servers might output:
05-03-16 05:16PM 503 file1.txt
08-08-16 05:16PM 1028 file2.txt
09-14-16 05:16PM 5747 file3.txt
which confuses the parser.
The ftp_list.php has been chanegd to use the awk NF variable to count the number of fields.
Regardless of the number of fields, awk will now output only the last value.
Although we could use -1 with nftpls or --list-only with curl, because we want to parse out the directories, we need the full output.
fixed
output change for: "The request you've made cannot be executed because it does not exist in your authority level"Previously, the output for CMD_WRONG or CMD_API_WRONG would generate:
"The request you've made cannot be executed because it does not exist in your authority level"
in full html format, with an response header:
HTTP/1.1 200 OK
This change will now produce:
HTTP/1.1 403 Forbidden
and CMD_API calls will be in the proper url encoded format:
error=1&text=You cannot execute that command&details=The request you've made cannot be executed because it does not exist in your authority level
fixed
Filemanager to support 'multiple' file[] typesThe CMD_FILE_MANAGER and CMD_API_FILE_MANAGER can now upload multiple files via one file selection window, using, eg:
<input type=file name="file\[\]" size=40 multiple="multiple">
fixed
max user quota over 2TBDA was using an integer for passing around the size in meg.
Converted the type to be unsigned long long, to rule out any oversize issues.
The integer format cause large number to flip to negative due to the first bit being set.
fixed
nginx_redirect.conf template not to add location / for blank REDIRECT_PATHChanged the template to exclude the "location / {}" wrap around the rewrite, in the case that the REDIRECT_PATH is blank.
It's not required, since a location / redirect applies to the whole server{} anyway, and this also prevents duplcate location / sections.
Template now looks like:
|*if REDIRECT_PATH=""|
|CUSTOM2|
rewrite ^/.*$ |REDIRECT_TO| |REDIRECT_TYPE|;
|*else|
location |REDIRECT_PATH|/
{
|CUSTOM2|
rewrite ^/.*$ |REDIRECT_TO| |REDIRECT_TYPE|;
}
|*endif|
fixed
Change to use use killall when removing UserPreviously, DA would manually get the list of processes, then kill each one before removing a User.
This wasn't entirely correct in that it's possible a new spawn would be created after the list was assembled.
Changed to use:
/usr/bin/killall -u 'username'
which handles things more cleanly.
fixed
preloaded .htaccess RedirectMatch being inserted into nginx.confOn User nginx.conf rewrites, DA will read a domain's .htaccess file for any RedirectMatch created by DA.
If present, the template:
nginx_redirect.conf
is used, and those redirects are added to the nginx.conf.
But in some cases, the RedirectMatch settings set in the .htaccess file are not intended to be added in this way.
With this change, the behavior has been modified such that a:
RedirectMatch ...
line will only be used by DA in the nginx.conf if it has no leading space/tab characters.
So it must be ^RedirectMatch (for those who know regexes) in order to qualify to be inserted.
Most pre-loaded RedirectMatch .htaccess entries from CMSs typically are surrounded by <IfModule ...> checks, something DA doesn't do since we know mod_rewrite.c is always compiled into Apache.
fixed
tickets.list read efficiencyIn cases where the tickets.list file becomes over-sized due to Admin's not reading/deleting old messages, the read can be very slow.
Changes to the container class should make reading these oversized lists much quicker, as the file is now loaded in fully, and then sorted, instead of the previous default of reading a line, adding it to the end if it's not already present, and sorting.
The drawback with this faster method is that it does not check for duplicates, but they shouldn't (in theory) happen in the first place, so is a reasonable risk/benefit.
fixed
login.log missing some casesIf you post to the CMD_LOGIN page directly from an external form, there would be 0 previous attempts, and the global login.hist file wouldn't have anything in it.
This meant that there were 0 previous attempts (usually loading the DA login page counts as 1 attempt, hence you usually always see 1).
The way it was written was the logging of the login only happened after on the first load of the true page, where the IP was cleared from the login.hist file.
But since a direct login didn't have an entry, there was no IP, so logging to the login.log or user login.hist file never happened.
Code has been changed around such that the actual writing of the session file in the same process as the CMD_LOGIN request will log to the login.log, user login.hist, and clear the global login.hist.
Then another case for authorized connections that do not have sessions (aka: API calls) will log to the login.log for each request, but still not to the login.hist file to prevent flooding.
All requests are still logged to the access log "2016-Nov-23.log" file (for example)
This has the added benefit that the login.hist is not checked/cleared for each CMD_ call. Only on the initial creation of the session, or a failed login, so should speed up connections somewhat.
fixed
check_subdomain_owner didn't allow subdomains on your own pointerIf you had a pointer called domain-pointer.com, DA previously wouldn't let you create a domain sub.domain-pointer.com stating it doesn't belong to you.
That because DA notices that /etc/virtual/domain-pointer.com existed, yet wasn't in the User's domains.list file.
Change to the logic so it simply uses the /etc/virtual/domainowners file, so it can very quickly see who owns what.
fixed
nginx_redirect.conf template to end with (/|$) instead of / (TEMPLATE)Changed:
location |REDIRECT_PATH|/
To be:
location ~ ^|REDIRECT_PATH|(/|$)
This will allow a redirect value of:
/some/file.txt
(previously didn't match, as it needed "/some/file.txt/")
as well as allowing adding "/folder" to allow:
/folder
/folder/
/folder/file.txt
which would redirect everything in /folder to the new location, while not matching:
/folder2
fixed
Remove bad cron from list if crontab errored during additionIf you create a cron with bad values, crontab would return an error, and not add them.
The issue was that DA had already saved the crontab.conf file so the bad cron was left in the list, causing confusion if other crons were attempted to be added.
Change is to remove a bad cron from the list anytime the crontab call returns a non-zero result.
fixed
ensure awstats links are owned by rootBecause apache will refuse to follow a link if the link owners does not match the destination owner, DA will now confirm the ownership of the link.
By default, the links are all created by root, so this isn't an issue.
But upon restore, because tar runs as the User, the link would likely be chowned to the User, thus the link doesn't match.
New internal directadmin.conf variable:
ensure_root_awstats_links=1
enabled by default. Set to 0 if you do not wish for DA to check this.
It will check:
- icon
- lang
- lib
- plugins
- docs
but will not check the index.html, which should be reset nightly already.
If the value is not chowned to root, DA will not change the ownership, but full delete the old link, and re-create a new one pointing to the default path.
So if you're using some custom path, you'll likely want to disable this feature.
We fully delete it because we cannot trust any link value that the User could have set.
Note that the script:
/usr/local/directadmin/scripts/awstats_process.sh
already had a variable:
ENSURE_ROOT_LINKS=0
which is disabled by default.
It does roughly the same thing, but it's checks are not as strict as DA's so if you do need to use ENSURE_ROOT_LINKS=1, run it once, then disable it.
It's better to rely on ensure_root_awstats_links=1
fixed
Filtering on CMD_SELECT_USERSRelating to this report:
http://seclists.org/bugtraq/2017/Jan/12
filter the location variable to prevent script injection.
Note that because of the check_referer=1 default value, there is no security threat if you have it enabled.
See:
https://help.directadmin.com/item.php?id=619
and just falls under the category of bug-fix.
fixed
session security improvements (SECURITY)Don't allow login/login-as if session is already logged in and referer is bad.
Don't allow logout if referer is a user controlled url within DA.
fixed
reload dns on monthly dnssec signThe monthly dnssec re-sign was not reloading named.
fixed
Create login key through login-as with login keyYou've got the ability to use a login key to connect to your Admin or Reseller (eg: "admin"), so you don't need to use your own password.
If you wish to use this login key to use the "login as" feature to login as a User (eg: "fred"),
but then want to create a login key for that User fred,
the "passwd" field in the form was incorrectly checking your admin login key against fred's current list, so the admin login key couldn't be used to create a login key for fred.
Fixed by correctly checking the correct list of keys.
fixed
ftp_list.php ftps required double leading forward slashWhen backing up to ftp with ftps, this uses curl.
The ftp you specify might be / or /admin_backups/, for example.
Previously, this would have been given to curl like:
/usr/local/bin/curl --config /home/tmp/1828.cfg --ftp-ssl -k --silent --show-error --list-only ftp://1.2.3.4:21/admin_backups/
But this actually wasn't correct, because the first slash is just a separator, making the ftp path just:
admin_backups/
which is just relative to the login.
Because some ftp accounts are not chrooted, this might not be correct if they pass the ftp_path:
/home/user/admin_backups/
because if the default login path is /home/user, then curl would be trying to cd to:
/home/user/home/user/admin_backups/
which would not be correct.
The solution is to add a 2nd leading slash for curl in the script, so it looks like:
/usr/local/bin/curl --config /home/tmp/1828.cfg --ftp-ssl -k --silent --show-error --list-only ftp://1.2.3.4:21//admin_backups/
fixed
Awstats to run as User (SECURITY) * will increase User disk usage *Awstats will now be run as the User, and no longer as root.
This requires a conversion which will increase the User's used disk space, so it's go to ensure the Users are not maxed out, or the conversion will abort.
If there are any root-owned files that are 600 (not readable by the user), the copy will have issues, the diff won't exit with code 0, so the conversion would abort.
Conversion will copy, as User:
cp awstats awstats.user
and if that worked and "diff" returns code 0.
If not, everything is aborted, start are not run.
Next, run as the User:
mv awstats awstats.old
and if that works:
mv awstats.user awstats
Then the tricky part, handled by DA is to delete the root owned files (awstats.old), which requires root access.
DA does this very carefully, this is the task.queue command used to do it:
echo "action=delete&value=secure_disposal&user=${USER}&path=${STATS_DIR}.old" >> /usr/local/directadmin/data/task.queue
Related directadmin.conf option:
secure_disposal=/home/.disposal
*** IMPORTANT***
If you have Users on a different partition, like /home2
Because the awstats.old is simply "moved", moving cross-partition doesn't work, so you might need to clear the awstats.old folders manually, after you've confirmed the new awstats folder is computing stats correctly.
=====================
You may have realized that the User does not have read permissions on their apache logs in:
/var/log/httpd/domains/domain.com.log
to get around this issue, the awstats_process.sh, using AWSTATS_MODE=1, will create a hardlink in:
/var/user_logs/username/domain.com.log
where:
/var/user_logs root:root: 711
/var/user_logs/username username:username 500
/var/user_logs/user/domain.com.log root:root 644
so that the logs can be read, but not modified.
The link is removed after the end of the awstats_process.sh call.
If hard-links don't work for you, then you can use:
AWSTATS_MODE=2
which does a full copy of each log, instead of using a hard-link.
Credit to Bartosz Kwitniewski for debugging and reporting the issue.