DirectAdmin Production Server Setup

Today I will instruct to setup a professional hosting server.

Configure your Hostname DNS first, so that ACME auto SSL can be enabled

1) Download CloudLinux ISO file;

https://www.repo.cloudlinux.com/cloudlinux/9/iso/x86_64/CloudLinux-9.4-x86_64-minimal.iso

Or, choose the latest version from https://www.repo.cloudlinux.com/cloudlinux/

2) Upload and attach the iso as your installation source

3) Start installation by disk partition;

/biosboot = 100 MiB
/boot = 512 MiB
/swap = 16 GiB

/ = rest of space

4) Set network interface, and hostname

5) Set root password

6) Start install finally


7) Get a trial license of CloudLinux, or buy a license from reseller

https://cloudlinux.com/trial/


8) Activate CloudLinux;

There are several ways to register your server with CloudLinux Network:


using the activation key by following commands:

yum install rhn-setup --enablerepo=cloudlinux-base

/usr/sbin/rhnreg_ks --activationkey=<activation key>


using IP-based licensing: (Buy a license from a reseller, eg: my.interserver.net)

yum install rhn-setup --enablerepo=cloudlinux-base

/usr/sbin/clnreg_ks

9) Update the system

yum update

Then reboot the system


10) Download DirectAdmin and pre-load for some command;

bash <(curl -fsSL https://download.directadmin.com/setup.sh) 'auto'
export DA_EMAIL=sysadmin@yourwebsite.com
export DA_NS1=ns1.yourwebsite.com
export DA_NS2=ns2.yourwebsite.com
export DA_HOSTNAME="host.yourwebsite.com"
export DA_PHP1_MODE=fastcgi
export DA_UNIT=yes
export DA_WEBSERVER=nginx_apache
export DA_CHANNEL=stable

11) Now, buy a license from directadmin.com

12) Finally, install DirectAdmin by command with your license key;

bash <(curl -fsSL https://download.directadmin.com/setup.sh) 'Provided license key should go here'

13) Do not reboot after the installation, some scripts are still installing in background

Login to DirectAdmin panel to see the background process until it is finished

After finishing the task, set the php mode to "fastcgi" from Custombuild Options


14) Configure CUSTOMBUILD options for DirectAdmin

Additionally, create some folders and set permissions, for furture tuning apps;

cd /usr/local/directadmin/data/templates/

mkdir custom
chmod 711 custom
chown diradmin:diradmin custom


cd /usr/local/directadmin/custombuild/

mkdir custom
chmod 711 custom
chown diradmin:diradmin custom

cd custom
mkdir roundcube
chmod 711 roundcube
chown diradmin:diradmin roundcube


cd /usr/local/directadmin/scripts/

mkdir custom
chmod 711 custom
chown diradmin:diradmin custom

15) Check custombuild Update to install/update any scripts

16) Lookup System Information to check any program failed to run, if any failed, build that program from custombuild section, or solve any other issue


17) Install alt-php for CloudLinux php selector

yum groupinstall alt-php


da build set_php htscanner yes

da build mod_htscanner2


Set the Global php limit for alt-php;

nano /etc/cl.selector/global_php.ini

Add the following settings to the bottom of the file;

max_execution_time = 300

max_input_time = -1

max_input_vars = 10000

memory_limit = 768M

post_max_size = 512M

upload_max_filesize = 500M


Additionally, Set modifiable limit ranges that user can customize;


nano /etc/cl.selector/php.conf


Then re-build the PHP-Selector with reinstall command;

yum reinstall lvemanager cagefs alt-python27-cllib

cagefsctl -r


Then reboot the server


18) Change Database system to MySQL-Governor

If it is an existing production server, backup all databases first;

yum remove db-governor db-governor-mysql

yum install governor-mysql  --yes

/usr/share/lve/dbgovernor/mysqlgovernor.py --install --yes


yum update cagefs lvemanager


Then reboot the server


