Installation Guide

Updated Oct 3, 2026 Markdown

System Requirements

Supported Operating Systems

WHost supports a narrow, deliberately modern OS matrix. Any other release is refused by the installer when it starts, before it installs anything — see Supported OS for the full rationale.

OS Version Status
Ubuntu 24.04 LTS (Noble) Fully Supported
Ubuntu 22.04 LTS (Jammy) Fully Supported — Python 3.12 from the deadsnakes PPA; the nginx ModSecurity connector is compiled from verified source
Debian 12 (Bookworm) Not installable in the 1.0 line — no Python 3.12 package; the installer refuses it. Returns with the multi-ABI build
AlmaLinux 9 Fully Supported
Rocky Linux 9 Fully Supported
CentOS Stream 9 Fully Supported
Validation

The installer has been run end to end on clean servers with Ubuntu 24.04, Ubuntu 22.04 and AlmaLinux 9.8. The fixes those runs led to (agent/requirements.txt, Python 3.12 provisioning, the fail2ban log file, pinned digests and bundled signing keys for the downloads that are compiled into the web server, services restarted with the configuration the installer writes) are part of the installer the published repository carries. Rocky Linux 9 and CentOS Stream 9 take the same installer path as AlmaLinux 9; on all three the installer switches SELinux from Enforcing to Permissive — see SELinux on the RHEL family. Debian 12 is not installable in this release — see Agent Python runtime in the supported-OS page.

Not supported

every other release — among them Debian 11 and 13, the version 8 and 10 releases of AlmaLinux, Rocky Linux and CentOS Stream, Red Hat Enterprise Linux itself, and every Ubuntu release other than 22.04 and 24.04. The installer stops with an error that names the supported releases.

Minimum Hardware

During the beta every supported system was installed and tested on servers of this size; smaller servers have not been tested.

  • CPU: 2 vCPU
  • RAM: 4 GB
  • Disk: 40 GB (the operating system plus WHost took 8.4–11 GB right after installation)
  • Network: Static IP address

For production, plan for more: 4+ vCPU, 8+ GB RAM and SSD storage sized to the accounts you host.

Prerequisites

  • Fresh OS installation (no existing web server, database, or mail server)
  • Root access (sudo or root user)
  • Internet connectivity for package downloads
  • git, to fetch the installation repository (the installer installs the rest of its tools itself)
  • A fully qualified host name for the server (for example srv1.example.com), either already set on the system or passed with --hostname. Cloud images usually boot with a single-label name such as ubuntu-4gb-hel1-3; the installer stops on such a name before it installs anything (see Host name)

Quick Installation

shell
# Download and run the installer
cd /tmp
git clone https://wisecp.com/files/whost/whost.git
cd whost/installer
bash install.sh --hostname=srv1.example.com

--hostname can be left out when hostname -f already prints a fully qualified name.

The installer will automatically:

  • Detect your operating system
  • Set the server's host name (see Host name)
  • Install and configure all required services
  • Generate API credentials and admin password
  • Download the web panel for this release and verify its signature
  • Start the WHost Agent

Verified Downloads

Everything the installer compiles into the web server or loads as a rule set is fetched over TLS and checked against a detached signature before use, with the upstream keys shipped in installer/lib/ (nginx-release-keys.pub, owasp-modsecurity-signing-key.pub, owasp-crs-signing-key.pub). The ModSecurity-nginx connector and the OWASP Core Rule Set also carry a pinned SHA-256. The nginx source archive — needed only where the distribution ships no ModSecurity module package, such as Ubuntu 22.04 — carries a pinned SHA-256 for the nginx releases the installer lists (1.18.0, 1.22.1, 1.24.0) and is checked by its signature alone for any other release. A connector or nginx source that fails a check is not built: the module is left out and the installer says so in its output. A rule set that fails its check stops the installation.

The ionCube Loader, which every PHP process loads, is taken as one named release (15.5.1) from ionCube's download server and unpacked only when its archive matches the SHA-256 the installer pins for that release and the machine's architecture (x86_64, aarch64); an archive that fails the check, or a download that fails, stops the installation.

Panel Archive

The web panel is published as a separate signed archive, whost-panel-<version>.tar.gz, beside the repository. During the frontend step the installer downloads it together with its .asc signature and .sha256 file, checks the release signature against the public key shipped in installer/lib/whost-release.pub and the SHA-256 when the .sha256 file is present, and refuses to unpack an archive that has no signature or fails a check.

