Slot 42 EasycPanel
Secure a Fresh cPanel Server in 30 Minutes with EasycPanel
A 30-minute hardening checklist for a new cPanel box: SSH keys, CSF, ModSecurity, PHP and MySQL tuning, tested backups, and what EasycPanel automates for you.
A fresh cPanel install is not a secure server. It ships with password SSH on port 22, no firewall worth the name, ModSecurity off or unvendored, MySQL running on defaults sized for a laptop, and a backup configuration that does nothing. The window between the provider handing you root and you finishing this list is the most dangerous half hour the box will ever have.
I wrote EasycPanel because I was doing this same list by hand on server after server. It is an open-source one-click cPanel setup, optimization and security script, currently v4.1 (July 2026), running on AlmaLinux and CloudLinux 8 and 9, with support for Apache, Nginx and LiteSpeed. The repo is at https://github.com/ahtshamjutt91/easycpanel.
dnf install -y git
git clone https://github.com/ahtshamjutt91/easycpanel.git
cd easycpanel
Read the menu before you pick anything. The options are named for what they do. Below is the manual version of every step, so you know what changed on your server whether you ran the script or not.
Minutes 0-3: the boring prerequisites
Update, then set a real fully qualified hostname. cPanel refuses to behave without one, and it must not be a domain you plan to host as an account.
dnf -y update
hostnamectl set-hostname srv01.example.com
hostname -f
Point an A record at the server for that hostname and confirm it resolves before moving on. Then refresh the licence and check the nameservers:
/usr/local/cpanel/cpkeyclt
dig +short srv01.example.com
dig +short ns1.example.com
Set ns1/ns2 in WHM > Basic WebHost Manager Setup, create A records for both, and register glue records at the registrar. Servers get built with nameservers that were never glued, and nobody notices until the first domain goes live.
EasycPanel covers this under its initial setup steps.
Minutes 3-8: SSH
Key authentication first, on your workstation:
ssh-keygen -t ed25519 -C "admin@example.com"
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@srv01.example.com
Then on the server, put the hardening in a drop-in rather than editing the shipped file:
vi /etc/ssh/sshd_config.d/99-hardening.conf
Port 5822
PermitRootLogin prohibit-password
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
X11Forwarding no
On EL8/EL9 with SELinux enforcing, the new port needs a label or sshd will not bind:
dnf install -y policycoreutils-python-utils
semanage port -a -t ssh_port_t -p tcp 5822
sshd -t && systemctl reload sshd
Open the new port in the firewall before you reload, and test the new session in a second terminal while the first one is still connected. A typo in AuthenticationMethods or a forgotten SELinux label locks you out of a box whose console you may not have. I have watched people skip this step exactly once.
EasycPanel handles SSH hardening, including moving the port and disabling password login.
Minutes 8-13: firewall
CSF is the sane default on cPanel.
# AlmaLinux, Rocky, CloudLinux
sudo yum install cpanel-csf
# Ubuntu
sudo apt install cpanel-csf
perl /usr/local/csf/bin/csftest.pl
Install from the package, not from the tarball everyone still has bookmarked. ConfigServer’s own developers stopped maintaining CSF at the end of August 2025 and released it under the GPL; on supported cPanel versions WebPros maintains the cpanel-csf package for security and stability updates, and the old download host is gone, so the wget in every guide older than that now just hangs. CSF also does not coexist with firewalld, so remove firewalld before you install, and run these as root.
Set the ports cPanel actually needs in /etc/csf/csf.conf, and add your custom SSH port:
TCP_IN = "20,21,25,53,80,110,143,443,465,587,993,995,2077,2078,2082,2083,2086,2087,2095,2096,5822"
TCP_OUT = "20,21,22,25,37,43,53,80,110,113,443,587,873,993,995,2087,2089,2703"
UDP_IN = "20,21,53"
UDP_OUT = "20,21,53,113,123,873,6277"
TESTING = "0"
LF_ALERT_TO = "you@yourdomain.com"
csf -r
Leaving TESTING = "1" is the most common CSF mistake: a cron job flushes your rules every five minutes and the firewall you think you installed is not running. LFD alerts go to a real mailbox you read, not to root@localhost.
EasycPanel installs and configures the firewall.
Minutes 13-17: ModSecurity
Enable a maintained vendor in WHM > Security Center > ModSecurity Vendor Configuration. cPanel ships OWASP CRS and a couple of commercial vendors; pick one that receives updates and let it auto-update.
The part people get wrong is what happens next. A legitimate request trips a rule, a site breaks, and someone disables ModSecurity globally. Tune instead. Find the offending rule ID in WHM > ModSecurity Tools > Hits List, then disable just that rule, just where it fires:
# /etc/apache2/conf.d/userdata/std/2_4/username/example.com/modsec.conf
<LocationMatch "/wp-admin/admin-ajax.php">
SecRuleRemoveById 941100
</LocationMatch>
/scripts/ensure_vhost_includes --user=username
/scripts/restartsrv_httpd
EasycPanel sets up ModSecurity with a ruleset as part of its security category.
Minutes 17-21: web server and PHP
Three reasonable choices, and the decision changes what you tune afterwards:
| Stack | Good for | What you tune |
|---|---|---|
| Apache + PHP-FPM | Default, most compatible, .htaccess works everywhere |
MPM event workers, per-account FPM pools, mod_evasive |
Nginx reverse proxy (ea-nginx) |
Static-heavy and high-concurrency sites, cheap caching | Proxy cache zones, worker connections, .htaccess still honoured by the Apache backend |
| LiteSpeed | WordPress at scale, LSCache, drop-in Apache config compatibility | LSCache rules, per-account connection limits (licence required) |
For PHP, install only versions you support, and get off EOL branches. An EOL PHP is the single most common reason a cPanel box gets compromised through a customer site.
whmapi1 php_get_installed_versions
whmapi1 php_set_system_default_version version=ea-php83
Then look at the functions that let PHP start processes, in WHM > MultiPHP INI Editor > Editor Mode:
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,show_source
That list is a starting position, not a truth. Plenty of legitimate software shells out: Composer, Laravel’s queue workers and artisan, WordPress plugins that call ffmpeg or ImageMagick, backup tools, anything that shells out to git. Set it system-wide on a shared box and you will spend the next fortnight finding out which of your customers’ sites it broke, one support ticket at a time.
Apply it per domain instead, after you know what each account runs. WHM > MultiPHP Manager > User Domain Settings is where the domain-specific PHP and PHP-FPM settings live, so the accounts running plain WordPress get the strict list while the one running a Laravel app keeps proc_open. Underneath it, cPanel builds each pool from that domain’s php-fpm.yaml file in the user’s userdata directory, and if you edit one by hand, /usr/ is the script that turns the YAML back into pool configuration and Apache vhost entries. On a single-tenant server you own, test the applications first and then tighten.
Turn on PHP open_basedir Tweak in WHM > Tweak Settings so one compromised account cannot read another’s home directory. Expect a handful of applications to complain about open_basedir; add their real paths rather than switching it off.
EasycPanel covers web server setup and tuning plus PHP configuration.
Minutes 21-25: MySQL/MariaDB
The default innodb_buffer_pool_size is far too small on any real server. On a cPanel box, Apache/LiteSpeed and PHP-FPM live on the same machine, so budget roughly 25-40% of RAM for InnoDB rather than the 70% you would give a dedicated database server.
# /etc/my.cnf
[mysqld]
innodb_buffer_pool_size = 4G
innodb_buffer_pool_instances = 4
innodb_file_per_table = 1
innodb_flush_log_at_trx_commit = 1
max_connections = 300
slow_query_log = 1
slow_query_log_file = /var/log/mysql-slow.log
long_query_time = 2
innodb_flush_log_at_trx_commit = 1 is the default and it is the only setting that is fully ACID: the log is written and flushed to disk at every commit. Guides push 2 because it is faster, and it is, but the manual is blunt about what you are buying it with. At 2 the log is written at each commit and flushed once a second, so a crash can lose up to about a second of transactions that the application was told had committed. On a shared hosting box that is somebody’s order, and they have the confirmation email. Leave it at 1 unless the person who owns the data has agreed to that trade in words.
/scripts/restartsrv_mysql
mysqldumpslow -s t -t 20 /var/log/mysql-slow.log
The slow query log is what tells you which customer’s plugin is eating the server at 3am. Turn it on at build time, not after the first outage.
EasycPanel includes MySQL tuning.
Minutes 25-28: backups you have actually restored
Configure WHM > Backup > Backup Configuration with an offsite destination (SFTP, S3, rsync, or WebDAV), daily retention plus a weekly, and compression on if the destination charges by the gigabyte.
Then do the part everyone skips. Take a backup, restore one account into a scratch account, and load the site.
/usr/local/cpanel/bin/backup --force
A backup you have never restored is a hypothesis. I have opened plenty of nightly archives that turned out to be empty, truncated, or missing every database because the destination filled up three months earlier and the only alert went to an unread root mailbox.
EasycPanel has hooks for backups and monitoring.
Minutes 28-30: updates, monitoring, outbound mail
Set the cPanel release tier and automatic updates in WHM > Update Preferences. For the OS, security-only unattended updates:
dnf install -y dnf-automatic
sed -i 's/^upgrade_type =.*/upgrade_type = security/' /etc/dnf/automatic.conf
sed -i 's/^apply_updates =.*/apply_updates = yes/' /etc/dnf/automatic.conf
systemctl enable --now dnf-automatic.timer
cPanel already excludes its own packages from yum, so leave those exclusions alone.
Watch the two things that actually take servers down. Disk and inode exhaustion:
df -h
df -i
du -xh /var --max-depth=2 | sort -h | tail -20
Inodes run out long before bytes do on a mail server. And the mail queue:
exim -bpc
exiqsumm
For outbound mail, publish SPF and DKIM for every domain from WHM > Email Deliverability and fix anything it flags. Then restrict who can send. Enable SMTP Restrictions so only Exim, root and Mailman can talk to port 25. Turn on “Prevent ‘nobody’ from sending mail” and set a max hourly emails per domain in Tweak Settings. Enable cPHulk while you are in there.
A fresh IP has no sending reputation. Confirm the reverse DNS your provider set matches your hostname, then ramp volume up over days rather than sending 50,000 messages on day one.
dig +short -x 203.0.113.10
EasycPanel covers automatic updates and outbound-mail related hardening in its security options.
An honest note about the script
EasycPanel is a starting point. It gets a fresh box from “installed” to “defensible” in one pass and saves an hour of typing, but it is not a substitute for knowing what it changed. Read the menu, read the repo, and after the run take five minutes to check /etc/csf/csf.conf, your sshd_config drop-in, and /etc/my.cnf with your own eyes. If a customer later asks why port 22 is closed, “the script did it” is not an answer.
FAQ
Does EasycPanel work on CentOS 7 or Ubuntu?
v4.1 targets AlmaLinux and CloudLinux 8 and 9, which is what cPanel itself supports going forward. Anything older should be rebuilt rather than hardened in place.
Can I run it on a server that already has customers on it?
I would not run any bulk setup script against a live production box without reading exactly what each option does first. Test on a fresh VPS, note the changes, then apply them deliberately on the live server.
Should I use Nginx or LiteSpeed instead of Apache?
Apache with PHP-FPM is the safe default and the easiest to support. Move to ea-nginx if you are serving a lot of static traffic, or to LiteSpeed if you are running WordPress at volume and want LSCache. Decide before you migrate accounts on, not after.
Is CSF enough, or do I need something else?
CSF plus LFD, cPHulk, and a maintained ModSecurity vendor covers the attacks that actually reach a cPanel server. What CSF cannot help with is an outdated plugin on a customer’s site, which is why the PHP version policy and open_basedir matter as much as the firewall.
How long does this really take?
Thirty minutes by hand if you have done it before and nothing surprises you. The DNS propagation for the hostname and nameservers is usually what makes it longer.
Where this fits
This checklist is what I run on every new build before a single account is created, and it is the same list behind cPanel server setup work I do for hosts and agencies. If you are standing up a box to move accounts onto, harden it first and migrate second, then work through the migration side once the server is not the weak link.