19) Enable System SSL serverwide;

/usr/local/directadmin/scripts/letsencrypt.sh server_cert


20) Enable DKIM for hostname;

Create a new DNS zone for hostname

Reconfigure the hostname to Exim;

/usr/local/directadmin/scripts/hostname.sh host.mywebsite.com

Install dkim for hostname;

cd /usr/local/directadmin/scripts

./dkim_create.sh host.mywebsite.com

Find/copy TXT records from DNS manager

Or, find the DKIM file in /etc/virtual/host.mywebsite.com/dkim.public.key


Force DKIM set to all users;

cd /usr/local/directadmin
./directadmin set dkim 1 restart
cd /usr/local/directadmin/custombuild
./build exim

./build eximconf


Also enable DMARC record for all domains;

cp /usr/local/directadmin/data/templates/dns_txt.conf /usr/local/directadmin/data/templates/custom/dns_txt.conf

cd /usr/local/directadmin/data/templates/custom/

echo '_dmarc="v=DMARC1; p=reject; sp=reject; pct=100; adkim=r; aspf=s; ruf=mailto:spam-reports@|DOMAIN|"' >> dns_txt.conf


21) Setup spamassassin for spam control




cd /usr/local/directadmin/scripts/custom/


nano /usr/local/directadmin/scripts/custom/user_create_post.sh

Add the below script to new file;


#!/bin/sh
if [ "$spam" = "ON" ]; then
  DIR=/home/$username/.spamassassin
  mkdir -p $DIR
  UP=$DIR/user_prefs
  if [ ! -s ${UP} ]; then
    echo 'required_score 3.5' > ${UP}
    echo 'rewrite_header subject ***SPAM***' >> ${UP}
    echo 'report_safe 0' >> ${UP}
    echo 'score RDNS_NONE 6.9' >> ${UP}
    echo 'score DKIM_INVALID 5.9' >> ${UP}
    echo 'score SPF_FAIL 7.9' >> ${UP}
    echo 'score SPF_SOFTFAIL 7.9' >> ${UP}
    chown $username:$username ${UP}
    chmod 644 ${UP}
  fi
  chown ${username}:mail $DIR
  chmod 771 $DIR
fi
exit 0;


Then, set file permission;

chmod 755 user_create_post.sh


nano /usr/local/directadmin/scripts/custom/domain_create_post.sh

Add the below script to new file;


#!/bin/sh
if [ "${domain}" != "" ]; then
  FCONF=/etc/virtual/${domain}/filter.conf
  if [ ! -s ${FCONF} ]; then
    echo 'high_score=16' > ${FCONF}
    echo 'high_score_block=yes' >> ${FCONF}
    echo 'where=inbox' >> ${FCONF}
    chown mail:mail ${FCONF}
   
    echo "action=rewrite&value=filter&user=$username" >> /usr/local/directadmin/data/task.queue
  fi
fi
exit 0;


Then, set file permission;

chmod 755 domain_create_post.sh


cd /usr/local/directadmin/data/templates/custom/

nano /usr/local/directadmin/data/templates/custom/spam_defaults.json


Add the below script in the new spam_defaults.json file;

{
        "required_hits" : "3.5",
        "score RDNS_NONE" : "6.9",
        "score DKIM_INVALID" : "5.9",
        "score SPF_FAIL" : "7.9",
        "score SPF_SOFTFAIL" : "7.9",
        "high_score" : "16",
        "high_score_block" : "yes",
        "rewrite_subject" : "1",
        "subject_tag" : "***SPAM***",
        "where" : "inbox",
        "report_safe" : "0"
}

Set file permission;
chmod 755 spam_defaults.json

Add some rules to the spamassassin's local config file;

nano /etc/mail/spamassassin/local.cf

Insert the below codes at the end of the file;

