Skip to main content

Running Craft CMS on a DirectAdmin server

Craft CMS can be hosted anywhere and I didn't find much information around hosting using DirectAdmin, here's my findings and tips.

Published

Craft CMS is a great Content Management System that can run virtually anywhere, being PHP based its requirements are typically quite modest. Having something like DirectAdmin allows you to manage certain aspects of website hosting/administration through a user-friendly interface without having to deal with SSH or configuration yourself. I happen to be comfortable with both, so I wanted to provide some specific information for DirectAdmin based usage.

Git manager

The Git manager feature in DirectAdmin is really great and simplifies your code deployment strategy. While DirectAdmin provides FTP access, this is a quite an old method of managing website updates and shouldn't be used. FTP is insecure and while FTPS and SFTP exists to add encryption to FTP, Git is a much better way of keeping track of changes. The DirectAdmin Git manager allows for local or remote Git repository synchronisation, meaning you can have a remote Git repository hosted on somewhere like GitHub and still use this feature.

For remote Git repositories hosted elsewhere you will need to setup SSH keys for your server to able to read and sync the contents of a remote repository i.e. GitHub. You would add the SSH public key from your server as a deploy key to your GitHub repository. This should typically be a read-only key, as you shouldn't need any write access to fetch and sync the repository data. This key file should not have any password, because of the non-interactive usage required.

When creating a Git repository through DirectAdmin, you'll be asked for:

  • Name - Repository name should be ideally all lowercase with hyphens or underscores, no spaces
  • Remote - If using a remote repository as the source you should put the remote e.g. [email protected]:jamesmacwhite/www.jmwhite.co.uk.git
  • Key file - Again if using a remote, you'll need to provide the path to the private key that will have access to the remote repository e.g. .ssh/id_rsa or .ssh/id_ed2xxxx

Once created, you'll then want to modify settings and set the deploy directory to a path you will be deploying your Craft CMS project to. Paths in the Git manager are all relative to the home directory of the user, so in my case /home/jmwhite.

  • Deploy Branch - Can be any branch but usually "main" or "master" for your live/production environment.
  • Deploy Directory - domains/DOMAIN/public_html.

Note: We are going to need to modify the document root path later to use the /web folder for Craft CMS.

Test a fetch to confirm everything is working with key file authentication, you should see the Git commits that are present.

To automate the fetch and deploy process, each Git manager repository has a webbook URL. By sending a POST request to this URL, this automatically triggers a fetch and deploy, which means you can add this into a script, GitHub action or any CI as part of the deployment process, this feature also means you do not have to copy the contents of your Git repository in your build process as it is deployed for you through Git manager.

PHP version and memory limit

DirectAdmin supports multiple PHP versions running at the same time, for Craft CMS 5, PHP version 8.2 or above is needed. Ensure your domain is set to the right PHP version, you can set the required PHP version from within Account Manager > Domain Setup > PHP Version selector

The PHP memory limit may be set to 128 MB by default which is below the recommended for Craft CMS. 256 MB is the minimum; 512 MB is recommended. In DirectAdmin you can customise your PHP config per domain by going to Account Manager > PHP Settings > Select memory_limit and set the value to 512 MB, wait for the server to reload the PHP FPM daemon.

Modifying disabled PHP functions

The following PHP functions need to be available for full functionality. If you are using the secure PHP option it is likely some of these functions may be disabled which will impact Craft CMS.

You will need to check for any functions listed and remove them.

Here's how you can keep secure PHP enabled but with the required PHP functions for Craft CMS enabled:

cd /usr/local/directadmin/custombuild/custom
echo "exec,system,passthru,shell_exec,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname" > php_disabled_functions
da build secure_php

This will still disable some pretty dangerous functions but allow one's required for Craft CMS.

Modifying the document root

The default document root on DirectAdmin is usually public_html e.g. /home/USER/domains/DOMAIN/public_html. Craft CMS requires the web folder to be the document root as the Craft CMS folders should be one level above the document root folder. While you can technically run Craft CMS under the public_html, you would need to implement additional measures to avoid sensitive files like .env, config paths and other files being accessible via web requests. It is a lot safer to ensure the document root is pointed to the Craft CMS web folder, to avoid this issue.

Modifying the document root for domains can be done through HTTPD customisations. Under an admin user Server Manager > Custom HTTPD Configurations, find the httpd.conf of the domain required and then click the "Customize" button.

Under additional CUSTOM tokens, choose CUSTOM1 and insert:

|?DOCROOT=/home/USER/domains/DOMAIN/public_html/web|

This sets the document root to a folder within the public_html folder. It is not required for public_html to be used, but the correct permissions are already set for this folder so it makes it easier.

MySQL timezone support

If you find MySQL timezone support indicates a warning when checking the System Report details in Craft CMS, run the following command:

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u da_admin -p mysql

You will need the da_admin MySQL password credential to run this command, which can be found in: /usr/local/directadmin/conf/my.cnf.

This will the populate MySQL with timezone data to fix the warning.

OPCache Extension

