Customizing Apache

I wish to customize the main Apache configuration and not lose the changes

If you make customized changes to your /etc/httpd/conf/httpd.conf file, CustomBuild will overwrite these changes as soon as it rebuilds Apache.

There are 3 ways of making your customizations stick:

  1. The "official" way would be to use the CustomBuild custom directory method:
cd /usr/local/directadmin/custombuild
mkdir -p custom/ap2
cp -Rp configure/ap2/conf custom/ap2

and then edit your configs in the custom/ap2/conf/ directory as needed. The custom path overrides the default, and won't be overwritten. Your customized files will be used for the config rewrites, so you just need to remember to make your changes in the custom path.

If you make changes to the custom files, you can test what result you'll get by typing:

./build rewrite_confs
  1. If you only need to add extra Apache config code to the system, but don't need to remove any existing code, the best way is to add your changes to /etc/httpd/conf/extra/httpd-includes.conf as this file will not be touched by CustomBuild or DirectAdmin.

If the httpd-includes.conf doesn't exist, DA will 'touch' it so that it does exist.

  1. The easiest way would be to protect the httpd.conf with the immutable bit:
chattr +i /etc/httpd/conf/httpd.conf

Then CustomBuild won't touch it. You can repeat this command on any other files you need, e.g., /etc/httpd/conf/extra/httpd-alias.conf, etc.

You'd then use:

chattr -i /etc/httpd/conf/httpd.conf

to allow changes again when needed. Don't forget to lock it again with chatter +i /etc/httpd/conf/httpd.conf after you're done.

CUSTOM HTTPD TEMPLATES: Starting point

DirectAdmin offers a huge variety of ways to customize your User's VirtualHost entries.
This guide will help you pick which method to use depending on what you need it to do.
Should you know what you want to use, enter the info here:
Username:
Domain:
Subdomain:
Template Name: See #1 for options
Server Type: or: cust_nginx, cust_openlitespeed
Token Name: or: CUSTOM1, CUSTOM2, etc.

Outlined below are the major sections to consider when deciding which method to use:

  1. Raw Templates

These are located in /usr/local/directadmin/data/templates/. We typically discourage relying on custom versions of these in case we make important changes to them, in which case you wouldn't inherit these changes. In some cases, you will need to use a custom copy, but only if none of the options below work for you. The 4 templates typically in question would be:

    #Apache 2.x
    virtual_host2.conf
    virtual_host2_secure.conf
    virtual_host2_sub.conf
    virtual_host2_secure_sub.conf

    #Nginx
    nginx_server.conf
    nginx_server_secure.conf
    nginx_server_sub.conf
    nginx_server_secure_sub.conf

    #OpenLiteSpeed
    openlitespeed_vhost.conf #combined for all 4
  1. Per-Domain with the CUSTOM tokens via Custom Httpd Config

This Admin Level area lets you insert code into any CUSTOM or CUSTOM# token point for all VirtualHosts in that domain, including http and https for both domains and subdomains.

This method is used only when you want to change a setting just for this domain.

This GUI tool saves files to disk (depending on the token name), e.g.,

"/usr/local/directadmin/data/users/fred/domains/fred.com.cust_httpd"     #CUSTOM
"/usr/local/directadmin/data/users/fred/domains/fred.com.cust_httpd.1"   #CUSTOM1
... #CUSTOM2, etc.
  1. Tokens for Global, Per-User, Per-Domain

This tool is used to insert token variables where applicable. You're not saving a file for each CUSTOM token name, but you can create the mentioned file below to preload some tokens. This will allow you to set tokens before any other CUSTOM tokens are set (it's not for code itself, just for setting variables). Continue with this guide on how to set a token with the |?TOKENNAME=value| syntax. Token variables can be used within a value, e.g.,

|?TOKENNAME=value of 'OTHERTOKEN'|

These files are available to load in your custom tokens of various levels:

"/usr/local/directadmin/data/admin/global_httpd_tokens.conf" #global
"/usr/local/directadmin/data/users/fred/user.httpd_tokens" #per user
"/usr/local/directadmin/data/users/fred/domains/fred.com.httpd_tokens" #per domain
"/usr/local/directadmin/data/users/fred/domains/fred.com.sub.httpd_tokens" #per subdomain

Note that "httpd_tokens" is the name used, regardless of server type (httpd/nginx/litespeed/openlitespeed).

This is independent of the template name, so these tokens will be loaded into all of the 4 virtual_host2*.conf templates mentioned above.

  1. Global VirtualHost Pre/Post

These templates depend on the "Template Name" above, so preset that if you're trying to sort out which to use.

Using these files will write the given code into the User's httpd.conf either before or after, outside of the VirtualHost tag, for any use of the given template file.

Paths can be either:

"/usr/local/directadmin/data/templates/custom/virtual_host2.conf.pre"
"/usr/local/directadmin/data/templates/custom/virtual_host2.conf.post"

This might be handy if you want to insert a https://webmail.domain.com VirtualHost (e.g., you'd use the /usr/local/directadmin/data/templates/custom/virtual_host2_secure.conf.post, so it only gets added once per domain, and only for https).

  1. Global Token name per file, pre/post

Similar to the global CUSTOM tokens, this lets you control only which template it goes with. Your code will be inserted either before or after any use of the given CUSTOM* tokens. For example, if you use the pre variant, this code is inserted before say, per-domain CUSTOM inserted code. Possible files might be:

