DirectAdmin: Improve performance and security

Introduction
When you set up a fresh DirectAdmin server, the default settings are functional but not secure or optimized. The first thing you should do is harden the server and improve its performance. Here’s what I did to optimize my DirectAdmin server for hosting my customers' websites.
Prerequisites
At the time of writing, I was using DirectAdmin v1.67 on Ubuntu 20.04, running on an Ampere ARM-based compute instance.
Solutions
-
Prepare envs
export SMTP_USER="YOUR_SMTP_USER" export SMTP_PASS="YOUR_SMTP_PASS" export SMTP_HOST="YOUR_SMTP_HOST" export SMTP_PORT="YOUR_SMTP_PORT" export AWS_S3_KEY="YOUR_AWS_S3_KEY" export AWS_S3_SECERT="YOUR_AWS_S3_SECERT" export AWS_S3_BUCKET="YOUR_AWS_S3_BUCKET" export AWS_S3_REGION="s3.ap-northeast-1.amazonaws.com" export ADMIN_NAME="XXX Admin" export DA_HOSTNAME=$(hostname -f) export DA_EMAIL=admin@$(hostname -f) export DA_NS1=ns0.hostcp.xyz export DA_NS2=ns1.hostcp.xyz
-
Increase the memory allocation for the
/tmp
directory by editing the/etc/fstab
filetmpfs /tmp tmpfs defaults,noexec,nosuid,nodev,size=1G 0 0
-
Disable potentially dangerous PHP functions for improved security
cd /usr/local/directadmin/custombuild ./build secure_php
-
Set
clean_old_webapps
to true to remove outdated scripts and minimize potential issuescd /usr/local/directadmin/custombuild ./build set clean_old_webapps yes
-
Turn off remote MySQL access to enhance security add the following to the
[mysqld
] section of the/etc/my.cnf
bind-address = 127.0.0.1
-
Use
php-fpm
mode/usr/local/directadmin/custombuild/build set php1_release 8.1 /usr/local/directadmin/custombuild/build set php2_release 8.0 /usr/local/directadmin/custombuild/build set php3_release 7.4 /usr/local/directadmin/custombuild/build set php4_release 5.6 /usr/local/directadmin/custombuild/build set php1_mode php-fpm /usr/local/directadmin/custombuild/build set php2_mode php-fpm /usr/local/directadmin/custombuild/build set php3_mode php-fpm /usr/local/directadmin/custombuild/build set php4_mode php-fpm /usr/local/directadmin/custombuild/build php n /usr/local/directadmin/custombuild/build rewrite_confs
-
Use Nginx reverse proxy
You can boost performance by serving static files with Nginx and handling PHP files with Apache:
cd /usr/local/directadmin/custombuild ./build update ./build set webserver nginx_apache ./build nginx_apache
-
Install ModSecurity for enhanced web application protection
/usr/local/directadmin/custombuild/build set modsecurity yes /usr/local/directadmin/custombuild/build set modsecurity_ruleset owasp /usr/local/directadmin/custombuild/build modsecurity /usr/local/directadmin/custombuild/build modsecurity_rules /usr/local/directadmin/custombuild/build rewrite_confs
-
Enable the jail system for improved security and isolation
/usr/local/directadmin/custombuild/build jailshell
-
Install Rspamd for advanced spam filtering and email protection
/usr/local/directadmin/custombuild/build set spamd rspamd /usr/local/directadmin/custombuild/build rspamd /usr/local/directadmin/custombuild/build exim_conf
-
Install ClamAV for reliable antivirus protection on the server
/usr/local/directadmin/custombuild/build set clamav yes /usr/local/directadmin/custombuild/build set modsecurity_uploadscan yes /usr/local/directadmin/custombuild/build set pureftpd_uploadscan yes /usr/local/directadmin/custombuild/build clamav
-
Enable common PHP extensions for better compatibility and functionality
/usr/local/directadmin/custombuild/build set_php "opcache" yes /usr/local/directadmin/custombuild/build set_php "gmp" yes /usr/local/directadmin/custombuild/build set_php "imagick" yes /usr/local/directadmin/custombuild/build set_php "redis" yes /usr/local/directadmin/custombuild/build set_php "snuffleupagus" yes /usr/local/directadmin/custombuild/build "php_opcache" /usr/local/directadmin/custombuild/build "php_gmp" /usr/local/directadmin/custombuild/build "php_imagick" /usr/local/directadmin/custombuild/build "php_redis" /usr/local/directadmin/custombuild/build "php_snuffleupagus"
-
Schedule a daily ClamAV scan with an automated script
Create the script:
mkdir -p /root/scripts mkdir -p /var/log/clamav vi /root/scripts/clamscan.sh
#!/bin/bash LOGFILE="/var/log/clamav/clamav-$(date +'%Y-%m-%d').log"; EMAIL_MSG="Please see the log file attached."; EMAIL_FROM="root@$(hostname -f)"; EMAIL_TO="root@$(hostname -f)"; DIRTOSCAN="/home"; for S in ${DIRTOSCAN}; do DIRSIZE=$(du -sh "$S" 2>/dev/null | cut -f1); echo "Starting AV scan of "$S" directory. Amount of data to be scanned is "$DIRSIZE"."; clamscan -ri --remove "$S" >> "$LOGFILE"; # get the value of "Infected lines" MALWARE=$(tail "$LOGFILE"|grep Infected|cut -d" " -f3); # if the value is not equal to zero, send an email with the log file attached if [ "$MALWARE" -ne "0" ];then # using heirloom-mailx below echo "$EMAIL_MSG"|mail -a "$LOGFILE" -s "Malware Found" -r "$EMAIL_FROM" "$EMAIL_TO"; fi done exit 0;
Next, add the script to the server's cron job for automated execution:
chmod +x /root/scripts/clamscan.sh ln /root/scripts/clamscan.sh /etc/cron.daily/clamscan_daily
-
Fine-tune DirectAdmin configuration for optimal performance and security
/usr/local/directadmin/directadmin set force_hostname $(hostname -f) /usr/local/directadmin/directadmin set dkim 1 /usr/local/directadmin/directadmin set letsencrypt_renewal_notice_to_admins 0 /usr/local/directadmin/directadmin set clear_blacklist_ip_time 1440 /usr/local/directadmin/directadmin set unblock_brute_ip_time 1440 /usr/local/directadmin/directadmin set ip_brutecount 10 /usr/local/directadmin/directadmin set user_brutecount 10 /usr/local/directadmin/directadmin set enforce_difficult_passwords 1 /usr/local/directadmin/directadmin set hide_brute_force_notifications 1 /usr/local/directadmin/directadmin set purge_spam_days 7 /usr/local/directadmin/directadmin set default_ttl 14400 /usr/local/directadmin/directadmin set brute_force_scan_apache_logs 2 /usr/local/directadmin/directadmin set one_click_webmail_login 1 /usr/local/directadmin/directadmin set one_click_pma_login 1 /usr/local/directadmin/directadmin set webmail_link roundcube /usr/local/directadmin/directadmin set one_click_webmail_link /webmail
-
Set up SSL for email and applications to ensure secure communication
Edit /etc/httpd/conf/extra/httpd-includes.conf using the configuration below:
################################################################################ # Mod_Rewrite ################################################################################ <location /phpMyAdmin> RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} </location> <location /webmail> RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} </location> <location /squirrelmail> RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} </location> <location /roundcube> RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} </location> <location /atmail> RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} </location>
Next, set
disable_plaintext_aut
h toyes
in the/etc/dovecot.conf file
.Prevent unencrypted email submissions:
# Prevents unencrypted mail submission. drop !encrypted = * authenticated = * message = Your connection must be encrypted. log_message = Connection from \ [$sender_host_address]($authenticated_id) was \ not encrypted.
Update webmail to use encrypted connections in
/var/www/html/roundcube/config/config.inc.php
:$config['smtp_host'] = 'tls://ser1.hostname.xyz:587';
Preserve the configuration by copying
config.inc.ph
p to/usr/local/directadmin/custombuild/custom/roundcube/config.inc.php
. -
Set the admin name
sed -i "0,/name=admin/s//name=${ADMIN_NAME}/" /usr/local/directadmin/data/users/admin/user.conf
-
Update CustomBuild settings
/usr/local/directadmin/custombuild/build set email root@$(hostname -f) /usr/local/directadmin/custombuild/build set notifications yes /usr/local/directadmin/custombuild/build set updates yes /usr/local/directadmin/custombuild/build set webapps_updates yes /usr/local/directadmin/custombuild/build set cron_frequency weekly /usr/local/directadmin/custombuild/build set use_hostname_for_alias yes /usr/local/directadmin/custombuild/build set redirect_host_https yes /usr/local/directadmin/custombuild/build set phpmyadmin_public no /usr/local/directadmin/custombuild/build phpmyadmin /usr/local/directadmin/custombuild/build roundcube /usr/local/directadmin/custombuild/build dovecot_conf /usr/local/directadmin/custombuild/build rewrite_confs
-
Disable outdated DirectAdmin skin
touch /usr/local/directadmin/data/skins/enhanced/.disabled
-
Configure CSF Settings
Set
SMTP_BLOCK = "0"
in/etc/csf/csf.conf
. -
Custome email templates
mkdir -p /usr/local/directadmin/data/templates/custom wget -O /usr/local/directadmin/data/templates/custom/a_welcome.txt https://raw.githubusercontent.com/powerkernel/directadmin-conf/main/email-templates/a_welcome.html wget -O /usr/local/directadmin/data/templates/custom/u_welcome.txt https://raw.githubusercontent.com/powerkernel/directadmin-conf/main/email-templates/u_welcome.html wget -O /usr/local/directadmin/data/templates/custom/r_welcome.txt https://raw.githubusercontent.com/powerkernel/directadmin-conf/main/email-templates/r_welcome.html wget -O /usr/local/directadmin/data/admin/a_welcome.txt https://raw.githubusercontent.com/powerkernel/directadmin-conf/main/email-templates/a_welcome.html wget -O /usr/local/directadmin/data/admin/r_welcome.txt https://raw.githubusercontent.com/powerkernel/directadmin-conf/main/email-templates/r_welcome.html wget -O /usr/local/directadmin/data/users/admin/u_welcome.txt https://raw.githubusercontent.com/powerkernel/directadmin-conf/main/email-templates/u_welcome.html wget -O /usr/local/directadmin/data/templates/custom/message_footer.txt https://raw.githubusercontent.com/powerkernel/directadmin-conf/main/email-templates/message_footer.txt wget -O /usr/local/directadmin/data/templates/custom/message_tech.txt https://raw.githubusercontent.com/powerkernel/directadmin-conf/main/email-templates/message_tech.html wget -O /usr/local/directadmin/data/templates/custom/message_user.txt https://raw.githubusercontent.com/powerkernel/directadmin-conf/main/email-templates/message_user.html wget -O /usr/local/directadmin/data/templates/custom/lost_password_email.txt https://raw.githubusercontent.com/powerkernel/directadmin-conf/main/email-templates/lost_password_email.html wget -O /usr/local/directadmin/data/templates/custom/mail_settings.html https://raw.githubusercontent.com/powerkernel/directadmin-conf/main/misc/mail_settings.html wget -O /usr/local/directadmin/data/templates/custom/outlook_setup.reg https://raw.githubusercontent.com/powerkernel/directadmin-conf/main/misc/outlook_setup.reg
-
Configure STMP for admin account
wget -O /etc/exim.routers.pre.conf http://files.directadmin.com/services/SpamBlocker/smart_route/exim.routers.pre.conf wget -O /etc/exim.transports.pre.conf http://files.directadmin.com/services/SpamBlocker/smart_route/exim.transports.pre.conf wget -O /etc/exim.authenticators.post.conf http://files.directadmin.com/services/SpamBlocker/smart_route/exim.authenticators.post.conf sed -i "s/your@email.com : yourpass/$SMTP_USER : $SMTP_PASS/g" /etc/exim.authenticators.post.conf sed -i "s/smtp.yourisp.com/$SMTP_HOST::$SMTP_PORT/g" /etc/exim.routers.pre.conf sed -i "s/manualroute/manualroute\n senders = *@$(hostname -f)/g" /etc/exim.routers.pre.conf
-
Disable the email feature for new accounts to help prevent spam
mkdir -p /usr/local/directadmin/scripts/custom wget -O /usr/local/directadmin/scripts/custom/user_create_post.sh https://raw.githubusercontent.com/powerkernel/directadmin-conf/main/scripts/user_create_post.sh chmod 755 /usr/local/directadmin/scripts/custom/user_create_post.sh
-
Configure S3 backup
Create a file
/root/.aws/credentials
with:[default] region = nl-ams endpoint_url = https://s3.nl-ams.scw.cloud aws_access_key_id = yyy aws_secret_access_key = xxx
Add an s3 sync script at
/usr/local/directadmin/scripts/custom/all_backups_post/s3.sh
:#!/bin/bash # This script moves successful Admin backups to an S3 bucket and deletes the local copies. # Replace with your actual bucket name S3_BUCKET_NAME="sg2-hostcp-xyz" LOCAL_BACKUP_PATH="/home/admin/admin_backups" # Ensure the script runs only for 'admin' type backups that were successful and where backup is local if [ "$type" == "admin" ] && [ "$success" -eq 1 ] && [ "$where" == "local" ]; then echo "Backup type is 'admin', the operation was successful, and the location is local." # Check if the backup directory exists if [ -d "$LOCAL_BACKUP_PATH" ]; then # Sync the local backup directory to the S3 bucket aws s3 sync "$LOCAL_BACKUP_PATH" "s3://$S3_BUCKET_NAME/" --quiet # Check if AWS sync command was successful if [ $? -eq 0 ]; then echo "Backup successfully synced to S3 bucket: $S3_BUCKET_NAME" # Delete local backup files after successful upload to S3 echo "Deleting local backup files $LOCAL_BACKUP_PATH" find "$LOCAL_BACKUP_PATH" -mindepth 1 -delete echo "Local backup files deleted." else echo "Error syncing backup to S3 bucket." exit 1 fi else echo "Local backup directory does not exist: $LOCAL_BACKUP_PATH" exit 1 fi else echo "This script only runs for successful 'admin' type backups with local storage." fi
Make the script executable:
chmod +x /usr/local/directadmin/scripts/custom/all_backups_post/s3.sh
-
Set up the CSF Allow and Ignore lists
Add the following text to
/etc/csf/csf.pignore
:# system whitelist user:ubuntu user:snap_daemon exe:/usr/lib/systemd/systemd exe:/usr/lib/systemd/systemd-networkd exe:/usr/lib/systemd/systemd-resolved exe:/lib/systemd/systemd exe:/lib/systemd/systemd-networkd exe:/lib/systemd/systemd-resolved exe:/usr/bin/clamd exe:/usr/bin/freshclam exe:/usr/sbin/clamd exe:/usr/sbin/rpcbind exe:/usr/sbin/uuidd exe:/opt/datadog-agent/bin/agent/agent exe:/opt/datadog-agent/embedded/bin/trace-agent exe:/opt/datadog-agent/embedded/bin/process-agent
-
Custome DNS template
touch /usr/local/directadmin/data/templates/custom/dns_a.conf touch /usr/local/directadmin/data/templates/custom/dns_aaaa.conf touch /usr/local/directadmin/data/templates/custom/dns_cname.conf touch /usr/local/directadmin/data/templates/custom/dns_mx.conf touch /usr/local/directadmin/data/templates/custom/dns_txt.conf
Edit
/usr/local/directadmin/data/templates/custom/dns_a.conf
:|*if IS_IPV6!="yes"| |DOMAIN|.=|IP| |*endif|
Edit
/usr/local/directadmin/data/templates/custom/dns_aaaa.conf
:|*if IS_IPV6="yes"| |DOMAIN|.=|IP| |*endif|
Edit
/usr/local/directadmin/data/templates/custom/dns_cname.conf
:www.|DOMAIN|.=|DOMAIN|.
Edit
/usr/local/directadmin/data/templates/custom/dns_mx.conf
:|HOSTNAME|.=10
Edit
/usr/local/directadmin/data/templates/custom/dns_txt.conf
:|DOMAIN|.="v=spf1 include:_spf.|HOSTNAME| ~all" _dmarc="v=DMARC1; p=quarantine; rua=mailto:|USERNAME|@|DOMAIN|; ruf=mailto:|USERNAME|@|DOMAIN|"
Add an SPF record for the server's hostname:
v=spf1 ip4:x.x.x.x ip6:xxxx ~all
-
Finally, rebuild the configuration and restart the server
/usr/local/directadmin/custombuild/build rewrite_confs reboot
Conclusion
Now you have a hardened and better-performing DirectAdmin server. The next step could be setting up multiple DNS servers using DirectSlave.