# Custom spamassassin rules
score RDNS_NONE 6.9
score DKIM_INVALID 5.9
score SPF_FAIL 7.9
score SPF_SOFTFAIL 7.9
rewrite_header Subject ***SPAM***
report_safe 0
required_score 3.5
high_score 16
high_score_block yes
where inbox


Then, setup spamassassin;

cd /usr/local/directadmin/custombuild/

da build set spamd spamassassin
da build spamassassin
da build set easy_spam_fighter yes
da build easy_spam_fighter

echo "EASY_NO_REVERSE_IP==690" >> /etc/exim.easy_spam_fighter/variables.conf.custom

echo "EASY_DKIM_FAIL==590" >> /etc/exim.easy_spam_fighter/variables.conf.custom

echo "EASY_SPF_FAIL==790" >> /etc/exim.easy_spam_fighter/variables.conf.custom

echo "EASY_SPF_SOFT_FAIL==790" >> /etc/exim.easy_spam_fighter/variables.conf.custom

echo "EASY_IS_SPAM==70" >> /etc/exim.easy_spam_fighter/variables.conf.custom

echo "EASY_HIGH_SCORE_DROP==1600" >> /etc/exim.easy_spam_fighter/variables.conf.custom

Build spam fighter again;

da build easy_spam_fighter

da build exim_conf


cd /usr/local/directadmin/scripts/custom/

nano spam.sh

Add the below script to spam.sh;


#!/bin/sh
for i in `ls /usr/local/directadmin/data/users`; do
{
  username=$i spam=ON /usr/local/directadmin/scripts/custom/user_create_post.sh
  for d in `cat /usr/local/directadmin/data/users/$i/domains.list`; do
  {
    username=$i domain=$d /usr/local/directadmin/scripts/custom/domain_create_post.sh
  };
  done;
};
done;
exit 0;

Then, set file permission;

chmod 755 spam.sh

Then, run only once the spam.sh file;

./spam.sh

Then, delete the spam.sh file;

rm spam.sh

Reboot the server.

22) Enable one-click login for Webmail RoundCube


da config-set one_click_webmail_login 1
systemctl restart directadmin
da build dovecot_conf
da build exim_conf
da build roundcube

23) Secure Webmail access URL

Add webmail DNS entry to dns template;

If not exist, create the "custom" folder first;

cd /usr/local/directadmin/data/templates/
mkdir custom
chmod 711 custom
chown diradmin:diradmin custom

cd /usr/local/directadmin/data/templates/custom/
cp /usr/local/directadmin/data/templates/dns_a.conf /usr/local/directadmin/data/templates/custom/dns_a.conf

perl -pi -e "s/^smtp=\\|IP\\|\n/smtp=\\|IP\\|\nwebmail=\\|IP\\|\n/" dns_a.conf


Add the webmail subdomain to LetsEncrypt auto SSL;

nano /usr/local/directadmin/conf/directadmin.conf

Make sure the below two lines has the specified subdomains to secure;

letsencrypt_list=www:smtp:mail:webmail:pop:ftp

letsencrypt_list_selected=www:smtp:mail:webmail:pop:ftp


Enable webmail subdomain for non-secure port;

nano /usr/local/directadmin/data/templates/custom/virtual_host2.conf.CUSTOM.4.post

</VirtualHost>

<VirtualHost |IP|:|PORT_80| |MULTI_IP|>

   ServerName mail.|DOMAIN|
   ServerAlias webmail.|DOMAIN|
   ServerAdmin |ADMIN|
   DocumentRoot /var/www/html/roundcube

   CustomLog /var/log/httpd/domains/|DOMAIN|.bytes bytes
   CustomLog /var/log/httpd/domains/|DOMAIN|.log combined
   ErrorLog /var/log/httpd/domains/|DOMAIN|.error.log

   <IfModule !mod_ruid2.c>
       SuexecUserGroup webapps webapps
   </IfModule>


Enable webmail subdomain for secure port;

nano /usr/local/directadmin/data/templates/custom/virtual_host2_secure.conf.CUSTOM.4.post