"/usr/local/directadmin/data/templates/custom/virtual_host2.conf.CUSTOM.pre"
"/usr/local/directadmin/data/templates/custom/virtual_host2.conf.CUSTOM.post"
  1. Global CUSTOM token, regardless of filename

This one is related to the global tokens, except you can use this for actual code as it's injected in a specific order. Applies to all template files. Possible files include:

"/usr/local/directadmin/data/templates/custom/cust_httpd.CUSTOM.pre"
"/usr/local/directadmin/data/templates/custom/cust_httpd.CUSTOM.post"
"/usr/local/directadmin/data/templates/custom/cust_httpd.CUSTOM.1.pre"
"/usr/local/directadmin/data/templates/custom/cust_httpd.CUSTOM.1.post"
... CUSTOM.2.pre ... etc.

Take note regarding how the numbered tokens have a dot between CUSTOM and the number.


Note: for almost all areas, you can use if-then-else syntax and set variables which carry forward within that template.

Custom HTTPD templates: read order

Knowing the order in which all of the templates are being loaded in can help you to determine when your tokens will be available.

For this guide, we'll refer to Apache/httpd. If you're running Nginx or OpenLiteSpeed, the guide still applies, but changes in the template names may also apply. More on the different names in this guide.

1. Loaded once before each VirtualHost is added:

    CUSTOM_DOMAIN_ITEM_*

2.

    WEBSERVER, DOMAIN, HAVE_SAFE_MODE, SSL_TEMPLATE, SPACE_HTTP2, IP, PROXY_IP, HAVE_NGINX_PROXY, PORT_8080, PORT_8081, PROXY_BUFFERING,
    LISTENERS, IF_MODULE_LITESPEED_OPEN, IF_MODULE_LITESPEED_OPEN, IF_MODULE_LITESPEED_CLOSE, IP1|2.., MULTI_IP, HOME, USERHOME, PACKAGE,
    REALUSER, ADMIN, CERT, KEY, HOSTNAME, SAFE_MODE, OPEN_BASEDIR, OPEN_BASEDIR_ENABLED, PHP_MAIL_LOG_ENABLED, CREATOR, BANDWIDTH, QUOTA,
    PORT_80, PORT_443, APACHELOGDIR

3.

    CB_VERSION, PHP1_RELEASE, PHP2_RELEASE, LSPHP1_RELEASE, LSPHP2_RELEASE, HAVE_PHP1_FPM, HAVE_PHP2_FPM, HAVE_PHP1_FCGI, HAVE_PHP2_FCGI,
    HAVE_PHP_FCGI, HAVE_RUID2, HAVE_MOD_SECURITY, HAVE_USERDIR_ACCESS, RUID2_AND_MOD_SECURITY,
    (MODSEC_AUDIT_DIR, NGINX_MOD_SECURITY_ENABLE)|NGINX_MOD_SECURITY_ENABLE, USE_HOSTNAME_FOR_ALIAS, HAVE_SUEXEC_PER_DIR, SUSPENDED_REASON,
    CLI, HAVE_PHP1_CLI, HAVE_PHP2_CLI, SUPHP, HAVE_PHP1_SUPHP, HAVE_PHP2_SUPHP, USECANONICALNAME, CAROOT

4.

    HANDLERS, MIMETYPES, USER, GROUP, SECURE_ACCESS_GROUP, (OLS)SSLPROTOCOL, SDOCROOT, SUSPENDED, CGI, PHP, SUB, FORCE_SSL_REDIRECT

5. Tokens TOK=value, not templates:

    /usr/local/directadmin/data/admin/global_httpd_tokens.conf
    /usr/local/directadmin/data/users/fred/user.httpd_tokens
    /usr/local/directadmin/data/users/fred/domains/domain.com.httpd_tokens
    /usr/local/directadmin/data/users/fred/domains/domain.com.sub.httpd_tokens

6. VirtualHost pre, where virtual_host2.conf would be whichever template file is used for this VH. Fully tokenized template.

    /usr/local/directadmin/data/templates/custom/virtual_host2.conf.pre

7.

    /usr/local/directadmin/data/templates/cust_httpd.CUSTOM.pre
    /usr/local/directadmin/data/templates/custom/virtual_host2.conf.CUSTOM.pre
    /usr/local/directadmin/data/users/fred/domains/domain.com.cust_httpd
    /usr/local/directadmin/data/templates/custom/virtual_host2.conf.CUSTOM.post
    /usr/local/directadmin/data/templates/cust_httpd.CUSTOM.post
added to CUSTOM.

