DirectAdmin in 2025: The Lightweight cPanel Alternative
A client of mine ran 40 cPanel servers for a mid-sized shared hosting operation. In 2023, their licensing bill crossed $18,000/year — for accounts that were 80% idle WordPress sites. When I asked what features they actually used, the answer was “DNS, mail, PHP-FPM, and backups.” That’s it. They were paying enterprise-tier money for a control panel whose feature surface they touched maybe 10%.
They migrated to DirectAdmin over six weeks. Their licensing cost dropped to roughly a third. Nothing broke that mattered.
This guide is for sysadmins, hosting operators, and infrastructure engineers who are tired of the control panel tax and want a panel that gets out of the way. By the end, you’ll understand DirectAdmin’s architecture, know how to install and harden it properly, and have a realistic migration plan from cPanel or Plesk.
Prerequisites
Section titled “Prerequisites”- A clean server (AlmaLinux 9, Rocky 9, Debian 12, or Ubuntu 22.04/24.04) with at least 2GB RAM
- Root SSH access and a valid DirectAdmin license key
- Familiarity with systemd, firewalls, and the LAMP/LEMP stack
- A staging box you can destroy without consequences
The Control Panel Tax Nobody Talks About
Section titled “The Control Panel Tax Nobody Talks About”Since the Oakley Capital acquisition, cPanel moved to per-account pricing and the industry collectively groaned. Plesk went the other direction — tiered editions where every useful feature is an extension you pay extra for. Both are fine products. Both are also priced like you’re running a Fortune 500 datacenter when you’re running a VPS with 30 WordPress sites.
What Changed Since 2019
Section titled “What Changed Since 2019”cPanel’s per-account model means a server with 1,000 accounts costs vastly more than one with 50, even though the resource footprint is nearly identical. Plesk’s “Web Admin Edition” doesn’t include the features most people actually want, so you upgrade to “Web Pro” and then buy extensions. DirectAdmin, by contrast, has kept flat per-server pricing and — as of this writing — still offers lifetime licenses through resellers if you look.
The Real Cost Math
Section titled “The Real Cost Math”Here’s a rough licensing comparison. Prices change; verify against vendor sites before budgeting.
| Accounts | cPanel (approx.) | Plesk Web Pro (approx.) | DirectAdmin |
|---|---|---|---|
| 50 | ~$25/mo | ~$20/mo | ~$15/mo |
| 200 | ~$45/mo | ~$20/mo | ~$15/mo |
| 1000 | ~$100+/mo | ~$20/mo | ~$15/mo |
Plesk’s flat pricing is its advantage. DirectAdmin’s advantage is that it’s flat and cheaper, with a smaller resource footprint. On identical hardware, typical idle RAM for the control panel daemon alone runs roughly:
# Snapshot of control panel daemon memory on a freshly-booted boxps aux --sort=-rss | grep -E 'directadmin|cpanel|sw-engine' | awk '{print $6/1024 " MB\t" $11}'In testing, DirectAdmin’s core daemon typically sits under 30 MB RSS. cPanel’s stack (cpsrvd, cpanel-php-fpm, various Perl workers) commonly runs 300–500 MB. Plesk’s sw-engine plus sw-cp-server lands in the 200–400 MB range. That difference matters on a 2GB VPS.
Disk footprint is similarly lopsided. du -sh /usr/local/directadmin typically reports under 200 MB; cPanel’s /usr/local/cpanel regularly exceeds 1 GB.
Q: Is DirectAdmin actually cheaper at scale? Yes — for pure licensing, at 200+ accounts the savings are usually 50–70% versus cPanel’s per-account model. The catch is that you’re trading vendor support maturity and ecosystem depth for that savings.
Architecture and Design Philosophy
Section titled “Architecture and Design Philosophy”Understanding what DirectAdmin is explains why it behaves the way it does. It’s a single daemon written in C++, not a sprawl of Perl scripts and PHP workers pretending to be one system.
What DirectAdmin Actually Is
Section titled “What DirectAdmin Actually Is”The directadmin binary is the control plane. It listens on port 2222, exposes a task queue, and shells out to system tools. There’s no “cPanel PHP-FPM pool for the panel itself.” The service model is boring, and boring is a feature.
systemctl status directadmin --no-pagerOutput looks roughly like:
● directadmin.service - DirectAdmin Web Control Panel Loaded: loaded (/etc/systemd/system/directadmin.service; enabled) Active: active (running) since Mon 2026-09-21 09:14:02 UTC Main PID: 1842 (directadmin) Tasks: 12 (limit: 4915) Memory: 27.4MTwelve tasks, 27 MB. Compare that to a cPanel box where systemctl list-units | grep cpanel returns a wall of services.
The Plugin/Extension Model
Section titled “The Plugin/Extension Model”CustomBuild 2.0 is the build system. It compiles and manages Apache/nginx/LiteSpeed, PHP, MariaDB, Exim, Dovecot, and the rest. It’s driven by /usr/local/directadmin/custombuild/options.conf. Where cPanel’s EasyApache 4 gives you a GUI and a curated package set, CustomBuild gives you a config file and a build runner. The API is thinner — you won’t find a rich JSON API for everything. That’s the honest tradeoff.
Security Posture by Default
Section titled “Security Posture by Default”DirectAdmin doesn’t run PHP as root. It defaults to per-user isolation via PHP-FPM pools or suPHP depending on your build. The directadmin service user has narrow privileges. A representative directadmin.conf with security-relevant flags:
# /usr/local/directadmin/conf/directadmin.conf (excerpt)# Bind only to the management interface, not the public oneethernet_dev=eth0# Force SSL on the panelssl=1# Disable the "demo" mode that lets anyone poke arounddemo=0# Require strong passwords for user creationenforce_difficult_passwords=1# Restrict API accessapi_allow_ip=10.0.0.0/8# Log verbosity — keep this at 1 in production unless debugginglog_level=1Each flag here is doing real work. api_allow_ip in particular is often forgotten, leaving the panel API exposed to the world.
Architecture Feature Matrix
Section titled “Architecture Feature Matrix”| Feature | cPanel | Plesk | DirectAdmin |
|---|---|---|---|
| Core language | Perl + PHP | PHP + C++ | C++ |
| Web server choice | Apache/nginx | nginx/Apache | Apache/nginx/LiteSpeed/OLS/nginx_unit |
| PHP handler modes | suPHP, FPM | FPM, FastCGI | suPHP, FPM, mod_php, lsapi |
| Built-in backup | Yes | Yes | Yes |
| CLI-first workflow | Partial | Partial | Yes |
| Idle RAM (panel) | 300–500 MB | 200–400 MB | <50 MB |
Installation — Doing It Right the First Time
Section titled “Installation — Doing It Right the First Time”Installation is where people screw up 90% of the time. The other 10% is CustomBuild configuration.
Pre-Flight Checklist
Section titled “Pre-Flight Checklist”DirectAdmin wants a clean box. If you’ve got nginx, Apache, MySQL, or Postfix already installed, remove them first. The installer will happily half-install on top of an existing stack and leave you debugging for hours.
Disk layout: put /home on its own volume. Put /var on its own volume if you can. /usr/local/directadmin can live on the root volume — it’s small. Separating /home means a runaway user can’t fill your root filesystem and take down the panel.
The Install Command
Section titled “The Install Command”After downloading the setup script from DirectAdmin’s official site:
# Fetch setup.sh and run with CustomBuild enabledwget -O setup.sh https://www.directadmin.com/setup.shchmod 700 setup.sh./setup.sh autoThe auto mode reads your license key from the environment or prompts for it, then runs CustomBuild to install the full stack. License keys are IP-bound by default — the panel checks the outbound IP against the license server. If you’re behind NAT, you need a hostname-bound license or a proxy config.
Post-install, harden immediately:
# Install CSF firewall (ConfigServer)cd /usr/local/srcwget https://download.configserver.com/csf.tgztar -xzf csf.tgzcd csf && sh install.sh# Verify it will work with this kernelperl /usr/local/csf/bin/csftest.plThe csftest.pl step is important — it tells you whether iptables/nftables is actually usable on this kernel before you enable CSF and lock yourself out.
Post-Install Sanity Checks
Section titled “Post-Install Sanity Checks”# Confirm the expected services are upsystemctl list-units --type=service --state=running | grep -E 'directadmin|exim|dovecot|httpd|php-fpm|named|mariadb'If named isn’t running, DNS won’t resolve for new zones. If exim isn’t running, mail silently queues and dies. Check /var/log/directadmin/error.log for the usual suspects — often it’s a port conflict or a permissions issue on /home.
War story: A client once installed DA on a box with a stray nginx listening on port 80. The installer didn’t fail — it just skipped starting Apache. Six hours of “why won’t my sites load” later, ss -tlnp | grep :80 revealed the culprit. Always run ss -tlnp before installing.
CustomBuild 2.0 — Where You Earn Your Keep
Section titled “CustomBuild 2.0 — Where You Earn Your Keep”CustomBuild is the single most important thing to understand. Get it wrong and you’ll fight your server for years.
Understanding options.conf
Section titled “Understanding options.conf”This file drives every build decision. Here’s an opinionated baseline for 2025:
# /usr/local/directadmin/custombuild/options.conf (excerpt)webserver=nginx_apachenginx=yesapache=yesphp1_release=8.3php1_mode=php-fpmphp2_release=8.2php2_mode=php-fpmphp3_release=8.1php3_mode=php-fpmphp4_release=7.4php4_mode=php-fpmmysql=mariadbmysql_inst=yesmariadb=10.11exim=yeseximconf=yesdovecot=yesdkim=yesspamassassin=yesnginx_apache means nginx serves static content and proxies dynamic requests to Apache. This is the standard high-performance setup in 2025 — you get nginx’s efficiency for static assets and Apache’s .htaccess compatibility for the apps that need it.
PHP Version Management
Section titled “PHP Version Management”After editing options.conf, rebuild:
cd /usr/local/directadmin/custombuild./build update./build php n./build rewrite_confs./build php n compiles PHP without prompting (the n answers “no” to the interactive questions). ./build rewrite_confs regenerates the web server configs to match your new setup. Skipping the second step is a classic mistake — the PHP binaries exist but the configs still point at the old versions.
Per-user PHP override:
php1_release=8.2php1_mode=php-fpmThen ./build rewrite_confs again. This lets you pin a user to a specific PHP version without touching the global config.
PHP Handler Tradeoffs
Section titled “PHP Handler Tradeoffs”| Mode | Performance | Isolation | Notes |
|---|---|---|---|
| mod_php | High | None | Runs as Apache user — avoid |
| suPHP | Low | Good | Slow, legacy, still used |
| php-fpm | High | Good | Default choice in 2025 |
| lsapi | Highest | Good | LiteSpeed only |
Use php-fpm unless you have a specific reason not to.
Mail Stack Decisions
Section titled “Mail Stack Decisions”MariaDB over MySQL 8 for most workloads — it’s faster for typical hosting, has better default configs, and DirectAdmin’s tooling assumes it. Exim and Dovecot come configured reasonably; tune them once you hit volume. DKIM is non-negotiable:
# Generate DKIM keys for a domain via DA's built-in tool/usr/local/directadmin/scripts/dkim_create.sh example.comThis writes the private key to /etc/virtual/example.com/dkim.private.key and gives you the public key to publish in DNS. If you skip DKIM, SPF, and DMARC, you will get blacklisted. Not “might” — will.
Q: Can I switch web servers after install?
Yes, but it’s a rebuild. Change webserver= in options.conf, run ./build update && ./build rewrite_confs, and expect a few minutes of downtime. Test on staging first.
Q: How do I add a PHP version not in the default list?
CustomBuild supports a limited set. For anything exotic, use the custom build path or compile PHP manually and register it with the panel — this is where the thinner API hurts compared to cPanel.
User Management, Resellers, and the Multi-Tenant Reality
Section titled “User Management, Resellers, and the Multi-Tenant Reality”Reseller accounts are how hosting businesses scale. They’re also how hosting businesses get compromised when configured lazily.
The Reseller Model
Section titled “The Reseller Model”Resellers get a package allocation and can create users underneath it. Never give resellers SSH by default. Never give them the ability to modify system configs. The panel’s permission model handles this, but you need to verify defaults.
# Create a reseller via the DA CLI/usr/local/directadmin/da admin user_create reseller1 \ --passwd='[strong-random-password]' \ --email='ops@example.com' \ --package='reseller_basic' \ --reseller=yesThe --reseller=yes flag is what elevates them. Without it, you’ve just made a regular user.
Per-User Security Hardening
Section titled “Per-User Security Hardening”open_basedir should be enforced for every PHP-FPM pool. DA does this by default in recent versions but verify. Disable shell for 99% of users:
# Disable shell access for a user/usr/local/directadmin/da admin user_modify alice --shell=/bin/falseThe classic public_html misconfiguration — world-writable directories — is still the most common cause of defacement I see. Check with:
find /home -type d -perm -0002 -name public_html 2>/dev/nullAnything that returns should be investigated.
Backups That Actually Restore
Section titled “Backups That Actually Restore”DA’s built-in backup system works. It’s not great, but it works. The problem is people store backups on the same box. Don’t.
# DA backup cron with S3 offload/usr/local/directadmin/da backup_create \ --domain=example.com \ --path=/home/admin_backups \ --s3_bucket=my-backups \ --s3_access_key=[key] \ --s3_secret_key=[secret]For anything serious, use restic or borg on top of DA’s /home directories:
#!/bin/bashexport RESTIC_REPOSITORY="s3:s3.amazonaws.com/my-backup-bucket/da"export RESTIC_PASSWORD_FILE="/root/.restic-pass"export AWS_ACCESS_KEY_ID="[key]"export AWS_SECRET_ACCESS_KEY="[secret]"
restic backup /home \ --exclude='/home/*/backups' \ --exclude='/home/*/.trash' \ --tag directadmin \ --host "$(hostname)"War story: A client got hit with ransomware that encrypted their DA backups — because the backups lived on the same box and the attacker had root. Off-site or it doesn’t count.
Security Operations — The Part That Separates Pros From Tourists
Section titled “Security Operations — The Part That Separates Pros From Tourists”Running DA without CSF, monitoring, and a patching cadence is malpractice. Here’s the baseline.
Firewall and Intrusion Detection
Section titled “Firewall and Intrusion Detection”CSF + LFD is the standard. Install it, configure it, and enable the aggressive settings:
# /etc/csf/csf.conf (hardened baseline excerpt)TCP_IN = "20,21,22,25,53,80,110,143,443,465,587,993,995,2222"TCP_OUT = "20,21,22,25,53,80,110,113,443,587,993,995"UDP_IN = "53"UDP_OUT = "53"# Rate limit SSHLF_SSHD = "5"LF_SSHD_PERM = "3600"# Block port scansLF_PORTSCAN = "1"LF_PORTSCAN_PERM = "3600"# Email alertsLF_ALERT_TO = "ops@example.com"After editing, csf -r to reload. Test with csf -l to see current rules.
Monitoring and Alerting
Section titled “Monitoring and Alerting”At minimum, monitor directadmin, exim, dovecot, httpd/nginx, and mariadb. Node exporter plus a Prometheus scrape config:
# /etc/prometheus/prometheus.yml (excerpt)scrape_configs: - job_name: 'da-host' static_configs: - targets: ['da-host-01.internal:9100'] - job_name: 'mariadb' static_configs: - targets: ['da-host-01.internal:9104']Ship logs to Loki or a central SIEM. If you’re not doing this, you have no forensic capability when something goes wrong.
Patching Cadence
Section titled “Patching Cadence”Two schedules: OS updates via dnf-automatic, and DA/CustomBuild updates via cron.
# /etc/dnf/automatic.conf (excerpt)[commands]upgrade_type = securityapply_updates = yes0 3 * * 0 root cd /usr/local/directadmin/custombuild && ./build update && ./build update_da && ./build rewrite_confsRun this weekly, not daily. Rebuilds can break things; you want them on a schedule you can react to.
Q: Does DirectAdmin have a WAF? Not built-in. You’ll want ModSecurity with the OWASP CRS, or Coraza if you’re on a newer stack. cPanel’s ModSecurity integration is more polished out of the box, but DA supports it fine with a bit of config.
Migration From cPanel/Plesk — The Real Talk
Section titled “Migration From cPanel/Plesk — The Real Talk”Migration is where the cost savings either materialize or evaporate into a two-week firefight. Plan it properly.
What Migrates Cleanly
Section titled “What Migrates Cleanly”Standard accounts, domains, mailboxes, databases, and DNS zones. SSL certs — don’t port them, just re-issue with Let’s Encrypt. It’s faster and cleaner.
What Breaks
Section titled “What Breaks”Custom Apache configs, cPanel-specific PHP extensions (looking at you, ea-* packages), cron jobs with hardcoded cPanel paths, and .htaccess files that assume cPanel’s specific module set.
The Migration Workflow
Section titled “The Migration Workflow”DA has a built-in cPanel restore tool. When it works, it’s great:
# Restore a cPanel backup tarball/usr/local/directadmin/scripts/restore_backup.sh /path/to/cpmove-user.tar.gzFor everything else, rsync and imapsync:
# Sync /home directoriesrsync -avz --delete --exclude='.cpanel' --exclude='.trash' \ root@old-cpanel:/home/user/ /home/user/
# Migrate mailboxesimapsync --host1 old.example.com --user1 alice@example.com --password1 '[pass]' \ --host2 new.example.com --user2 alice@example.com --password2 '[pass]' \ --automap --useheader 'Message-Id'DNS cutover: lower TTL to 300 seconds 24 hours before cutover. Run both boxes in parallel for a week. Keep the old box warm for rollback.
War story: A migration I consulted on forgot to recreate SPF records on the new box. Every outbound email bounced for 48 hours. Check your DNS records against the source before cutover — every single one.
When DirectAdmin Is the Wrong Choice
Section titled “When DirectAdmin Is the Wrong Choice”DirectAdmin is not universally better. Be honest about your situation.
| Use Case | Recommendation |
|---|---|
| 10+ servers, technical staff | DirectAdmin |
| Single server, cost-sensitive | DirectAdmin |
| Agency without sysadmin depth | cPanel/Plesk |
| Heavy cPanel plugin dependency | Stay on cPanel |
| Enterprise SLA requirements | cPanel/Plesk |
| Managed hosting reseller | Plesk |
Q: Should I migrate from cPanel to DirectAdmin? If you have technical staff, 10+ servers, and you’re paying more than $200/month in cPanel licensing, yes. If you’re a one-person shop without CLI comfort, no — the support ecosystem and GUI polish aren’t there.
Common Mistakes and How to Avoid Them
Section titled “Common Mistakes and How to Avoid Them”- Installing on a dirty box. Remove existing web stacks first. The installer won’t always fail loudly.
- Skipping
./build rewrite_confs. Your configs won’t match your binaries. Weird bugs follow. - Backups on the same box. This is not a backup strategy. It’s a ransomware delivery mechanism.
- Not enforcing
open_basedir. One compromised site becomes ten. Verify per-user isolation. - Ignoring the DKIM/SPF/DMARC trifecta. You will land in spam. Every time.
Q: Is DirectAdmin secure enough for production? Yes, with caveats. The core is solid and the defaults are sane. The thinner ecosystem means you’re responsible for more of the hardening yourself — CSF, ModSecurity, patching. If you do that work, it’s production-grade.
Q: How does DA handle Let’s Encrypt? It has native Let’s Encrypt integration. Enable it per-domain in the panel or via CLI, and it handles issuance and renewal automatically. No certbot gymnastics needed.
Q: Can I run DirectAdmin on ARM? As of this writing, official support is x86_64 only. ARM builds exist in community forks but aren’t supported. Don’t run production on unsupported architectures.
Q: What’s the difference between DA’s Evolution skin and the classic one? Evolution is the modern, responsive UI introduced around 2019. Classic is the legacy interface. Evolution is the default and what you should use unless you have a specific reason not to.
Q: Does DA support Docker? Not natively. You can run Docker alongside it, but the panel doesn’t manage containers. If container orchestration is core to your workflow, DA isn’t the right panel.
Key Takeaways
Section titled “Key Takeaways”30-Day Pilot Plan
Section titled “30-Day Pilot Plan”Week 1: Stand up a test box. Install DA, break it, rebuild it. Learn CustomBuild. Week 2: Migrate one low-risk client. Run parallel with the old box. Week 3: Monitor, tune, document. Write your runbook. Week 4: Decision point. If it worked, plan the fleet migration. If it didn’t, you lost a month and learned something.
Ansible snippet for repeatable installs:
- hosts: da_servers become: yes tasks: - name: Ensure clean web stack dnf: name: ['httpd', 'nginx', 'mariadb-server'] state: absent - name: Download DA setup get_url: url: https://www.directadmin.com/setup.sh dest: /root/setup.sh mode: '0700' - name: Run installer shell: /root/setup.sh auto args: creates: /usr/local/directadmin/directadminThat’s the whole pitch. DirectAdmin isn’t glamorous. It’s cheaper, leaner, and boring in the best way — which is exactly what you want from a control panel.