# Frequently Asked Questions

**Quick links:** [Installation](installation.md) · [Admin guide](admin-user-guide.md) · [Troubleshooting](troubleshooting.md)

---

## Licensing & activation

### How is WHost licensed?

Per-server. Each WHost agent installation needs its own license key, issued from your WISECP account; the activation form asks for the key only. Trial licenses are available on request.

### What happens if my license expires?

An expired license gets **no grace period**. The license service answers `LICENSE_EXPIRED` at the agent's next check — the background check (roughly once a day), an agent restart or **Verify Now** on the license page — and the panel is suspended at once: the admin and client panels close (admin pages lead to the license page, client pages to a "The control panel is temporarily unavailable" notice for your customers that names no license detail) and every API call other than sign-in and the license endpoints answers `403 LICENSE_SUSPENDED`. Signing in as admin still works: the panel then opens on the license page (Settings → License), so you can renew without SSH.

Hosted websites, mail, DNS and FTP keep running and customer data is not touched — the suspension closes the panel and the API only. After renewing on wisecp.com, click **Verify Now** on the license page (signing in does not check the license; it opens that page); the panel opens again as soon as the check answers active. Left alone, the next background check can be up to about 29 hours away.

The 24-hour **grace period** (`license.grace_period`) covers a different case: license servers that cannot be reached. The panel keeps working with a warning banner in the admin topbar, the agent retries every 9–18 minutes, and the panel is suspended only when no check has succeeded for 24 hours after the last successful one.

### My server's IP changed — does the license keep working?

That depends on the license's lock type, which is set on the license itself (Settings → License shows the licensed IP, not the lock type; WISECP support can tell you which one your license has). With a hardware-only lock (`lock_type: none`) an IP change is fine. With an IP or domain+IP lock, a changed public IP is a definitive `IP_MISMATCH`: the panel switches to the suspended state at once (no grace period) until the license is bound to the new address — open the service on your wisecp.com customer area and choose **Reissue License** (or ask WISECP support to update the license's IP), then restart the agent once (`systemctl restart whost-agent`) so its check records the new address. If the hardware itself changes (a new motherboard or network card, a server your provider re-created, re-imaging), the license is refused with a message asking you to reissue it: open the service on your wisecp.com customer area and choose **Reissue License**, then restart the agent once (`systemctl restart whost-agent`) — its start-up check records the new hardware, the panel receives a new installation secret and is active again. If that does not bring it back, contact WISECP support, who can also reset the license's hardware lock.

### Can I move my license to a different server?

Yes. Switch the old server off, open the service on your wisecp.com customer area and choose **Reissue License** — it releases the old server's address and hardware lock. Then install on the new server and activate with the same key. The first installation that checks in after the reissue is the one recorded, so keep the old server off; no waiting period applies.

### Is the activation_secret the same as the license key?

No. The **license key** is the identifier (`WHOST-XXXX-XXXX-...`) you enter on the activation form, and it is the only value a WHost installation needs. The **activation_secret** is an optional per-license setting (`license.activation_secret` in `agent.conf`) that WHost licenses do not use today: the panel's activation form never sends it, the installer writes no `license:` block, and no such value is handed out with a WHost license — your wisecp.com customer area does not show one. Leave it empty.

---

## Compatibility & requirements

### Which operating systems are supported?

Ubuntu 22.04 / 24.04 LTS, AlmaLinux 9, Rocky Linux 9, CentOS Stream 9. The agent's compiled modules need CPython 3.12, which the installer provides on each of these (on Ubuntu 22.04 from the deadsnakes PPA). **Debian 12 is not installable in this release**: it has no Python 3.12 package, so the installer recognises it and stops. The installer also **hard-fails** on every other release — among them Debian 11, the RHEL 8 family, Red Hat Enterprise Linux itself, the version 10 releases of AlmaLinux / Rocky / CentOS Stream and any Ubuntu other than 22.04 / 24.04. See [`docs/operator/supported-os.md`](supported-os.md) for the policy.

### Can I install WHost alongside an existing cPanel / DirectAdmin install?

No. WHost takes ownership of Nginx / Apache / Postfix / MariaDB / PowerDNS / Pure-FTPd. Mixing two control panels on the same host invites configuration drift and is unsupported. Use a fresh server.