8. For each custom token, 1 through 8 (we'll use 1 for the example):

    /usr/local/directadmin/data/templates/custom/virtual_host2.conf.CUSTOM.1.pre
    /usr/local/directadmin/data/templates/custom/cust_httpd.CUSTOM.1.pre
    /usr/local/directadmin/data/users/fred/domains/domain.com.cust_httpd.CUSTOM.1
    /usr/local/directadmin/data/templates/custom/cust_httpd.CUSTOM.1.post
    /usr/local/directadmin/data/templates/custom/virtual_host2.conf.CUSTOM.1.post
added to CUSTOM1

9.

    PROTECTED_DIRECTORIES, CONTEXTS, REALMS, NGINX_REDIRECTS, OPENLITESPEED_REDIRECTS, HOTLINK_PROTECTION, EXTRA_LOCATIONS, LOCATION_INSERT, NGINX_PHP_CONF

10. If exists:

/usr/local/directadmin/data/templates/custom/virtual_host2.conf

else:

/usr/local/directadmin/data/templates/virtual_host2.conf

Using a token that does not exist yet

Since the above order does matter, if you're using a token which has not yet been fixed, (as of DirectAdmin 1.61.0) a change has been done such that any unknown TOKEN will be swapped with |TOKEN|open in new window, which will be inserted into its final token location inside the template file by the tokenizer. So at that point, it should be known and properly filled, instead of being left as TOKEN in the template.

Using a custom VirtualHost template

If you wish to change the setup of the VirtualHosts for all domains, you can do so by creating your own custom templates.

cd /usr/local/directadmin/data/templates
cp virtual_host2*.conf custom
cd custom

Once you've copied the 4 VirtualHost files (or just the ones you want) to the custom directory, you can then edit the new files you've just copied. DirectAdmin will always check for the custom file before going to the default ones. Failure to copy the virtual_host2*.conf files to the custom directory before modifying them will result in a loss of all changes when DirectAdmin updates itself (because the files are overwritten). Note that there are actually 8 virtual_host files, but you only need to worry about the 4 that apply to you. The files with the 2 in them are for Apache 2.x.

Inside the virtual_host*.conf files, you'll find code that is similar to httpd.conf code, but contains what are known as tokens. These tokens are what will be replaced with specific user data for each domain created.

TOKENNAMEDESCRIPTION
DOMAINthe name of the domain. e.g., domain.com
IPthe IP address associated with that domain. eg: 12.34.56.78
HOMEThe users home directory. e.g., /home/gary
ADMINThe email address of the server admin. webmaster@domain.com
HOSTNAMEThe hostname of the server. e.g., server.domain.com
SAFE_MODEON or OFF, if PHP safe_mode is enabled or not
PHPON or OFF, if PHP is enabled or not
CGIThe whole httpd.conf line used to add the Script-Alias
HANDLERShttpd.conf code holding all Apache handlers
MIMETYPEhttpd.conf code holding all Apache Mime Types
USERthe username
GROUPthe user's group name (99% of the time, it's the same as the USER)
DOCROOTThe DocumentRoot of the VirtualHost. This is the path that Apache will use to access the data when the ServerName (domain.com) is requested
SUBthe subdomain name (for the virtual_host_*sub.conf file) e.g., sub
CUSTOMcustom httpd.conf code to be inserted if the domain.com.cust_httpd file exists. (See Adding custom httpd.conf code the VirtualHost of one domain)
CAROOTThe whole httpd.conf line used to load in the SSLCACertificateFile directive
CERTThe path of the certificate to be used for the domain
CREATORThe username of the account that created the User account who owns this domain
KEYThe path of the certificate to be used for the domain

The top of the templates should contain |?CGI=...| and |?DOCROOT=...|. These lines are where the data for the CGI and DOCROOT tokens are set. If CGI is not enabled, this line will be ignored and the CGI token will be empty. If the domain is suspended, the DOCROOT will be filled with the path of the suspended page. The CAROOT token will be empty unless the User has added a valid CARootCertificate through DA.

You can use tokens when assigning a value to CGI or DOCROOT, just use 'TOKEN' instead of |TOKEN|.

Once you are happy with your new virtual_host*.conf files, they'll need to be used in the real httpd.conf files. You can trigger DirectAdmin to rewrite all User httpd.conf files by running:

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

The command will be added the the task queue, which is checked once per minute, so it may be a few minutes before all httpd.conf files have been rewritten. *Note: the main /etc/httpd/conf/httpd.conf file is overwritten whenever CustomBuild rebuilds Apache, so any custom changes you make in this file will be not retained. Depending on the changes you intend to make, you may consider using the file /etc/httpd/conf/extra/httpd-includes.conf, as it is not overwritten during a rebuild.

Note that you can also use if-then-else statementsopen in new window if you don't want all settings to be global. Example, say you want a custom item added, only for 1 domain:

|*if DOMAIN="domain.com"|
#custom item for just this domain
|*endif|

See the if-then-else linkopen in new window for more info on what else you can do with this basic scripting tool.

You can also run actual scripts with database queries, etc., (that is, if you wanted using the scripting portion of the templates).
More info on that here: http://www.directadmin.com/features.php?id=756open in new window

Adding custom httpd.conf code to the VirtualHost

DirectAdmin allows the Admin to insert extra httpd.conf code that a User may require. To access the control page for this functionality, go to Admin Panel -> Admin Settings -> Customize Httpd Configurations.

Once you see the list of domains, click the domain you wish to insert the extra httpd.conf code for.

At the bottom of the page, you'll see the current httpd.conf for that User. It will contain all VirtualHosts for all domains, subdomains and redirects. Any changes made by this page will only affect the VirtualHosts for the domain in question, not the other domains owned by that user. If all domains need the changes, then you would repeat this process for each domain.

The top textarea is where you will paste the custom httpd.conf code you wish to insert. The code you write will be inserted into the |CUSTOM| token for all VirtualHosts for this domain. You can edit the templates as needed if you require to move the |CUSTOM| token to a different position in the VirtualHost.