</VirtualHost>

<VirtualHost |IP|:|PORT_443| |MULTI_IP|>

   ServerName mail.|DOMAIN|
   ServerAlias webmail.|DOMAIN|
   ServerAdmin |ADMIN|
   DocumentRoot /var/www/html/roundcube

   SSLEngine on
   SSLCertificateFile |CERT|
   SSLCertificateKeyFile |KEY|
   |CAROOT|

   CustomLog /var/log/httpd/domains/|DOMAIN|.bytes bytes
   CustomLog /var/log/httpd/domains/|DOMAIN|.log combined
   ErrorLog /var/log/httpd/domains/|DOMAIN|.error.log

   <IfModule !mod_ruid2.c>
       SuexecUserGroup webapps webapps
   </IfModule>


Then run;


echo "action=rewrite&value=httpd" >> /usr/local/directadmin/data/task.queue


/usr/local/directadmin/dataskq d


da build rewrite_confs


24) (Optional) If nginx available to your server, secure webmail subdomain

cd /usr/local/directadmin/data/templates/custom/
cp /usr/local/directadmin/data/templates/nginx_server.conf /usr/local/directadmin/data/templates/custom/nginx_server.conf

cp /usr/local/directadmin/data/templates/nginx_server_secure.conf /usr/local/directadmin/data/templates/custom/nginx_server_secure.conf

nano nginx_server.conf

Add the following to the bottom of the file;


server

{

       listen |IP|:|PORT_80|;

       |MULTI_IP|


       server_name mail.|DOMAIN| webmail.|DOMAIN|;


       root /var/www/html/roundcube;

       index index.php index.html index.htm;


       access_log /var/log/nginx/domains/|DOMAIN|.log;

       access_log /var/log/nginx/domains/|DOMAIN|.bytes bytes;

       error_log /var/log/nginx/domains/|DOMAIN|.error.log;


|*if HAVE_PHP1_FPM="1"|

       # use fastcgi for all php files

       location ~ \.php$

       {

               try_files $uri =404;

               fastcgi_split_path_info ^(.+\.php)(/.+)$;

               include /etc/nginx/fastcgi_params;

               fastcgi_index index.php;

               fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

               include /etc/nginx/nginx_limits.conf;


               if (-f $request_filename)

               {

                       fastcgi_pass unix:/usr/local/php|PHP1_RELEASE|/sockets/webapps.sock;

               }

       }

|*endif|


|*if HAVE_NGINX_PROXY="1"|

       location /

       {

               # access_log off;

               proxy_pass http://127.0.0.1:|PORT_8080|;

               proxy_set_header X-Client-IP      $remote_addr;

               proxy_set_header X-Accel-Internal /nginx_static_files;

               proxy_set_header Host             $host;

               proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;

       }

       location /nginx_static_files/

       {

               # access_log  /var/log/nginx/access_log_proxy;

               alias       /var/www/html/roundcube/;

               internal;

       }

|*endif|


       # deny access to apache .htaccess files

       location ~ /\.ht

       {

               deny all;

       }

}





Also for secure the virtualhost;


nano nginx_server_secure.conf


Add the following to the bootom of the file;


server

