Security
How ZoPanel protects the server and your customers: a panel without root, sandboxed accounts, firewall, WAF, malware scanning, 2FA and audit logs.
ZoPanel is built for shared hosting, where you have to assume that one customer's website will eventually be compromised. Several layers keep that problem inside one account: privilege separation in the panel, a sandbox for each account, network filtering, and tools that tell you when something is wrong. This page describes each layer and the settings that control it.
Architecture: a panel without root
ZoPanel runs as two processes with different privileges:
| Process | Runs as | Role |
|---|---|---|
zopanel serve |
the unprivileged zopanel user, with systemd hardening (NoNewPrivileges, ProtectSystem=strict, ProtectHome, no capabilities) |
Web interface, API, database, background jobs |
zopanel agent |
root | Carries out a fixed list of system actions through a local socket |
The web process never has root rights. It can only ask the agent for actions on a fixed allowlist, and the agent validates every parameter again instead of trusting the panel. The agent only accepts connections from the panel user or root. User data is never passed to a shell: every command runs as a fixed program with a separate argument list.
Root also avoids touching files inside customers' home directories. File operations in a home directory run as that account's own Linux user, so the kernel enforces the permissions, and a symlink planted by a customer cannot redirect root to another account's files.
Per-account sandbox
Each hosting account is a separate Linux user with its own resources:
- Resource limits: each account runs in its own systemd slice (
zp-<user>.slice) with CPU, memory and process limits taken from its package. The PHP-FPM pools, cron jobs and apps of the account all run inside that slice. - Separate PHP: each account has its own PHP-FPM pool running as its user, with
open_basediranddisable_functionsapplied. - File isolation: customers cannot read each other's
domainsfolders. nginx refuses to follow symlinks that point to files owned by someone else, and SFTP is chrooted to the home directory. - Disk quotas: under Settings → System → Disk quotas, Enable quotas lets the kernel enforce each package's disk space and file count (inode) limits. Without quotas, usage is only measured, and one account can fill the whole disk.
- Hidden processes: Security Center can mount
/procwithhidepid, so an account only sees its own processes and not other customers' command lines. - Sandboxed shell: the browser terminal for customers is limited to their home directory.
Docker apps
Apps from the App Store run in Docker with user-namespace remapping, which ZoPanel turns on automatically. A process running as root or as uid 1000 inside a container is mapped to a host uid range that no hosting account owns, so customers cannot read a container's environment variables or data through a shared uid.
Firewall and Fail2ban
The installer turns on UFW with your SSH port and ports 80, 443 and 8888 open, and enables it at boot. You manage rules under Security → Firewall (action, port, protocol, source).
Fail2ban is set up with:
| Jail | Watches | Rule |
|---|---|---|
sshd |
SSH logins | 5 failures in 10 minutes, 1 hour ban |
zopanel |
Panel password and 2FA failures | 8 failures in 15 minutes, 1 hour ban |
The mail and FTP services add their own jails when you install them. Banned IPs appear on the Security page, where you can unban them. If your websites are behind Cloudflare, turn on Websites behind Cloudflare so logs, rate limits and Fail2ban see the real visitor IP.
Web application firewall
Security → Web application firewall installs ModSecurity with the OWASP Core Rule Set. It blocks SQL injection, XSS, file inclusion, remote code execution and vulnerability scanners. The firewall is only loaded while at least one website uses it, at about 25 MB of RAM per nginx worker.
Each website has three modes in its Tools tab: On (block attacks), Detect only (log) and Off. Start with Detect only for a few days, review the events, then switch to blocking. If a rule blocks a legitimate request, click Allow this on the event to skip that rule for the website. Apply to all websites sets the mode for every site at once.
Malware scanner and quarantine
Malware scan looks for webshells, backdoors, obfuscated code, injected JavaScript and PHP files in upload folders. Every account is scanned automatically each Sunday, and customers can run Scan now on their own websites.
For each finding you can:
- Quarantine: the file is moved to
~/quarantinewith no permissions, so it can no longer run. The website may break if the file was legitimate. - Ignore: mark a false positive.
Customers can get an email or Telegram notification when suspicious files are found.
Two-factor authentication
Every user can turn on 2FA under My account → Two-factor authentication with any TOTP app (Google Authenticator, Authy, 1Password):
- Click Enable 2FA and scan the QR code.
- Enter the code and click Verify & enable.
- Save the 10 recovery codes. Each one signs you in once if you lose your phone. New recovery codes replaces them and the old ones stop working.
To make 2FA mandatory, go to Settings → General → Require two-factor authentication and choose Administrators and resellers or Everyone. You must turn on 2FA on your own account first. Users without 2FA must set it up the next time they sign in.
If an administrator loses both the phone and the recovery codes, run this on the server as root:
zopanel ctl disable-2fa USERNAME
This also signs the user out everywhere and revokes the user's API tokens.
Panel IP allowlist
Settings → General → Restrict panel access limits the panel (interface and API) to the IPs and networks you list. Your current IP must be in the list when you save it. If you lock yourself out, run on the server:
zopanel ctl allow-ip --clear # remove the restriction
zopanel ctl allow-ip 203.0.113.7 # or allow just one address
API tokens
API tokens (zpat_…) are created under My account → API tokens and require a Pro license. Creating a token asks for your password (and 2FA code) again. Each token has:
- Permissions: Full acts as your account. Provisioning only can only call the provisioning API
/api/v1(see Provisioning API). - Allowed from IPs: up to 20 IPs or ranges. Empty means any address.
- Expires: 30, 90 or 365 days, or never.
Even a full token cannot reach account security (password, 2FA), other tokens, the terminal, the license, fleet enrolment, panel access and 2FA policy, backup destinations, the recovery key, or restoring the panel configuration. Those actions require a signed-in administrator. Each token is limited to 1200 requests a minute. Changing your password revokes every token you own.
Activity log integrity and remote syslog
The Activity Log records security-relevant actions. Each entry is chained to the previous one, so an entry that is changed or deleted breaks the chain. Security Center reports it under Activity log intact.
An intruder with root access could still erase the whole log. To keep a copy that nobody on the server can change, enter a syslog server under Settings → General → Send the activity log to, for example udp://logs.example.com:514 or tcp://logs.example.com:514.
Secrets encrypted at rest
Sensitive values in the panel database are encrypted with AES-256-GCM. This covers S3 and SMTP credentials, bot tokens, API keys, the recovery key, TOTP secrets, external database passwords, app and container environment variables and fleet tokens. The key comes from the server's configuration file, which only root and the panel can read, so a copy of the database by itself reveals none of these values.
Security Center
The Security page opens with Security Center, which scores the server and the panel and offers a one-click Fix where a fix is safe. Its checks include:
- Server: firewall on and enabled at boot, SSH root password login, SSH password authentication, SSH login attempts, Fail2ban, automatic security updates, pending security updates and reboots, time synchronization, services exposed on public ports, extra UID 0 accounts, empty passwords, process hiding (
hidepid) and kernel hardening (sysctl). - Panel: 2FA for all admins, the 2FA policy, no
adminlogin name, a valid panel certificate, a panel IP allowlist, off-site backups, a successful backup in the last 48 hours, the panel version, API tokens unused for 90 days, unresolved malware and activity log integrity.
SSH fixes check that a key is set up first, so a fix cannot lock you out of the server.