All tokens that are available for the VirtualHost will be available with this feature. You can also set any token you wish. For example, if you with to change the DocumentRoot for a domain, you can paste:

|?DOCROOT=/new/path/you/want|

Note that this new DocumentRoot will be used for all DocumentRoots for this domain, including https connections and subdomains, so it may not be a desired effect.

Another common use is to add another ServerAlias. This allows another domain to be used to access the exact same content. To accomplish this, you would write:

ServerAlias newdomain.com www.newdomain.com

to get newdomain.com and www.newdomain.com to point to the original domain for the VirtualHost. You will also have to make sure that newdomain.com and www.newdomain.com both resolve to the same IP as stored in |IP|.


Note, the above example will set the DOCROOT token into all 4 templates, so this will also apply to all subdomains, which may not be desired.

To only make the DOCROOT apply to the domain, and not to the subdomain, add an if, e.g.,

|*if !SUB|
|?DOCROOT=/new/path/you/want|
|*endif|

How to use different ciphers with Apache

With the ever evolving needs for security, good encryption cipher lists can change regularly. Also, the needs of those connecting to a given server may be different from box to box, e.g.,

  • Some servers require the maximum standards of security.
  • Some clients have old browsers which cannot use modern ciphers.
  • Some API scripts cannot use modern ciphers.

Etc., so each case might be different.

To use different ciphers with Apache 2.x and CustomBuild, you can use the "custom" folder method to manage your own cipher lists and SSL rules.

If you wanted a more secure list of ciphers, you could run the following:

cd /usr/local/directadmin/custombuild
mkdir -p custom/ap2/conf/extra
cp configure/ap2/conf/extra/httpd-ssl.conf custom/ap2/conf/extra/httpd-ssl.conf

which then lets you edit /usr/local/directadmin/custombuild/custom/ap2/conf/extra/httpd-ssl.conf for changes such as:

SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1

SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK

SSLHonorCipherOrder On

SSLCompression off

Note: the SSLCipherSuite list is all one long line. Also note that the recommended ciphers and protocols update very often, so you'll want to make sure to check set these accordingly.

This tool is very useful to get a good list for your scenario: Mozilla's SSL Config Generatoropen in new window

Once you've created the custom httpd-ssl.conf as desired, you can then install it with:

cd /usr/local/directadmin/custombuild
./build rewrite_confs

To disable TLSv1.1 and only allow TLSv1.2 and TLSv1.3 on OpenLiteSpeed:

echo '|?SSLPROTOCOL=24|' >> /usr/local/directadmin/data/templates/custom/openlitespeed_vhost.conf.CUSTOM.pre
/usr/local/directadmin/custombuild/build rewrite_confs

There is another way to set up ciphers per Apache/Nginx/OpenLiteSpeed/LiteSpeed/ProFTPD/Pure-FTPd. One may choose to just use the ssl_configuration option in CustomBuild. The settings reflect the Modern, Intermediate, or Old configuration per https://ssl-config.mozilla.org/open in new window. By default, this is set to Intermediate.

To switch to Old, for example:

cd /usr/local/directadmin/custombuild/
./build set ssl_configuration old
./build rewrite_confs

Be informed that 'Modern' means to support TLS 1.3 only while CentOS7 / Debian 8 does not have it. Old OS's support TLSv1.3 by default in LiteSpeed/OpenLiteSpeed only.

Adding custom modules to Apache for CustomBuild

If you want to add any extra modules to Apache in CustomBuild, they'll need to be compiled in. Any module that needs to be compiled in will have a --with- type flag which will need to be used. The To add this flag, run the following:

cd /usr/local/directadmin/custombuild
mkdir -p custom/ap2
cp configure/ap2/configure.apache custom/ap2/configure.apache
vi custom/ap2/configure.apache

Add your --with-module line to the end of the file, and make sure the \ character exists at the end of all lines except the last one. Then build Apache:

./build clean
./build apache

Then restart Apache:

systemctl restart httpd

If you run into problems, you may also need to recompile PHP as well:

./build php

Then restart Apache again.

How to modify the open_basedir setting for one domain

To change the open_basedir value when using PHP in CLI mode (not suPHP), you can do so by going to:

Admin Level -> Custom httpd configuration -> domain.com

In the top textarea, insert this one line:

|?OPEN_BASEDIR_PATH=`HOME`/:/tmp:/var/tmp/:/usr/local/lib/php/|

which is the default value in the templates. Edit the paths in that line to meet your needs.

If you're running CustomBuild 2.0, you may also need to add the path:

/usr/local/php73/lib/php/

to the above list. Adjust php73 accordingly for the PHP version you're using.

How to change the DocumentRoot of only one of your subdomains

A GUI now exists in DirectAdmin for editing a subdomain's DocumentRoot.

As of DirectAdmin 1.59.5, support for a subdomain document root override file has been addedopen in new window.

You can use this override file to set a given DocumentRoot for any subdomain (per-https/https control).

For DirectAdmin versions prior to Version 1.61.0 (before the GUI was added), the Admin GUI can be used with the new SDOCROOT tokens (requires 1.59.5+) for any webserver type, without the need for custom templates.