{

       listen |IP|:|PORT_443| ssl|SPACE_HTTP2|;

       |MULTI_IP|


       server_name mail.|DOMAIN| webmail.|DOMAIN|;


       root /var/www/html/roundcube;

       index index.php index.html index.htm;


       access_log /var/log/nginx/domains/|DOMAIN|.log;

       access_log /var/log/nginx/domains/|DOMAIN|.bytes bytes;

       error_log /var/log/nginx/domains/|DOMAIN|.error.log;


        ssl_certificate |CERT|;

        ssl_certificate_key |KEY|;


|*if HAVE_PHP1_FPM="1"|

       # use fastcgi for all php files

       location ~ \.php$

       {

               try_files $uri =404;

               fastcgi_split_path_info ^(.+\.php)(/.+)$;

               include /etc/nginx/fastcgi_params;

               fastcgi_index index.php;

               fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

               include /etc/nginx/nginx_limits.conf;


               if (-f $request_filename)

               {

                       fastcgi_pass unix:/usr/local/php|PHP1_RELEASE|/sockets/webapps.sock;

               }

       }

|*endif|


|*if HAVE_NGINX_PROXY="1"|

       location /

       {

                proxy_buffering |PROXY_BUFFERING|;

                proxy_pass https://|PROXY_IP|:|PORT_8081|;

                proxy_set_header X-Client-IP      $remote_addr;

                proxy_set_header X-Accel-Internal /nginx_static_files;

                proxy_set_header Host             $host;

                proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;

                proxy_hide_header Upgrade;


       }

       location /nginx_static_files/

       {

               # access_log  /var/log/nginx/access_log_proxy;

               alias       /var/www/html/roundcube/;

               internal;

       }

|*endif|


       # deny access to apache .htaccess files

       location ~ /\.ht

       {

               deny all;

       }

}



Then rewrite the configuration;


echo "action=rewrite&value=httpd" >> /usr/local/directadmin/data/task.queue


/usr/local/directadmin/dataskq d


da build rewrite_confs


25) Force Webmail to use SSL


Check if config.inc.php is present in:

/var/www/html/roundcubemail-1.6.8/config/config.inc.php

You should find the folder of the "roundcube version" in /var/www/html/

If you get the file available, then copy the file, if already not exist in custombuild's "/custom/" folder, create the custom, then roundcube folders in /usr/local/directadmin/custombuild/

Set the folder's permission;
chmod 711 foldername
chown diradmin:diradmin foldername


Eg: cp /var/www/html/roundcubemail-1.6.8/config/config.inc.php /usr/local/directadmin/custombuild/custom/roundcube/config.inc.php

chmod 640 /usr/local/directadmin/custombuild/custom/roundcube/config.inc.php


Then add the force SSL option;


nano /usr/local/directadmin/custombuild/custom/roundcube/config.inc.php

$config['force_https'] = true;


If you want to add "Mark as Junk" button to Roundcube Message read panel, then enable the "markasjunk" plugin here;

// List of active plugins (in plugins/ directory)

$config['plugins'] = [

    'managesieve',

    'password',

    'archive',

    'zipdownload',

    'markasjunk',


];

Then run: da build roundcube


26) Webmail (Roundcube) Branding

You can set the branding options to the custom config, so that re-build or update will intact your branding ok;

nano /usr/local/directadmin/custombuild/custom/roundcube/config.inc.php

Insert the following to the bottom, if not already exist;

// provide an URL where a user can get support for your webmail system

$config['support_url'] = 'http://emailfeedback.mywebsite.com';


// Name your service. This is displayed on the login screen and in the window title

$config['product_name'] = 'My Website Webmail Portal';


// Put the logo images to /usr/local/directadmin/custombuild/custom/roundcube/skins/elastic/images/
// Put the logo images to /usr/local/directadmin/custombuild/custom/roundcube/skins/images/

// If the skins and images folder does not exist, create it first

// Logo image replacement. Specifies location of the image as:


$config['skin_logo'] = [

     // show the image /images/favicon.ico for the Login screen favicon in all skin

     "login[favicon]" => "/images/favicon.ico",

     // show the image /images/favicon.ico for the elastic screen favicon

     "elastic:*[favicon]" => "/images/favicon.ico",

     // show the image /images/favicon.ico for the larry screen favicon

     "larry:*[favicon]" => "/images/favicon.ico",

     // show the image /images/logo_login_small.png for the Login screen in all skin on small screens

     "login[small]" => "/images/logo_login_small.png",

     // show the image /images/logo_login.png on the login template in all skins

     "login" => "/images/logo_login.png",

     // add a link to the logo on the Login screen in all skin

     "login[link]" => "https://host.akijonline.com/webmail/",

     // show the image /images/logo.png on the elastic template

     "elastic:*" => "/images/logo.png",

     // show the image /images/logo.png on the larry template

     "larry:*" => "/images/logo.png",

     // show the image /images/logo_print.png for all print type logos in all skins

     "[print]" => "/images/logo_print.png",

   ];