The OPCache extension is recommended. If it is not enabled, you can update your DirectAdmin PHP build config:

da build set_php "opcache" yes
da build "php_opcache"

Craft CMS queue runner

Craft CMS comes with a queue which by default is triggered by web Control Panel requests, this however is usually not ideal as it means queue jobs will only be run when someone is logged in. Instead, you can configure a queue runner which is independent of web requests. For DirectAdmin you can use either the CRON function or setup a systemd daemon. The CRON option is great if you do not have admin level access, whereas systemd is a more robust option but requires root access to configure and recommends the additional pcntl PHP extension.

Modify the USER and DOMAIN values to the required username and domain in DirectAdmin account.

Example cron queue runner:

*/5 * * * * /usr/bin/env php /home/USER/domains/DOMAIN/public_html/craft queue/run

Example daemon queue runner:

The WorkingDir value is used to set the path directly to where the craft CLI runner is located.

# /etc/systemd/system/[email protected]
# Note the @ in the filename above!
[Unit]
Description=Craft CMS Queue %i
After=network.target
After=mysql.service
Requires=mysql.service
[Service]
User=USER
Group=USER
WorkingDirectory=/home/USER/domains/DOMAIN/public_html
ExecStart==/usr/bin/nice -n 10 php craft queue/listen --verbose=1 --color=0
# Only restart after unexpected failures:
Restart=on-failure
# Extend time between restart attempts after a failure:
RestartSec=120
# Allow more time before issuing a kill signal:
TimeoutStopSec=300
[Install]
WantedBy=multi-user.target

The daemon then needs to be enabled and started:

systemctl enable craft-queue-worker
systemctl start craft-queue-worker

PHP pcntl extension

For queue runners run through a daemon the pcntl extension is recommended. It is not a core Craft CMS requirement but if you can enable it, it is worth doing. For DirectAdmin, the extension is not built automatically or able to be installed by the standard additional extension options currently, instead you can use custombuild with a custom PHP configure config to enable it.

In this example, it shows copying the default configure configuration for PHP 8.3, you can replace the PHP version without the dot.

cd /usr/local/directadmin/custombuild
mkdir -p custom/php
cp -fp "configure/php/configure.php83" "custom/php/configure.php83"

Edit the configure file within the custom path where --enable-pcntl needs to be appended, it should look similar to this example:

SSH session showing the configure file for a PHP version with enabling the pcntl module

Adding --enable-pcntl to the configure command

PHP then needs to be recompiled with custombuild

da build php

You can confirm the extension has been installed and loaded by running the following command:

php -m | grep pcntl

This command should return the text "pcntl", confirming it is present in the loaded extensions.

ModSecurity

If you have ModSecurity enabled, you are likely going to encounter 406 errors when performing various Craft CMS actions in the Control Panel. The reason for this is ModSecurity uses a variety of rulesets and patterns to try and detect suspicious or potentially dangerous requests sent to your server, which can be triggered on both GET and POST requests. While this is great, ModSecurity can be very paranoid and impact legitimate requests.

There are a few options you have available to resolve this:

  1. Turn off ModSecurity for your domain entirely.
  2. Exclude false positive rulesets from running on your domain
  3. Bypass ModSecurity rules via an IP address rule

If you are finding ModSecurity a pain, turning it off at the domain level will resolve the issue, but this will reduce security for any requests sent to your domain/server, instead you should consider excluding rulesets or an alternatively prevent ModSecurity from your own IP address, while keeping it enabled for all other requests, given you can likely trust your own actions (I hope!),

From my own experience, here's some rulesets which were triggered by innocent actions. I found this was the case for either general Control Panel actions or entry content which had code samples, which were being detected as potentially dangerous POST payload data. Because of the amount of rule exclusions, I decided excluding my own IP address was a better idea, so I wouldn't turn off these rules for other requests.

Rulesets you may want to consider excluding for Craft CMS:

921130 930120 932120 932125	932130 932140 932230 932235	932250 932260 933150 933160	933180 933210 941100 941110	941140 941160 941170 941180	941190 941250 941260 942290	942360 942550

To prevent ModSecurity from running at all by IP address, a Custom HTTPD configuration is required, this can be done in the same way as modifying the DOCROOT value but this time select the CUSTOM2 token and add the following directive, replacing xxx.xxx.xxx.xxx with your actual IP address:

<IfModule mod_security2.c>
    SecRuleEngine On
    SecRule REMOTE_ADDR "@ipMatch xxx.xxx.xxx.xxx" "id:1000001,phase:1,nolog,allow,ctl:ruleEngine=Off"
</IfModule>

Save the changes and wait for DirectAdmin to reload your webserver. This should now prevent any ModSecurity rules from being triggered when traffic is coming from the REMOTE_ADDR defined, while not excluding the rulesets for other requests.

Overall running Craft CMS on a server running DirectAdmin is possible. To configure Craft CMS correctly, admin level access is needed to configure certain settings, you may need to speak to your website host if you do not have root/SSH access to your environment.