Let's assume you want to change the DocumentRoot for .domain.com :

  1. Admin Level -> Custom Httpd Config -> domain.com

  2. In the |CUSTOM| token, you can specify any path you'd like to the SDOCROOT token. If you want it relative to the current domain.com/public_html, you'd use:

|*if SUB="subname"|
|?SDOCROOT=`DOCROOT`/othersub|
|*endif|

which would place it in /home/user/domains/domain.com/public_html/othersub.

  1. Or if you wish it to be something fully out of the public_html/private_html, you could set it like:
|*if SUB="subname"|
|?SDOCROOT=`HOME`/domains/`DOMAIN`/subdomains/`SUB`|
|*endif|

which would place it in /home/user/domains/domain.com/subdomains/sub.

The full list of available tokens can be viewed from the "Available Tokens" button in the Custom Httpd Config, when viewing the domain.

Wildcard *.domain.com

If you'd like to set up your domain to accept anything.domain.com, you can do so with the following instructions (requires Admin access).
See the last method below if you want other subdomains to work with their own data, or if you want the main domain to show different data.

  1. Set up the DNS with a wildcard A record. Go to Dns Control, and add an "A" record:
*  ->  1.2.3.4

where 1.2.3.4 is the IP of your domain.

This will allow anything.domain.com to resolve to your server. Apache does not yet know how to direct those wildcard subdomains, though.

  1. To set up Apache, go to Admin Level -> Custom Httpd configurations -> domain.com, and in the top textarea, add this one line:
ServerAlias *.|DOMAIN|

then click "Save".

That should be it. Wait a few minutes for everything (Apache, Named) to be restarted and then test it out.

The wildcard subdomains will point to your main public_html directory for the domain.

If you want to change this, it's probably best not to do step 2, and to instead set up your own custom VirtualHost manually in the /etc/httpd/conf/extra/httpd-includes.conf file (DA wont delete/overwrite it there) with the same ServerAlias directive as in step 2.

Other similar uses might be subdomain aliasing, where test.domain.com is the same as test.domain2.com.
You can accomplish this by following step 1) above, and then inserting the following instead during step 2) above:

|*if SUB|
    ServerAlias |SUB|.domain2.com
|*endif|

which will make any existing subdomain from domain2.com point to domain.com.


I still want all other subdomains to continue to work with their different data

You may notice that when using the DomainAlias option on your main domain, that other subdomains also get handled by the wildcard. If you want to have a wildcard value, but still have created subdomains go elsewhere, then you'll need to do the following instead. The premise is to make the wildcard VirtualHost show up dead last in the httpd.conf, after the other subdomain VirtualHosts are added.

  1. Create the DNS records in the same way as step 1) above.

  2. Create a subdomain normally in DA, such that it's going to appear dead last in the subdomain list.

It's ASCII alphabetical, so, a value of zzzz may be reliably at the end of the list (unless you have special international characters like ÿ, so you'll want to use those instead as they've got a higher ASCII value). We'll assume you went with zzzz.domain.com as the created subdomain.

This will store your data in the usual place:

/home/user/domains/domain.com/public_html/zzzz

so that's where you're going to store your wildcard data. All wildcard URLs will go to that DocumentRoot. If you want that to point to the main domain's public_html, either delete the zzzz directory, and replace it with a symbolic link to "..", or change the DOCROOT to the public_html in the templates (symbolic links are easiest).

  1. Now to make all wildcards go to the zzzz subdomain, go to Admin Level -> Custom Httpd Configuration -> domain.com, and in the top textarea, paste in this code:
|*if SUB="zzzz"|
    ServerAlias *.|DOMAIN|
|*endif|

Which, when saved, should add the ServerAlias code to only the zzzz subdomain VirtualHost, which should be at the very bottom of the User httpd.conf file.

Setting up webmail.domain.com as default

  1. We'll need to add a webmail.* VirtualHost to each domain. We can make use of a feature that lets us globally specify CUSTOM# tokens without altering the original templates. Create the file /usr/local/directadmin/data/templates/custom/virtual_host2.conf.CUSTOM.4.post and add the code:
</VirtualHost>
<VirtualHost |IP|:|PORT_80| |MULTI_IP|>
   ServerName 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>

taking note that we start the code with the closing </VirtualHost> because the CUSTOM4 token is before the trailing </VirtualHost> in the virtual_host2.conf template.

The above is for port http:80, but similar code can be used in /usr/local/directadmin/data/templates/custom/virtual_host2_secure.conf.CUSTOM.4.post if you want it for https on the domain, in which case, you'd add:

</VirtualHost>
<VirtualHost |IP|:|PORT_443| |MULTI_IP|>
   ServerName 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>
  1. Then run:
echo "action=rewrite&value=httpd" >> /usr/local/directadmin/data/task.queue
/usr/local/directadmin/dataskq d

to rewrite the httpd.conf files.

  1. You'll also need to set up the DNS portion.
cd /usr/local/directadmin/data/templates
cp dns_a.conf custom
cd custom
perl -pi -e "s/^smtp=\\|IP\\|\n/smtp=\\|IP\\|\nwebmail=\\|IP\\|\n/" dns_a.conf

This will set up the webmail A record for new DNS zones. For existing DNS zones, you'll have to manually add the webmail A record to point to the domain's IP.

How to disable the ~username method of viewing a website

CustomBuild 2.0 now has the following option by default:

cd /usr/local/directadmin/custombuild
./build set userdir_access no
./build rewrite_confs

So, if you need to access a domain before it resolves, add your domain and IP to your computer's "hosts" file to override the true DNS.

How to set up per-domain Aliases

If you want to disable /webmail for just one domain (for example), one way to do that is to change the Aliases to be within the VirtualHosts instead of 1 global Alias. To do that, we'll need to use the virtual_host2.conf template (for Apache 2) and use the custom httpd config settings found in the Admin Level. This guide assumes you're using Apache 2 with CustomBuild.

  1. Set up the custom template so it's safe from DirectAdmin updates:
cd /usr/local/directadmin/data/templates/custom
cp ../virtual_host2.conf .
  1. Edit the copied virtual_host2.conf file, and insert the following at the top of the file:
|?WEBMAIL=ON|

Then just below the token that says |CUSTOM| (in the same file) add:

|*if WEBMAIL="ON"|
Alias /webmail /var/www/html/webmail/
|*endif|
  1. Go to Admin Level -> Custom httpd config -> domain.com and in the textarea at the top, insert this one line:
|?WEBMAIL=OFF|

which will shut off webmail for just that one domain.

  1. Remove the global Alias from the /etc/httpd/conf/extra/httpd-aliases.conf file.

  2. Issue a httpd.conf rewrite, then restart Apache.

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

Prevent Apache logging of certain requests

If you have a common request that might be filling up your logs or you simply don't wish to see it (knowing it may skew your web stats), then you can tell Apache not to log it via the following changes:

  1. Create /etc/httpd/conf/extra/dontlog.conf and add the code:
CustomLog /var/log/httpd/domains/directadmin.com.log combined env=!dontlog
  1. In your /etc/httpd/conf/extra/httpd-includes.conf, add this code:
Include /etc/httpd/conf/extra/dontlog.conf
  1. Lastly, for any site where you wish to disable the request of a given file, let's call it /commonfile.txt. You could go to Admin Level -> Custom Httpd Config -> domain.com and in the top CUSTOM textarea, add:
SetEnvIf Request_URI "^/commonfile.txt" dontlog
|?COMBINED_LOG=combined env=!dontlog|