Two variables change where the archive comes from:

WHOST_PANEL_URLDownload from another location, such as a mirror. The .asc file must be published beside the archive there as well; a .sha256 file is checked when it is there.
WHOST_PANEL_ARCHIVEUse a local copy instead of downloading, for servers without outbound access. Keep the .asc file (and optionally the .sha256) next to it; the same checks apply. When both variables are set, the local copy is used.
shell
WHOST_PANEL_ARCHIVE=/root/whost-panel-VERSION.tar.gz bash install.sh

Replace VERSION with the release you are installing; bash install.sh --help prints it on its first line.

If the archive cannot be fetched or does not verify, the installer leaves the panel out and says so in its output (Panel archive could not be fetched or verified - the panel is NOT installed, followed by the file name it expects). The closing check then reports the missing panel page, and the run ends with an error instead of the completion screen. Provide the archive and run bash install.sh again; the download is skipped once the panel is in place.


Custom Installation

Command-Line Options

shell
bash install.sh [OPTIONS]
Option Description Default
--webserver=TYPE Web server: nginx_apache or nginx (see below) nginx_apache
--php-versions=LIST Comma-separated PHP versions 5.6,8.2,8.3,8.4
--php-default=VER Default PHP version 8.4
--hostname=FQDN Server hostname, fully qualified; set as the system host name, and also the subject of the self-signed certificate and the base of the defaults below. See Host name the system's name (hostname -f); required when that is not fully qualified
--nameservers=NS1,NS2 Nameservers written into new DNS zones ns1.<hostname>,ns2.<hostname>
--mail-hostname=HOST Mail server hostname mail.<hostname>
--ssl-email=EMAIL Email address for Let's Encrypt notifications not set
--timezone=TZ Server timezone, e.g. Europe/Istanbul auto-detected, UTC if unknown
--no-dns Skip PowerDNS installation DNS enabled
--no-mail Skip Postfix/Dovecot installation (Roundcube and Rspamd are skipped with it) Mail enabled
--no-ftp Skip Pure-FTPd installation FTP enabled
--no-firewall Skip firewall configuration Firewall enabled
--no-fail2ban Skip Fail2Ban installation Fail2Ban enabled
--no-modsecurity Skip ModSecurity (OWASP WAF) installation ModSecurity installed in detection_only (logs, never blocks)
--help Show help message -

Web server and the panel. With nginx_apache (the default) or nginx, nginx serves the panel at https://<hostname>/admin/. The installer refuses apache, openlitespeed and litespeed before it changes anything and names the two supported modes. To host sites on OpenLiteSpeed or LiteSpeed Enterprise, install with the default and switch under Plugins in the admin panel; the LiteSpeed Enterprise server itself is downloaded when it is activated there.

Examples

shell
# Nginx only, with PHP 8.3 and 8.4
bash install.sh --webserver=nginx --php-versions=8.3,8.4 --php-default=8.4

# All services, PHP 7.4 to 8.5
bash install.sh --php-versions=7.4,8.0,8.1,8.2,8.3,8.4,8.5

# Minimal install (no DNS, no mail, no FTP)
bash install.sh --no-dns --no-mail --no-ftp

# Own nameservers, hostname and Let's Encrypt contact
bash install.sh --hostname=srv1.example.com --nameservers=ns1.example.com,ns2.example.com [email protected]

Host name

The name the panel is installed under becomes the subject of the self-signed certificate, the base of the default nameservers (ns1.<hostname>) and mail host (mail.<hostname>), the DKIM domain, and the domain of the address the panel mails from (whost@<hostname> while no SMTP relay is configured). It therefore has to be fully qualified: at least two labels of letters, digits and hyphens, the last one not purely numeric. A single-label name (ubuntu-4gb-hel1-3, localhost) or an IP address is refused, and the installer stops before it installs anything:

text
[ERROR] 2026-09-26 09:14:03 Server hostname "ubuntu-4gb-hel1-3" is not a fully qualified domain name.
[ERROR] 2026-09-26 09:14:03 Run the installer with --hostname=<fqdn>, for example: --hostname=srv1.example.com

The installer also makes the system answer to that name: it runs hostnamectl set-hostname <fqdn> and points the 127.0.1.1 line of /etc/hosts at it (exactly one such line is kept; it is added when the file has none). hostname -f then prints the panel's name, which is what the mail server and the agent read. On cloud images whose /etc/hosts is managed by cloud-init the change stays in place across reboots. A run on a server that already carries the name changes nothing.