### What's the minimum hardware spec?

The installer does not check the hardware. During the beta every supported system was installed and tested on servers with 2 vCPU, 4 GB RAM and a 40 GB disk, which the [installation guide](installation.md) lists as the minimum; smaller servers have not been tested. For production: ≥ 4 vCPU, ≥ 8 GB RAM, fast NVMe (≥ 100 GB SSD). RAM dominates because the FastAPI agent + Nginx + Apache + MariaDB + PowerDNS + Dovecot + Pure-FTPd + PHP-FPM pools all stay resident.

### Is IPv6 supported?

Partly. Nginx and Apache listen on both stacks; the panel and the per-account vhosts include `listen [::]:80` / `listen [::]:443`. Dovecot (IMAP / POP3) listens on IPv6 as well, but the installer configures Postfix for IPv4 only (`inet_protocols = ipv4`), so SMTP is IPv4-only. DNS (PowerDNS) serves the AAAA records you add; the zones the panel creates carry IPv4 (A) records only, because the server IP and IP Management are IPv4-only.

### Does WHost support OpenLiteSpeed / LSWS?

Yes — both as opt-in webservers via the plugin system (Plugins, `/admin/plugins`): **OpenLiteSpeed** (free) and **LiteSpeed Web Server** (the Enterprise edition: 15-day trial or a serial key from LiteSpeed Technologies). Activation moves the accounts' vhosts — primary domains, addon domains and subdomains, with their PHP versions, redirects, Let's Encrypt certificates and suspension state — to the new server and switches PHP to LSAPI. A failed activation is rolled back automatically, and **Deactivate** moves the vhosts back to the previous web server.

---

## Installation & deployment

### How long does a fresh install take?

6–15 minutes: during the beta one installation on each supported system took 6 to 15 minutes on a 2 vCPU / 4 GB cloud server. The installer is fetched with `git clone`; it installs distribution packages (adding third-party repositories where the distribution lacks a package, for example for PHP, Python 3.12 and Rspamd), the agent's Python packages from PyPI into `/opt/whost/venv`, the OWASP Core Rule Set and the signed panel archive, and it compiles the nginx ModSecurity connector from signature-checked source only where the distribution ships no module package (Ubuntu 22.04). Running it again after a failed run completes the installation (finished steps such as the panel download are skipped), but every run generates new API credentials, a new admin password and a new session secret and rewrites `agent.conf` from scratch, which drops the license key and the settings saved from the panel — do not re-run it on a server in use.

### Can I install WHost in a Docker / LXC container?

Officially: no. WHost provisions Linux users, systemd units, cgroup v2 slices, kernel firewall rules, and runs MariaDB / Postfix as real services. LXC works for evaluation but lacks production support. Container support is on the long-term roadmap.

### Can I install WHost behind a reverse proxy (Cloudflare, AWS ALB, etc.)?

Yes for the panel ports (80 / 443), but only Cloudflare is recognised as a proxy. The installer configures nginx to restore the visitor's address from `CF-Connecting-IP` for Cloudflare's address ranges; nginx does not read `X-Forwarded-For` from any other proxy (AWS ALB, your own load balancer), so behind one every request reaches the agent with the proxy's address, and the per-IP rate limits, the admin IP whitelist and the ban after repeated failed signatures then apply to that single address. Note: the HMAC signature covers the raw body, so the proxy in front of `https://<host>/api/v1/` must pass request bodies through byte-for-byte; Cloudflare rewrites bodies for some content types. The agent itself listens on `127.0.0.1:2000` only and is never reached directly from outside — point HMAC clients at the origin's web server (bypassing the CDN) rather than at the agent port.

### Where does WHost store data?

- `/etc/whost/` — agent config (`agent.conf`), license state, account records and other state files (directory `0751`; the files are root-only, mostly `0600`)
- `/opt/whost/agent/`, `/opt/whost/venv/` — the agent's code and its Python environment (root-only)
- `/var/lib/whost/` — runtime state (webhook queue, idempotency cache, etc.)
- `/var/log/whost/` — agent + audit + debug logs
- `/var/www/whost/panel/` — static admin / client frontend bundle
- `/var/whost/backups/` — local backup archives (default `backup.local_path`)
- `/home/<username>/` — per-account home dirs (standard Linux convention)
- `/var/vmail/` — mailboxes
- `/var/lib/mysql/`, `/var/spool/postfix/`, etc. — service-managed data