// ----------------------------------

// USER INTERFACE

// ----------------------------------


// Behavior if a received message requests a message delivery notification (read receipt)

// 0 = ask the user,

// 1 = send automatically,

// 2 = ignore (never send or ask)

// 3 = send automatically if sender is in my contacts, otherwise ask the user

// 4 = send automatically if sender is in my contacts, otherwise ignore

// 5 = send automatically if sender is a trusted sender, otherwise ask the user

// 6 = send automatically if sender is a trusted sender, otherwise ignore

$config['mdn_requests'] = 2;


// These are requests for system state updates e.g. checking for new messages, etc.

// Setting it to 0 disables the feature.

$config['refresh_interval'] = 600;


// If true all folders will be checked for recent messages

$config['check_all_folders'] = true;


// default messages sort column. Use empty value for default server's sorting,

// or 'arrival', 'date', 'subject', 'from', 'to', 'fromto', 'size', 'cc'

$config['message_sort_col'] = 'arrival';


// default messages sort order

$config['message_sort_order'] = 'DESC';


// the default locale setting (leave empty for auto-detection)

// RFC1766 formatted language name like en_US, de_DE, de_CH, fr_FR, pt_BR

$config['language'] = 'en_US';


// use this timezone to display date/time

// valid timezone identifiers are listed here: php.net/manual/en/timezones.php

// 'auto' will use the browser's timezone settings

$config['timezone'] = 'Asia/Dhaka';


// use this format for date display (PHP DateTime format)

$config['date_format'] = 'd-m-Y';


// use this format for time display (PHP DateTime format)

$config['time_format'] = 'g:i a';


// Enables using standard browser windows (that can be handled as tabs)

// instead of popup windows

$config['standard_windows'] = true;


// Enables display of email address with name instead of a name (and address in title)

$config['message_show_email'] = true;


// prefer displaying HTML messages

$config['prefer_html'] = true;


// Display remote resources (inline images, styles) in HTML messages. Default: 0.

// 0 - Never, always ask

// 1 - Allow from my contacts (all writeable addressbooks + collected senders and recipients)

// 2 - Always allow

// 3 - Allow from trusted senders only

$config['show_images'] = 2;


// Display attached images below the message body

$config['inline_images'] = false;


// If true, after message/contact delete/move, the next message/contact will be displayed

$config['display_next'] = false;


// compose html formatted messages by default

//  0 - never,

//  1 - always,

//  2 - on reply to HTML message,

//  3 - on forward or reply to HTML message

//  4 - always, except when replying to plain text message

$config['htmleditor'] = 4;


// When replying:

// -1 - don't cite the original message

// 0  - place cursor below the original message

// 1  - place cursor above original message (top posting)

// 2  - place cursor above original message (top posting), but do not indent the quote

$config['reply_mode'] = 1;


Then re-build the Roundcube;

da build roundcube



27) Configure CloudLinux Plugin/menu


28) Set logged in user Dashboard view to Menu not Widget


Admin Login to DirectAdmin;

Admin Tools > Customize Evolution Skin > Layout > Dashboard Mode > Menu


29) Configure Layout Menu with adding a Favourites section on top


30) Set email address for System mails (root mail)

nano /etc/aliases

Uncomment the root contact line (#root:   marc) if the line available, and/or set as below;

root: hostname@yourbusinessdomain.com

Then, run the command newaliases

reboot




35) Disable Auto-SSL for hostname (if needed)

da config-set admin_ssl_check_retries 0
systemctl restart directadmin

Post a Comment