Give the name an A record in public DNS. The installation finishes without one, but the local mail server checks the domain of every sender address: while the name does not resolve, mail the panel sends through it (notifications, password resets, e-mailed sign-in codes) is turned away with 450 4.1.8 Sender address rejected: Domain not found, and the agent log records the notification with email=failed.

SELinux on the RHEL family

WHost does not ship an SELinux policy yet. With SELinux Enforcing — the default of AlmaLinux, Rocky Linux and CentOS Stream installed from their own media — nginx may not connect to the agent (the panel's API answers 502) or hand PHP sites to Apache on port 8080, fail2ban may not read the account logs, and quotaon is refused at boot. The installer therefore switches a host that enforces SELinux to Permissive before it installs anything, in the running system (setenforce 0) and in /etc/selinux/config (SELINUX=permissive), so the mode holds after a reboot. It says so on the screen, in /var/log/whost/install.log and in the closing summary:

text
[WARN] 2026-10-01 10:02:11 SELinux switched from Enforcing to Permissive: the running system and /etc/selinux/config

In Permissive mode SELinux still labels files and logs what it would have refused (the AVC entries in /var/log/audit/audit.log), but refuses nothing. A host that is already Permissive — some cloud images ship that way — or that has SELinux disabled is left as it is. If the installation fails and rolls back, the previous mode is put back. Running WHost with SELinux enforcing is planned after the beta; until then keep the host Permissive (getenforce prints the current mode).

PHP 5.6 note

PHP 5.6 is included in the default version list to support legacy customer scripts. It installs cleanly on Ubuntu (the ondrej/php PPA); on RHEL family 9 the Remi repository no longer ships PHP 5.6 packages and the installer will skip it with a warning (PHP 5.6 unavailable on RHEL 9+ (Remi dropped EOL series) — skipping). Modern accounts use PHP 8.4 (the default) regardless of OS.


Post-Installation

Verify Installation

shell
# Check service status
systemctl status whost-agent

# Verify the agent answers (it listens on 127.0.0.1 only)
curl -k https://127.0.0.1:2000/health

The answer is {"status":"ok","version":"<version>"}.

The agent tree /opt/whost/agent is owned by root with no access for other users (0750 directories, 0640 files); tenant shells cannot read the agent's source or compiled modules. stat -c '%a' /opt/whost/agent should print 750.

Access Admin Panel

The built-in admin panel is accessible at:

text
https://<SERVER_HOSTNAME>/admin/

It also answers on the server's IP address. Until a trusted certificate is installed, the browser warns about the self-signed one (see SSL Certificate Issues under Troubleshooting).

Sign in with the user name admin and the admin password printed at the end of the installer; the installer also stores the printed value in /etc/whost/admin_password (readable by root only). API keys are managed from Settings → API Access in the admin panel.

The installer writes no license: block into /etc/whost/agent.conf and takes no license option, so the agent starts without a key, in the NOT_ACTIVATED state. The first screen is the ordinary sign-in form: once the admin password printed by the installer is accepted, the panel opens on the license page, which says that no license is active and holds the key form. That sign-in's session is what submits the key, and until a key is accepted it opens nothing else in the panel. Activation contacts the license service over outbound HTTPS, binds the license to this server's public IP address and hardware, and stores the issued credentials in agent.conf; the license page then shows the active license and the rest of the panel opens. Afterwards the license is managed from Settings → License. See the admin user guide for the first-login steps.

Reinstalling a server under the same key. The license service keeps a key registered to the installation that activated it, together with credentials that lived only in that installation's agent.conf. After a reinstall those credentials are gone, and the activation form answers "This license key is already registered to an installation". Reissue the license with your license provider (for licenses bought from WISECP: the service's management screen on wisecp.com), then enter the key in the form again. A reissue is handed to the first request that reaches the license service afterwards: if the earlier installation is still running, stop its agent (systemctl stop whost-agent) before you reissue, or it picks the new credentials up on its next check and the new server is refused again. An installation that keeps running through a reissue needs nothing — its next check applies the new credentials by itself.

A fresh install accepts admin sign-ins from any address: no CAPTCHA is configured and the admin IP whitelist is empty, so the sign-in form is guarded only by the web server's request limit, the agent's lockout and the whost-agent fail2ban jail. After the first sign-in open Settings → Security and set the Admin Panel IP Whitelist and CAPTCHA Protection; the installer's closing output says the same.


Disk quota

Per-account disk limits are enforced by filesystem quota on /. On an ext4 root filesystem the installer adds usrquota,grpquota to the root filesystem's mount options, creates the aquota.* files and turns quota on, then checks whether it is actually active and says so in its output. On an XFS root it changes nothing and only reminds you in its output that the uquota mount option is needed (a reboot may be required), then runs the same check; on any other filesystem it skips quota with a warning.

Quota needs the quota_v2 kernel module. Ubuntu cloud images boot a kernel whose base module package does not include it. When the module is missing, the installer installs linux-modules-extra-<running kernel> and, on images that use the linux-image-virtual meta package, linux-image-extra-virtual, so that later kernel upgrades keep the module. The second package depends on the generic kernel image, so it also installs the kernel firmware packages (about 0.7 GB on disk) and a newer kernel when one is available; that kernel becomes the running one at the next reboot. Installing only the modules of the running kernel would be smaller, but the next kernel upgrade would then silently turn quota off.

If the installer reports Disk quota is NOT active on /, the panel still records and shows each plan's disk limit, but nothing enforces it, and the agent logs an error every time it tries to apply one. On ext4 the installer then takes the quota mount options out of /etc/fstab again and removes the aquota.* files, so that the server does not come up with a failed quotaon.service on every boot. To enable quota afterwards on ext4:

  1. Install the kernel module package of your distribution that provides fs/quota/quota_v2 (Ubuntu: apt-get install linux-modules-extra-$(uname -r) linux-image-extra-virtual), then run modprobe quota_v2.
  2. Add usrquota,grpquota to the options of the / line in /etc/fstab, then run mount -o remount /, quotacheck -cugm / and quotaon -v /.
  3. Confirm with quotaon -p / — both user and group quota should read on.

Limits are applied on / only: the agent sets each account's limit on the root filesystem, so a server whose /home is a separate filesystem does not enforce them.

Service Management

shell
# WHost Agent
systemctl start whost-agent
systemctl stop whost-agent
systemctl restart whost-agent
systemctl status whost-agent

# View logs (the agent writes to agent.log; the journal holds only unit start/stop events)
tail -f /var/log/whost/agent.log

On Ubuntu, unattended-upgrades installs security updates every day and needrestart then restarts the services that use an upgraded library, the WHost Agent among them. The panel and the API are away for the length of that restart (about 15–20 seconds on a small server); the agent checks its files and verifies its license again when it comes back. The installer leaves this distribution default in place: a service that keeps running on the old library does not receive the fix.


Firewall

The installer opens the following ports and refuses the rest: on Ubuntu it sets UFW's incoming policy to deny; on the RHEL family it adds the services below to firewalld's default zone, which refuses what it does not list, and removes the cockpit service that zone opens by default. The list is the same whichever --no-dns, --no-mail or --no-ftp options are given; with --no-firewall the firewall is left untouched.

Port Protocol Service
22 TCP SSH
80 TCP HTTP
443 TCP HTTPS
21 TCP FTP
30000–30100 TCP FTP passive data range
25 TCP SMTP
465, 587 TCP SMTP submission (implicit TLS / STARTTLS)
110, 995 TCP POP3 / POP3S
143, 993 TCP IMAP / IMAPS
53 TCP + UDP DNS
2000 TCP, loopback only WHost Agent — bound to 127.0.0.1, not opened in the firewall; the panel and /api/v1/ are served through the web server on 443

Manual Port Management

shell
# Ubuntu (UFW) — example: an extra service port
ufw allow 8443/tcp

# AlmaLinux / Rocky Linux / CentOS Stream (firewalld)
firewall-cmd --permanent --add-port=8443/tcp
firewall-cmd --reload

# Do not open 2000/tcp: the agent only listens on loopback and every
# client, the panel included, reaches it through https://<host>/api/v1/.

Troubleshooting

Agent won't start

shell
# Check that the configuration file loads (PYTHONPATH as in the service unit)
PYTHONPATH=/opt/whost/agent /opt/whost/venv/bin/python -c "from whost_agent.config import load_config; load_config()"

# Check port availability
ss -tlnp | grep 2000

# Unit start/stop events; the agent's own output goes to agent.log
journalctl -u whost-agent --no-pager -n 50
tail -50 /var/log/whost/agent.log

If the agent log shows ModuleNotFoundError: No module named 'paramiko', the venv is missing dependencies — re-run pip install:

shell
/opt/whost/venv/bin/python -m pip install --require-hashes -r /opt/whost/agent/requirements.lock
systemctl restart whost-agent

SSL Certificate Issues

The installer creates a self-signed certificate for the host name at /etc/whost/ssl/cert.pem, with its key at /etc/whost/ssl/key.pem, before any step that needs it. The panel's nginx site, Postfix, Dovecot and the agent's loopback listener all use this pair. The paths are fixed in the panel's nginx configuration and in the agent's service unit, so the server.ssl_cert and server.ssl_key keys of /etc/whost/agent.conf do not change the certificate that is served. To use a trusted certificate, replace the two files in place (keep the key readable by root only), then reload the services that read them:

shell
systemctl reload nginx postfix dovecot
systemctl restart whost-agent

Pure-FTPd uses a self-signed certificate of its own (/etc/ssl/private/pure-ftpd.pem on Ubuntu, /etc/pki/pure-ftpd/pure-ftpd.pem on the RHEL family).

Multi-OS Specific Issues

Unable to locate package php<version>-fpm on Ubuntu

The PHP packages come from the ondrej/php PPA, which the installer adds when a requested version is not in the configured sources. A failure to add the PPA does not stop the installer at that point; it stops at the package install with this message. Check that the PPA is configured (grep -rl ondrej /etc/apt/sources.list.d/), then run the installer again.

The panel's API answers 502 on AlmaLinux, Rocky Linux or CentOS Stream

The login page opens but every sign-in fails, and the nginx error log shows connect() to 127.0.0.1:2000 failed (13: Permission denied): SELinux is enforcing (a server switched back after the installation). Switch it to Permissive now and for the next boot (see SELinux on the RHEL family):

shell
setenforce 0
sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config

git: command not found before the installer starts

The quick installation fetches the repository with git; the installer then installs the rest of its base tools (curl, wget, tar, unzip and others) itself. On an image without git, install it first:

shell
dnf install -y git        # AlmaLinux, Rocky Linux, CentOS Stream
apt-get install -y git    # Ubuntu

Nginx returns the Apache 404 page on RHEL family

mod_ssl on RHEL drops /etc/httpd/conf.d/ssl.conf with Listen 443 https, which steals the port from Nginx. The installer disables this listen directive in nginx_apache mode. If you see the wrong page, verify:

shell
grep -i '^Listen 443\|^#Listen 443' /etc/httpd/conf.d/ssl.conf
ss -tlnp | grep ':443 '

The ^Listen 443 line should be commented; :443 should belong to nginx, not httpd. Restart both services if needed:

shell
systemctl restart httpd nginx

nginx: [emerg] Invalid input: IncludeOptional on account create

ModSecurity v3 (the nginx connector) accepts Include only, not IncludeOptional, and an Include pattern must match at least one file. The installer writes Include /etc/modsecurity/custom/*.conf into /etc/modsecurity/modsecurity.conf together with a placeholder file, /etc/modsecurity/custom/00-placeholder.conf, so the pattern always matches. If the error appears after a manual edit, replace IncludeOptional with Include and keep at least one .conf file in /etc/modsecurity/custom/.

Rollback

When a step fails, the installer stops and names the command that stopped it, in its output and in the transcript:

text
[ERROR] <date> <time> Installer stopped: "<command>" exited with <code> (transcript: /var/log/whost/install.log)

Fix the cause and run bash install.sh with the same options again. The second run goes through the steps again and completes the installation: package installs and configuration files come out the same, phpMyAdmin, Roundcube and a panel that is already in place are left as they are, and the admin password, the API key and secret and the service database passwords are generated anew — the closing screen prints the new values. Do not run the installer again on a server that is already in use: it writes agent.conf anew, which drops the license credentials and the settings saved from the panel, and on Ubuntu it removes the hosting accounts' PHP-FPM pools.

Steps that already ran are not undone by a failure inside one of the installer's own step functions, which is where almost every failure occurs; only a failure of a top-level command in install.sh runs the registered undo steps (stop the services installed so far, drop the databases the installer created, remove /opt/whost, the panel tree and the ModSecurity, phpMyAdmin and Roundcube trees). To remove a partial installation by hand (a run that stopped late can also have written the files listed under Uninstallation below):

shell
systemctl stop whost-agent
rm -rf /opt/whost
rm -rf /etc/whost
rm -f /etc/systemd/system/whost-agent.service
systemctl daemon-reload

Uninstallation

A default run (--webserver=nginx_apache, Ubuntu 24.04) leaves the files below, the ones the agent writes when it first starts included. Remove what WHost owns and keep the service packages (nginx, Apache, MariaDB, PowerDNS, Postfix, Dovecot, Pure-FTPd, Rspamd, PHP) with their data unless you also mean to remove the services.

shell
# Stop and disable the WHost units
systemctl disable --now whost-agent whost-policyd whost-http-ban.path whost-http-ban-apply
rm -f /etc/systemd/system/whost-agent.service /etc/systemd/system/whost-policyd.service \
      /etc/systemd/system/whost-http-ban.path /etc/systemd/system/whost-http-ban-apply.service
rm -f /etc/systemd/system/php*-fpm.service.d/whost-limits.conf
systemctl daemon-reload

# WHost trees: agent + venv + bundled Node.js runtimes, config + accounts, panel, state, backups + metrics, logs
rm -rf /opt/whost /etc/whost /var/www/whost /var/lib/whost /var/whost /var/log/whost

# Web server pieces WHost added (reload nginx and Apache afterwards, or remove the packages)
rm -f /etc/nginx/sites-enabled/whost-panel.conf /etc/nginx/sites-available/whost-panel.conf \
      /etc/nginx/snippets/whost-panel-locations.conf /etc/nginx/snippets/whost-security-headers.conf \
      /etc/nginx/conf.d/whost-panel-ratelimit.conf /etc/nginx/conf.d/whost-banlist.conf \
      /etc/nginx/conf.d/whost-cloudflare-realip.conf /etc/nginx/conf.d/whost-modsecurity.conf
rm -f /etc/apache2/conf-enabled/whost-status.conf /etc/apache2/conf-available/whost-status.conf \
      /etc/apache2/conf-enabled/whost-banlist.conf
rm -rf /etc/modsecurity            # ModSecurity configuration, the OWASP CRS copy, per-account rules

# phpMyAdmin and Roundcube, unpacked from their upstream archives and served through the panel site
rm -rf /usr/share/phpmyadmin /etc/phpmyadmin /var/lib/phpmyadmin /usr/share/roundcube /var/lib/roundcube
rm -f /etc/nginx/snippets/phpmyadmin.conf /etc/nginx/snippets/roundcube.conf

# PHP drop-ins, log rotation, fail2ban, SSH and Dovecot drop-ins
rm -f /etc/php/*/fpm/conf.d/99-whost-opcache.ini
rm -f /etc/logrotate.d/whost /etc/logrotate.d/whost-accounts /etc/logrotate.d/modsecurity
rm -f /etc/fail2ban/filter.d/whost-agent.conf /etc/fail2ban/filter.d/whost-web-scan.conf \
      /etc/fail2ban/action.d/whost-http-deny.conf /etc/fail2ban/action.d/whost-nginx-deny.conf
rm -f /usr/local/sbin/whost-http-ban
rm -rf /var/lib/fail2ban/whost-http-ban
rm -f /etc/ssh/sshd_config.d/10-whost-accounts.conf /etc/ssh/sshd_config.d/60-whost-hardening.conf
rm -f /etc/dovecot/conf.d/95-whost-quota.conf

# Kernel settings (ptrace restriction, swap tuning); the running values change back at the next reboot
rm -f /etc/sysctl.d/99-whost-ptrace.conf /etc/sysctl.d/99-whost-perf.conf

Kept unless you remove the services too: /etc/fail2ban/jail.local (the installer's jails, [whost-agent] included) and /etc/fail2ban/fail2ban.local, the ionCube loader (/usr/local/ioncube, /etc/php/*/mods-available/00-ioncube.ini and its conf.d links), the MariaDB drop-ins 99-whost.cnf (loopback only) and 99-whost-tuning.cnf (sized to the RAM) in /etc/mysql/mariadb.conf.d/ with /var/lib/mysql-files, the MariaDB root login in /root/.my.cnf, the MariaDB databases powerdns, pureftpd, roundcubemail and vmail with their users (powerdns, pureftpd, roundcube, vmail), the vmail user and group with the whost-noshell and whost-sso groups, the UFW rules (ufw status numbered), the usrquota,grpquota mount options in /etc/fstab with /aquota.user and /aquota.group, the kernel module packages the quota step installed where the image lacked them (linux-modules-extra-*, linux-image-extra-virtual), and the APT sources the installer added (ondrej/php, deadsnakes, rspamd).


Developed by WISECP LLC. Contact: [email protected]

Still Need Help?

Our support team is here around the clock for anything you can't find above.