---

## Multi-tenant & isolation

### How are accounts isolated from each other?

Each account runs as a **dedicated Linux user** (`useradd`) with its own home directory. New accounts get no login shell and are refused by the SSH server; the **SSH / Shell Access** switch gives an account a normal `/bin/bash` login, not a jailed shell. PHP-FPM workers run under the account user. Each account also gets a cgroup v2 slice (`whost-<user>.slice`) carrying the plan's CPU, memory, process and disk I/O limits; the account's Python and Node.js apps run inside it, but PHP is served by the PHP-FPM service each PHP version shares across accounts, so the slice does not cap an account's PHP, and cron jobs and shell sessions run outside it. The plan's disk limit is enforced as a Linux user quota when quotas are active on the root filesystem (the installer turns them on where it can and warns otherwise). Database names and users carry the account's `<username>_` prefix. Mailboxes and forwarders can only be created on the account's own domains (primary, addon domains and subdomains).

### Can a compromised tenant read other tenants' files?

In a default install: no. Per-user POSIX permissions + the PHP-FPM `open_basedir` restriction (the account's home plus the system PHP libraries) + the web servers' symlink-owner checks (nginx `disable_symlinks if_not_owner`, Apache `SymLinksIfOwnerMatch`) + the Pure-FTPd chroot all block direct cross-tenant filesystem access. The agent's own tree (`/opt/whost/agent`) is root-only as well, so a tenant shell cannot read its source, templates or compiled modules. The shared MariaDB instance enforces per-user `GRANT` boundaries (only on databases the account owns).

### How many accounts can a single WHost server host?

There is no hard limit — the agent scales with the kernel and the underlying services. Practical guideline: **50–200 active accounts per server** depending on plan limits, traffic, and email volume. Past 200 accounts MariaDB connection limits and PHP-FPM pool exhaustion start to bite; shard onto multiple servers.

### Can I rate-limit per tenant?

Not per tenant — the rate limits work per client address or server-wide:
1. **API** — the agent limits requests per client IP, by request class (read, write, delete, heavy, auth); there is no per-API-key limit.
2. **Connections** — Firewall → **Rate Limiting** rules ban, server-wide, an address that opens more new connections than a rule allows within its time window (IPv4). **Under-Attack Mode** adds a server-wide nginx `limit_req` while it is on; there is no per-vhost request limit.
3. **Resources** — the per-plan cgroup v2 limits (CPU, memory, processes, disk I/O) on the account's slice, which holds its Python and Node.js apps (see *How are accounts isolated from each other?* above).

---

## Migration from cPanel / DirectAdmin / Plesk

### Does WHost have a migration tool?

Yes — Migration (`/admin/migration`) connects to the source server over SSH (password or key; the source's host key is pinned on first use) and imports accounts from cPanel, DirectAdmin, Plesk, HestiaCP, CyberPanel, CloudPanel or CWP; a WHost source is read through its API with an HMAC key instead. Migration is experimental in the beta: cPanel and DirectAdmin are the sources measured end to end (see [Known Limitations](known-limitations.md)). After a scan you pick the accounts. For each account an SSH migration creates the account with its primary domain and a new random password, copies the primary site's files into `public_html`, imports the account's databases (names with the `<username>_` prefix; database users and grants are not carried over), copies the cron jobs and creates the FTP accounts it finds with new passwords. It does not carry over DNS zones (the new account gets a fresh zone), addon domains and subdomains, or mailboxes: the source's mail folder is only copied into `~/mail/`, and the mailboxes have to be created on WHost.

### How long does a typical migration take?

A 5 GB account with 3 databases migrates in 4–8 minutes (network-bound). The accounts of a job are migrated one after another over a single SSH connection; there is no parallelism setting. Run on a staging WHost server first, validate, then point DNS.

### Will my customers' email keep flowing during migration?

If you're cutting MX records: there will be a TTL-bound gap. Best practice: lower MX TTL 24 h before migration, migrate, create the mailboxes on the new server (the migration does not recreate them) and validate inbound there, then update MX. Postfix on both sides should accept mail for the migration window.

### What about SSL certificates?

Certificates are **not carried over** — issue or upload them again after the migration. Migrated accounts are created with automatic SSL on, so a Let's Encrypt order is attempted right away; it fails while the domain still points at the old server. After the DNS switch, issue Let's Encrypt certificates on the SSL page (`/admin/ssl`) per domain, or for every domain without one with **Secure All Domains**. Custom (paid) certificates are uploaded with **Install SSL** → **Custom Certificate** → **Upload Custom Certificate**.

---

## Backups & data safety

### What does a WHost backup include?

A backup holds up to three parts, chosen together or separately: the account's home files (its sites, and the certificate files kept in `~/ssl`), one SQL dump per database the account owns, and its mailboxes (addresses, password hashes, quotas and the mail itself). The account's configuration — vhosts, PHP pool settings, cron jobs, DNS zones — is not part of a backup. A restore (one action per backup, behind a confirmation, in the admin and the client panel alike) writes back what the backup holds: `public_html`, `tmp`, `ssl`, `mail` and the folders of the account's addon domains and subdomains (not logs, hidden files or the account's `backups` folder), each database re-created from its dump, and the mailboxes with their mail.

### Where are backups stored?

Default: `/var/whost/backups/<username>/` on the WHost server itself (`backup.local_path`). **Strongly recommended:** add a remote destination — FTP, SFTP, Google Drive, Microsoft OneDrive, Yandex Disk or Bunny Storage — on Backups → **Remote Storage** → **Add Destination**, and choose it for a backup or a schedule; clients can add their own destinations in the client panel. Local-only backups die with the server. The server-wide retention (next answer) removes a backup's remote copy together with the local archive.

### How often do automatic backups run?

Only when you schedule them — a fresh install has no backup schedule. Schedules are per account (Backups → **Schedules** → **Create Schedule**; clients can create them for their own account): daily, weekly or monthly at a time of day in the server's local time, with a retention count that keeps that schedule's newest runs (default 5). An account can have up to three schedules unless you change **Max Schedules per Account** on the Backups → **Settings** tab. The same tab's **Retention Days** removes every backup older than that many days — manual and scheduled, remote copies included — once a day; the installer sets it to 30.

### Can I restore a single file from a backup?

Not from the panel: a restore writes back every part the backup holds, and there is no selective restore. For a single file, download the archive (the backup's **Download** action) and take the file from its `files/` folder; as root on the server, the archives are under `/var/whost/backups/<username>/` — `tar -tzf` lists one, `tar -xzf` extracts it to a staging directory, and you copy the file back by hand. Per-file restore UI is on the roadmap.

### Are backups encrypted at rest?

No. There is no encryption option: local archives are stored unencrypted, readable by root only (mode `0600`), and a remote destination receives the same archive. SFTP and the cloud destinations (Google Drive, OneDrive, Yandex Disk, Bunny Storage) transfer over encrypted connections; an FTP destination uses TLS when the server offers it and falls back to plain FTP when it does not. For at-rest encryption on the WHost host, put the backup directory on an encrypted volume (for example LUKS), or choose a remote destination whose storage is encrypted.

---

## Updates & lifecycle

### How are WHost updates delivered?

The agent checks the vendor update service once every 24 hours (the first check runs five minutes after each agent start) and installs only signed packages: the SHA-256 checksum and the release signature are verified before anything is replaced. Settings → Updates shows the offered version; **Check for Updates** asks the vendor at any time, and **Install Update** installs the release a check has offered. Automatic installs are set on its Settings tab: **Automatic Updates** on or off, and the update type — **Security fixes only** (the default), **Patch only**, **Minor** or **All Updates**. While **Allow vendor to push critical updates** is on (the default), updates the vendor flags as mandatory are installed whatever the update type; **Security fixes only** installs nothing else. Installs happen at the next daily check, not the moment a release is published, and with Automatic Updates off nothing is installed on its own. The **Update Channel** is Stable or Beta; the beta channel serves only licenses WISECP has admitted to the beta programme. Details: [Update and patch flow](update-flow.md).

### How do beta releases reach my server?

During the beta every WHost release is a beta release (`1.0.0-beta.N`) published on the `beta` channel. A new installation asks for that channel, and the licence must also be admitted to the beta programme: an approved beta request comes with an admitted licence ([Getting Started](getting-started.md)). A licence that is not admitted is answered from the stable channel and is offered no release; the Updates page then shows the note "Beta programme: this licence is not admitted, the stable channel was used". Channels and the programme in detail: [Update Flow](update-flow.md).

### What if an update breaks my server?

Before replacing anything, an install archives the agent code (unless **Create backup before update** is switched off; the newest three archives are kept). A run that fails after files were replaced puts back everything it replaced — agent code, panel, service unit, Python environment and integrity manifest — without a restart, and the History tab records it as rolled back with the reason. A release that installs but does not start is caught by a post-update check: it waits 20 seconds, then asks the agent's health route for up to 90 seconds, and if the new release never answers it restores the previous one and starts the service again. There is no manual rollback button; only an install cut off at the wrong moment (for example by a power loss) needs the previous release put back by hand from the `.old` copies — see [Update and patch flow](update-flow.md). A release is installed on WISECP's test servers first and can be offered to listed servers before it is widened to everyone.

### How long is the v1 API supported?

The API is versioned by path, and `/api/v1/` is the only version today (this is the API version, not the product version). Within v1, endpoints and fields are never removed or renamed; changes are additive — see [`docs/developer/versioning-policy.md`](../developer/versioning-policy.md). If a `v2` ever ships, it runs in parallel under `/api/v2/`: at least 3 months as a beta, then at least 12 months of deprecation during which v1 keeps working and answers with `Deprecation` / `Sunset` headers — at least 15 months from the v2 announcement to the removal of v1. No release forces a client to migrate.

### Does WHost auto-update OS packages too?

No — OS packages are checked and reported automatically, but installing them is your decision. With **Check OS packages periodically** on (the default) the agent refreshes the pending list every 24 hours, and **Notify on OS security updates** sends a panel notification when the number of pending security updates grows. Settings → Updates → OS Packages lists the pending packages and applies them on request with **Apply Security Updates** or **Apply All Updates** (the API can also upgrade named packages). The agent runs `apt-get` / `dnf` itself, without a shell, and does not filter out kernel packages; when the OS reports that a reboot is needed, the admin topbar shows **Reboot required** and the OS Packages tab offers **Reboot Now**.

---

## Security & hardening

### How do I rotate the API key?

Settings → **API Access** (`/admin/settings/api-access`) → **Create API Key** (name, optional allowed IPs, permission scope) → copy the key and the secret from the **API Key Created** dialog (the secret is shown once) → switch your integration to the new pair → **Revoke Key** on the old one (or **Delete Key** to remove it). A key's secret cannot be rotated in place; a new key replaces the old one.

### Where are secrets stored?

`agent.conf` holds them at rest in plain text, protected by `mode 0600`, root-only access — as are the other root-only files in `/etc/whost/`; API key secrets are the exception and are stored encrypted, and `agent.conf` keeps the admin password as a bcrypt hash. Sensitive credentials are protected in memory at runtime so they aren't recoverable from a casual process dump.

---

## Performance & sizing

### How many requests per second can the agent handle?

The FastAPI agent is async + uvloop-backed. Load test on a 4 vCPU server: 1,100 mixed REST requests over 20 concurrent connections, **0 % error rate**, p95 < 80 ms. Real-world steady state on a busy 100-account server: 50–150 RPS sustained without saturation.

### Why is the first request slow?

It should not be: the agent finishes its start-up work (module load, integrity verification, baseline capture, license check) before it opens its port, so the first request is served like any other. What you can notice is the restart itself — while the agent starts, the panel and the API are unavailable (about 15–20 seconds on a small server).

### Can I run multiple WHost agents on one host?

No — the agent binds to port 2000 and owns the host's services (Nginx, Postfix, etc.), so there is one agent per server. For multi-tenant scaling, shard accounts across multiple servers, each with its own license. WHost has no built-in standby or replication; for recovery, keep backups on a remote destination.

### How do I scale beyond one server?

WHost is a **single-server control panel** by design. There is no master / slave clustering. For larger deployments, partition customers across multiple WHost servers and centralise billing / provisioning in your billing system, which drives each server through its API.

---

## Integration with billing platforms

### Is WHost tied to WISECP?

No. WHost is **developed by WISECP LLC**, but there is no WISECP-specific integration: WISECP and every other billing system drive WHost through the same generic agent API. Any billing system that can speak HTTP + HMAC can drive WHost: provision accounts, suspend on non-payment, terminate, package change.

### Is there a WHMCS / Blesta / custom module?

No — WHost ships no billing-specific module (for WHMCS, Blesta or WISECP); integrations are written on the billing side against the generic API. Glue code lives on the billing side. The PHP SDK (`wisecp/whost-php-sdk`, a download from this site) covers the admin API with 403 methods and is the recommended starting point; its `examples/03-billing-integration-pattern.php` shows the order hooks such a module needs. See the [PHP SDK page](../developer/sdk-php.md).

### Can I use webhooks instead of polling?

Yes. The agent dispatches **25 dot-notation events** (account / domain / ssl / backup / database / email / ftp / dns / plan) to operator-registered subscribers. Signed HMAC, retry-with-backoff, dead-letter on persistent failure. See [`docs/developer/webhooks.md`](../developer/webhooks.md).

### How do I prevent duplicate billing-triggered provisioning?

Pass `X-Idempotency-Key: <uuid>` on every mutating call. Same key + same body within 24 h returns the original response; same key + different body returns `409 IDEMPOTENCY_KEY_REUSED`. Standard partner pattern: one UUID per logical order, reused across all retries of that order.

---

## Resellers & multi-admin

### Can I create reseller accounts?

Yes — `/admin/resellers` creates reseller accounts (any account can also be turned into one from its edit form) with per-reseller limits: max accounts, total disk, total bandwidth, max domains, databases, email and FTP accounts, with or without overselling. The limits are checked when a sub-account is created or its package changes. Monthly traffic is not measured in this release, so the bandwidth limit only caps the sum of the sub-accounts' plan allowances (with overselling on, it never blocks). An optional ACL plan (**ACL Lists**, `/admin/resellers/acl`) decides which operations the reseller may perform; a reseller without one is unrestricted. Resellers cannot impersonate one another's accounts.

### Can a reseller see the parent admin's data?

No. Resellers sign in to the client panel, never to the admin panel, which accepts only the single admin identity. Reseller scope is enforced server-side: a reseller session reaches only the client API, and every request checks that the account belongs to the reseller and that its ACL plan allows the operation. Resellers see only their own accounts.

### How do I add a second admin user?

Currently WHost supports **one admin user per install**. Multi-admin is on the roadmap. As a workaround, use API keys (Settings → **API Access**, `/admin/settings/api-access`) to delegate scriptable access without sharing the admin password; an API key cannot manage API keys or change credentials — those need the admin's browser session.

### Can a reseller use the API directly?

Yes, when its ACL plan grants **API Access** (of the built-in plans only Full Access does; a reseller without an ACL plan is unrestricted). The reseller creates its own keys in the client panel (user menu → **API Access**, up to 10 keys); the admin cannot issue one on its behalf, but sees, revokes and deletes them under Settings → API Access. A request signed with such a key acts as the reseller on the client API (`/api/v1/client/*`), with the same ownership checks and ACL plan as its browser session — never on the admin API.

---

## Support & escalation

### Where do I report bugs?

Open a support ticket from your wisecp.com client area (or e-mail `hello@wisecp.com` when you cannot) with the bundle described in [`docs/operator/troubleshooting.md → When to escalate`](troubleshooting.md#17-when-to-escalate). For security issues: see the disclosure section there.

### Is there a public roadmap?

A public roadmap and release notes are published with each version on [https://wisecp.com](https://wisecp.com).

### Can I contribute / submit patches?

WHost source is proprietary, and so is the PHP SDK (see the LICENSE in its archive); neither takes outside patches. Send bug reports and feature requests through the same support channel.

### What's the SLA for support?

Per your WISECP service agreement. WHost itself does not ship a free SLA — production deployments should hold an active support contract.