This uses the following DirectAdmin feature:
[http://www.directadmin.com/features.php?id=1712]

I wish to keep domain logs in a separate location for long-term safe-keeping

After several iterations of log ownership in ~/domains/domain.com/logs, the current state (as of August 2019) stores the logs as the User.

Users do have sufficient privileges to accidentally delete their logs.

Managing root-owned data under a User's home directory is very difficult to do securely, so keeping your long-term root logs in a non-User-writable area is recommended.

We can use the rotate_log_post.sh, which runs just after /var/log/httpd/domains/* logs are copied to ~/domains/domain.com/logs (and compressed to the tar.gz). This is where we'd grab our copy.

  1. Create the script /usr/local/directadmin/scripts/custom/rotate_log_post/root_logs.sh

Note the new hook script path format.

  1. In it, place the following code to sort out what to copy, where to copy it, and clean up old logs:
#!/bin/sh
DAYS_TO_KEEP=365

DOMAIN=`basename $file`
LONG_TERM=/var/log/httpd/long_term
DOMAIN_DIR=${LONG_TERM}/$DOMAIN
DATE=`date +%F`
DEST=${DOMAIN_DIR}/${DATE}
if [ ! -d ${DEST} ]; then
       mkdir -p ${DEST}
fi
/bin/cp -n ${access_log} ${DEST}
if [ "${error_log}" != "" ]; then
       /bin/cp -n ${error_log} ${DEST}
fi
find ${LONG_TERM}/* -mtime +${DAYS_TO_KEEP} -type d -exec rm -rf "{}" \;
exit 0;
  1. Set the executable permissions on the script:
chmod 755 /usr/local/directadmin/scripts/custom/rotate_log_post/root_logs.sh

Once the next tally runs, this should automatically fill up the root-logs area.

How to change the PHP email in the Apache VirtualHosts

You might see this value in your User's httpd.conf file:

php_admin_value sendmail_path '/usr/sbin/sendmail -t -i -f user@domain.com'

where user is the account owner for domain.com.

If you'd like to change this value, go to Admin Level -> Custom Httpd Configuration -> domain.com and in the top textarea, paste this code:

|?PHP_EMAIL=new@email.com|

to whichever email value you'd like, and this will be used in the VirtualHost configs for that domain.


For PHP-FPM (Nginx, and some Apache setups), the Custom Httpd Config page does not currently fill the required CUSTOM1 tokens for the User's php-fpm.conf file, thus the EMAIL token cannot currently be easily overwritten. If you do need to change the EMAIL token for a php-fpm.conf file, create a custom copy of the php-fpm.conf template, and change the EMAIL token to have if-then-else statements, so that it only affects one domain, e.g.,

|*if DOMAIN="domain.com"|
|?EMAIL=new@email.com|
|*else|
|?EMAIL=`USER`@`DOMAIN`|
|*endif|

Enabling PUT and DELETE methods in Apache/Nginx

CustomBuild 2.0 has the ability to add the extra methods by overwriting the default list.

To add , run the following:

cd /usr/local/directadmin/custombuild
./build set http_methods "GET:HEAD:POST:PUT:DELETE"
./build rewrite_confs

You can adjust the full list however you need.

To enable all possible HTTP methods, just use:

cd /usr/local/directadmin/custombuild
./build set http_methods ALL
./build rewrite_confs

How to customize the User httpd.conf based on a custom package item

With the addition of custom package itemsopen in new window, you can now use these items to control other areas of your system. For this example, we'll have these items control the content of a User httpd.conf file.

  1. The first step is to add a custom package item. See this guideopen in new window on how to do that. For this example, use a checkbox. Give the variable a name called myval.

  2. Next, we need to have this option do something. By default, the item is only stored in the user.conf file. It won't do anything yet.

To have it do something, create the script /usr/local/directadmin/scripts/custom/user_create_post.sh. Inside that file, add this code:

#!/bin/sh
if [ "$myval" = "yes" ]; then
     echo "Custom Apache code" >> /usr/local/directadmin/data/users/$username/domains/$domain.cust_httpd
     echo "action=rewrite&value=httpd&user=$username" >> /usr/local/directadmin/data/task.queue
fi
exit 0;

Which will insert the "Custom Apache code" into the |CUSTOM| token in the virtual_host2*.conf template files.

The templates offer even more degrees of flexibility with the use of if-then-else statements and variables. For example, if you edit the global templates to have some code, but you only want the code available for some Users or domains, you can use if-then-else along with variables. For this example, if the variable MYVAL=yes is set, then we'll insert code into the httpd.conf, e.g., in the virtual_host2*.conf files, after the |CUSTOM| token:

|*if MYVAL="yes"|
Custom Apache code
|*endif|

Then, in step 2) above, instead of adding using this:

echo "Custom Apache code" >> /usr/local/directadmin/data/users/$username/domains/$domain.cust_httpd

you'd use this instead:

echo "|?MYVAL=yes|" >> /usr/local/directadmin/data/users/$username/domains/$domain.cust_httpd

which gets inserted into the |CUSTOM| token, thus setting the variable so that once your if-then-else statement happens, the value=yes, and you're good to go.

You can then turn the domain on or off from Admin Level -> Custom httpd config -> domain by adding or removing the |MYVAL=yes| code from the text area.

This can also still be managed via the packages, but you'd also need to create the user_modify_post.sh script to add or remove the domain.com.cust_httpd file, based on what value is set.

Ability to set global custom apache tokens

The existing virtual_host2*.conf templates allow you to do pretty much anything you need, but there are cases where you might only want to add or change one small variable without creating an entirely new set of templates.

This feature allows you to insert your own global tokens into a config file:
/usr/local/directadmin/data/admin/global_httpd_tokens.conf
set with the internal directadmin.conf default:

global_httpd_tokens=/usr/local/directadmin/data/admin/global_httpd_tokens.conf

one token per line, with a = character, followed by the value you want to set.

There will also be similar files for users, domains and subdomains, if you create them with load order:
/usr/local/directadmin/data/users/username/user.httpd_tokens
/usr/local/directadmin/data/users/username/domains/domain.com.httpd_tokens
/usr/local/directadmin/data/users/username/domains/domain.com.subdomain.httpd_tokens

They will be loaded after the DA-based tokens are set, but before the CUSTOM tokens, so that they're available in the domain.com.cust_httpd files. If you want to set a CUSTOM token, do that in the domain.com.cust_httpd.

This type of setup can be handy in the event that you may include a set of templates for many servers, and need to update those templates from time to time, but you might want to have different tokens in each server, used by those templates (or per-domain customizations).

How to activate web cache. Cache-Control HTTP headers

HTTP 1.1 introduced a new class of headers, Cache-Control response, to give webmasters more control over their content. The Cache-Control takes precedence on Expires if both are present.

Useful Cache-Control response headers include:

  • max-age=[seconds] — specifies the maximum amount of time that a representation will be considered fresh. Similar to Expires, this directive is relative to the time of the request, rather than absolute. [seconds] is the number of seconds from the time of the request you wish the representation to be fresh for.
  • s-maxage=[seconds] — similar to max-age, except that it only applies to shared (e.g., proxy) caches.
  • public — marks authenticated responses as cacheable; normally, if HTTP authentication is required, responses are automatically private.
  • private — allows caches that are specific to one user (e.g., in a browser) to store the response; shared caches (e.g., in a proxy) may not.
  • no-cache — forces caches to submit the request to the origin server for validation before releasing a cached copy, every time. This is useful to assure that authentication is respected (in combination with public), or to maintain rigid freshness, without sacrificing all of the benefits of caching.
  • no-store — instructs caches not to keep a copy of the representation under any conditions.
  • must-revalidate — tells caches that they must obey any freshness information you give them about a representation. HTTP allows caches to serve stale representations under special conditions; by specifying this header, you’re telling the cache that you want it to strictly follow your rules.
  • proxy-revalidate — similar to must-revalidate, except that it only applies to proxy caches.

For example:

Cache-Control: max-age=3600, must-revalidate

Validators

The most common validator is the time that the document was last changed, as communicated in the Last-Modified header (which is used to ask the server if the representation has changed since that time).

Another kind of validator is called the ETag, which is a unique identifier generated by the server and changed when the representation does.

Activating per domain

The best option for caches with Apache is to use .htaccess files per each domain. An example (use in .htaccess) to cache static files would be as follows:

<IfModule mod_headers.c>
    <IfModule mod_expires.c>

        ExpiresActive On
        ExpiresByType application/vnd.ms-fontobject "access plus 1 week"
        ExpiresByType application/x-font-ttf "access plus 1 week"
        ExpiresByType application/x-font-opentype "access plus 1 week"
        ExpiresByType application/x-font-woff "access plus 1 week"
        ExpiresByType image/svg+xml "access plus 1 week"

        <FilesMatch "\.(json|pdf|swf|bmp|gif|jpeg|jpg|png|svg|tiff|ico|flv|js|css)$$">
            ExpiresDefault "access plus 1 week"
            Header append Cache-Control "public"
        </FilesMatch>
    </IfModule>
</IfModule>

And resulting output checked with curl:

$ curl -I  http://example.com/favicon.ico
HTTP/1.1 200 OK
Date: Tue, 22 Jun 2020 17:59:12 GMT
Content-Type: image/x-icon
Last-Modified: Sat, 15 Oct 2016 17:20:51 GMT
ETag: "3aee-53eea907e02c0"
Accept-Ranges: bytes
Cache-Control: max-age=604800, public
Expires: Tue, 29 Jun 2020 17:59:12 GMT
Vary: Accept-Encoding,User-Agent

Activating for all domains

To activate globally for all domains, create the directory:

mkdir -p /usr/local/directadmin/data/templates/custom/
cd /usr/local/directadmin/data/templates/custom/

And then create a file called virtual_host2.conf.CUSTOM.post, insert the same code provided above for the .htaccess file, and lastly, rewrite configs:

cd /usr/local/directadmin/custombuild
./build rewrite_confs

How to install mod_pagespeed

Mod_pagespeed is an open-source Apache HTTP Server (or Nginx) module, which automatically applies chosen filters to pages and associated assets such as stylesheets, JavaScript, and HTML files, as well as to images and website cache requirements.

A major advantage of this module is that it does not require modifications to existing content or workflow, meaning that all internal optimizations and changes to files are made on the server side, presenting modified files directly to the user. Each of 40+ filters correspond to one of Google's web performance best practices rules.

Installation is relatively easy but as DirectAdmin does not use RPM for Apache, and mod_pagespeed provides 'source installation' packages only for Nginx, it could create some difficulties.

Tested with Apache on CentOS 7:

mkdir -p /root/mod_pagespeed
cd /root/mod_pagespeed
wget -O mod-pagespeed-stable_current_x86_64.rpm https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_x86_64.rpm
yum install cpio
rpm2cpio mod-pagespeed-stable_current_x86_64.rpm| cpio -idmv

Now just move the files to the appropriate places:

mv -f ./etc/httpd/conf.d/pagespeed.conf /etc/httpd/conf/extra/pagespeed.conf
mv -f ./etc/httpd/conf.d/pagespeed_libraries.conf /etc/httpd/conf/extra/pagespeed_libraries.conf
mv -f ./usr/bin/pagespeed_js_minify /usr/bin/pagespeed_js_minify
mv -f ./usr/lib64/httpd/modules/mod_pagespeed_ap24.so /usr/lib/apache/mod_pagespeed_ap24.so
mkdir -p /var/cache/mod_pagespeed
mkdir -p /var/log/pagespeed

Replace the /usr/lib64/httpd/modules/ path with /usr/lib/apache/ in /etc/httpd/conf/extra/pagespeed.conf:

perl -pi -e 's|/usr/lib64/httpd/modules/|/usr/lib/apache/|g' /etc/httpd/conf/extra/pagespeed.conf

Edit the /etc/httpd/conf/extra/httpd-includes.conf file and add following two includes:

Include /etc/httpd/conf/extra/pagespeed.conf
Include /etc/httpd/conf/extra/pagespeed_libraries.conf

And restart Apache:

service httpd restart

When completed, mod_pagespeed will be enabled globally for all domains. Test it with curl like so:

curl -Is domain.com | grep X-Mod-Pagespeed

It should show the output similar to the following:

X-Mod-Pagespeed: 1.13.35.2-0

How to enable brotli compression

Apache 2.4.26 and newer supports Brotli by default.

  1. Enable it by installing Brotli headers. Use one of the following depending on your OS.
apt install libbrotli-dev   (for Debian based systems)
yum install brotli-devel    (for Red Hat based systems)
  1. Compile apache using the --with-brotli flag. Run the commands below to add custom configuration:
cd /usr/local/directadmin/custombuild
mkdir -p custom/ap2
cp configure/ap2/configure.apache custom/ap2/configure.apache

Add "--with-brotli" to the end of custom/ap2/configure.apache. Make sure the \ character exists at the end of all lines except the last one.

  1. rebuild apache
./build apache

If compiled successfully, httpd -M | grep brotli should output:

brotli_module (static)
  1. Activate it for your domains by adding the following:
<IfModule mod_brotli.c>
    AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml text/css text/javascript application/javascript
</IfModule>

to /etc/httpd/conf/extra/httpd-includes.conf

  1. Rewrite configs:
./build rewrite_confs

Test the configuration's validity by curling one of your domains (exampledomain.com in this example).

curl -kL -I -H 'Accept-Encoding: br' http://exampledomain.com 2>&1 | grep -i encoding

If successful, the following output should be returned.

content-encoding: br
Last Updated: