Settings

Updated Oct 5, 2026 Markdown

Settings at the bottom of the sidebar (or All Settings in the topbar's gear menu) opens the settings hub. Its tiles come in four sections: Server — General, Security, IP Management, Plugins (§10); Hosting — PHP (§11), Spam Filter, Banned Words; Panel — Notifications (§15), Whitelabel, Updates (§9), License; Integrations — API Access, Webhooks (§14). Profile opens from the account menu.

Profile

Email, language preference, avatar (≤ 2 MB, JPEG/PNG/WebP by MIME type and magic bytes; SVG and HTML are refused; the upload route allows five attempts per minute). Automatic (the default) keeps the language you sign in with; an explicit choice switches the panel to that language on every login and accepts every shipped locale, region variants and three-letter tags included (pt-BR, zh-TW, fil, …). Changing the recovery address, the language or the profile picture writes a settings_updated audit row; a save that changes nothing writes none. Password change invalidates other sessions; the new password is at least 8 characters and at most 72 bytes (UTF-8). Two-factor enrollment offers an authenticator app (TOTP) or a code e-mailed to the recovery address; the e-mail factor follows that address when you change it here, so the next code always goes to the current address, and switching 2FA off clears it. E-mail codes are sent through the server's local mail relay unless admin.two_factor.smtp_* in agent.conf names another SMTP server.

Security

  • Admin IP whitelist (CIDR list or empty for any). Saving a changed non-empty list (an entry added or removed) rotates the session secret: every admin and client browser session ends and has to sign in again. Saving the page with the list unchanged (for example after editing only the session timeout) keeps every session. API keys are not affected. Values that equal the stored ones are dropped before anything is written, so an unchanged save writes no configuration and no audit row; a refused value answers 422 VALIDATION_ERROR like the General page (400 stays for the self-lockout guard), and text where a number or a switch is expected is refused.
  • 2FA enforcement (off / TOTP / email / both). While the switch is on, the login and session endpoints report requires_2fa_setup (with the demanded method) for an identity that has not enrolled a second factor, and the panels act on it: such a sign-in lands on the enrolment page (admin: Settings › Profile, client: Settings › Security) with the setup dialog open and a notice explaining why; every other panel page redirects there until the second factor is active (signing out stays possible). When the switch demands one method, the dialog offers only that method; both leaves the choice to the user. Identities that already have a second factor are not affected.
  • SSH config tab — port, root login, password / key auth, allowed IPs (writes back to sshd_config; reload requires manual confirmation). The port must be free: the ports the panel itself holds (80, 443, 2000) and any port another service is already listening on are refused with PORT_IN_USE, because sshd -t does not catch a bind conflict. If sshd fails to come back on the new settings, the previous SSH configuration, firewall rule and fail2ban port are restored and the save reports a warning.
  • Root password — changes the Linux root password. Requires an admin browser session: HMAC API keys are refused with HMAC_FORBIDDEN_FOR_CREDENTIAL_MUTATION, like every other credential change. Control characters (line breaks) are refused.
  • Spam thresholds (Rspamd reject / add-header / greylist scores) are not on this page: they are set on the Spam Filter page (Settings → Spam Filter, Overview & Config tab). There too a failed read of the scores shows an error state instead of the form.
  • A failed read of these settings (an error, or a rate-limit answer) shows an error state with a Retry button instead of the form, so a Save can never write the defaults, or the answer kept from an earlier visit, over the stored settings.

General

Hostname, advertised server IP, timezone, nameservers, default PHP/web server, MariaDB / FTP / mail tuning, SSL defaults, default language and the client-panel feature switches. The server IP must be a routable unicast IPv4 address (loopback, unspecified, broadcast, multicast, link-local, reserved and zero-padded forms are refused with INVALID_IP / VALIDATION_ERROR); changing it rewrites, in every zone, the A records and SPF entries that carried the old address (a DNS failure is listed in the answer's dns_errors and does not stop the change), gives the accounts that used the old address the new one, and regenerates the panel vhost; the account sites listen on every address, so their vhosts are left as they are. It does not add or remove addresses on the machine — that is IP Management. IP Management is a page of its own (/admin/ip-management, opened from the IP Management tile on the Settings page, not from General; IPv4 only): the list shows every address the host carries plus stored records the host no longer carries, marked Not bound — they are never offered to accounts. Adding an address binds it at once and persists it through netplan (Debian) or nmcli connection modify (NetworkManager, RHEL); when the persistence step fails the answer carries a warnings list: the address is bound now but will not survive a reboot. The configured primary address, the address the host's default route uses and the first address of the default interface cannot be removed, nor can an address still assigned to an account (the count is in the message). A Not bound record can still be updated and deleted; only an address that is neither bound nor stored answers 404 NOT_FOUND on update and delete. The audit rows carry the operator and their address, and changing the advertised server IP refreshes the account index the list uses.

Values sent as text where a number or a switch is expected ("10000", "yes") and fields the form does not define are refused with 422 VALIDATION_ERROR; nameservers are filled in order (an ns3 with an empty ns2 is refused instead of moving up a slot) and the MariaDB buffer sizes take a non-zero K/M/G value (0K is refused). A save that changes nothing writes no configuration, touches no service and leaves no audit row; the settings_updated row of a real change names only the changed fields (client_features.<name> for a feature switch) and carries the operator and their address. The agent's reason for a refused value reaches the toast, a 0 can be typed into the numeric fields whose minimum is 0 (Keep-Alive), and a failed read shows the error view with Retry rather than a form of defaults. Two FTP fields the API accepts, ftp_bandwidth_limit and ftp_passive_mode, are stored only: the save keeps and echoes them, but no Pure-FTPd directive is written for them and the form does not show them.

API Keys

Create new key (with optional IP allowlist), revoke, delete, view access logs (last 100 calls per key with timestamp, IP, endpoint, status). The secret is shown once at creation time — the operator must copy it immediately. Default API Key is the installer's pair from agent.conf; revoking or deleting it retires it for good. A key always carries at least one scope: creating or updating a key with an empty scope list answers 422 VALIDATION_ERROR.

Reseller keys. A reseller whose ACL plan grants API Access mints its own keys from the client panel (Settings → API Access). Such a key is bound to the reseller account: the Owner column names it (server-wide keys show Server), its scope is fixed to Reseller (client API) and cannot be widened, and every request signed with it is served as that reseller on /api/v1/client/* — the same ownership checks and ACL plan as the reseller's browser session, never the administrator API, whatever session cookie the request also carries. Switching API Access off in the plan refuses both minting and every request signed with an existing key; suspending the account does the same. The operator sees, revokes and deletes reseller keys here like any other key; a reseller holds at most 10.

Whitelabel

Branding overrides: company name, logo (light + dark), favicon, color theme, the background video of the sign-in pages. Gated behind the whitelabel license addon. The colours, the company name and the address of each logo are propagated to the static frontend via /var/www/whost/panel/config.json so the next page load picks them up without rebuilding; the logo images themselves are separate files (below), so config.json stays a few hundred bytes whatever the logos weigh.

The brand follows the addon: when a licence check finds it granted or withdrawn, config.json is rewritten at once, so the next page load shows or drops the brand without an agent restart; the account pages the agent writes (a new account's default page, the suspended page) take the published colours only while the addon is licensed and the feature is on. Purchase Addon and Renew Now open the WHost product page (https://wisecp.com/whost). With the feature on and hide_login_branding set (the default), the sign-in screens carry the company logo and name — the administrator form's subtitle names the company too; each screen paints with its form at once, and the logo and name appear as the page finishes loading, never the WHost defaults first. The setting is the Brand the login pages switch at the top of the Login Page Video section; switched off, the sign-in screens keep the WHost logo and name while the panels stay branded. An addon the licence service still reports as active but whose expiry date has passed is treated as expired by the panel itself: the page shows the expired banner with Renew Now, and the brand leaves the published pages at the next licence check (the publisher normally suspends a lapsed addon first; this is the panel's own safeguard).

The colour theme paints both panels in both themes, and the admin and client sidebars share one look. In the light theme the sidebar colour tints both sidebars: they stand on a dark ground mixed from it, so the white menu text stays readable whatever the colour. The dark sidebar colour gives its hue and saturation to the dark theme's page background, cards, muted surfaces and lines, so the page reads as one scale; in the dark theme both sidebars stand on that same card surface, slightly see-through over a blur. Those surfaces stay dark enough for the panel's secondary text to keep a 4.5:1 contrast: with a lighter dark sidebar colour (for example one picked up from a mid-tone logo) they take a darker step of the same hue instead of the sidebar's own lightness. The primary and secondary colours draw a short glow behind the logo in the top corner of both sidebars (top right in right-to-left languages); it takes the light-theme pair in both themes and looks the same in each. Text on the primary and secondary colours (buttons, badges, tooltips) stays white while it keeps a 4.5:1 contrast; on a lighter brand colour it turns to a dark shade of the same hue.

The dark surfaces — the sidebar and its collapsed icon — show the dark logo and the dark favicon; when only the light variant is uploaded, the light one stands in (inside a light frame when it is too dark for the sidebar), and the WHost mark appears there only when neither variant is uploaded. When no favicon is uploaded at all, the browser tab and the collapsed sidebar show a generated mark instead of the WHost icon: the first letter of the company name (of the server name when no company name is set) on the primary colour. If the page cannot read the addon status or the settings (a limiter answer, a network error), it shows an error with Refresh instead of the purchase banner and a locked form; the dashboard's purchase prompt likewise opens only on a real "not licensed" answer.

What an uploaded logo may contain. The file type is decided by the leading bytes, not by the declared content type: JPEG, PNG, WebP and SVG are accepted, anything else is refused with 415, and the ceiling is 2 MB. An SVG is rewritten before it is stored — XML entities are refused outright (no file:// reads, no expansion bombs), and <script>, <foreignObject>, on* handlers, javascript: links, animations that rewrite a link target (under any prefix) or carry a script or outside address in any of their values, stylesheets and style or presentation attributes that pull a second document (read as a browser reads CSS, escapes decoded — only a url(#…) pointing inside the file stays), xml:base, and links to anything other than a part of the same file or an embedded PNG / JPEG / GIF / WebP image are removed. Ordinary shapes, animation and styling survive. An SVG may open with an XML declaration, a comment of any length or a doctype — the root element decides the type.

How a logo is stored. A JPEG, PNG or WebP is shaped before it is stored: a logo is scaled down to fit 512 px wide by 160 px tall — the panel shows a logo at most 160 px wide and 48 px tall, and this covers the sharpest screens (proportions kept, a smaller image is never enlarged, the format stays the same), and a favicon becomes a square PNG of at most 256 px — a non-square image is centred on a transparent square, nothing is cropped. The camera orientation of a photo is applied. A small image that already fits (up to 256 KB) keeps its pixels byte for byte; an animated logo that fits keeps its animation, a larger one keeps its first frame. What a camera or an editor wrote beside the pixels (EXIF, XMP, text comments: place, device, date) is removed from every stored image, logos and sign-in covers alike, since the sign-in page shows them to anyone; the colour profile stays. An image above 25 megapixels is refused from its header with 400 IMAGE_DIMENSIONS_TOO_LARGE before anything is decoded, and a damaged or truncated file with 400 INVALID_IMAGE. The upload answer reports each file's size before and after (optimized). SVG is kept as a vector. The stored file is served by the panel's web server at /branding/<name>; the name changes whenever the image changes, so browsers keep the file for a year and pick up a new logo at the next page load. Replacing or removing a logo, and the reset, delete the old file. The files live under /var/lib/whost/branding/ on the server — include that folder in host backups.

Login page video. The Login Page Video section replaces the background video of the administrator and of the client sign-in page, one card each (the badge reads Default or Custom; the preview plays on hover or click). Upload Video takes an MP4, MOV (as phones and cameras record), WebM or MKV file and prepares it in the browser before it is sent; whatever it came in, the stored file is an MP4. An H.264 video that fits 5 MB is only repackaged (a MOV or MKV becomes an MP4 without re-encoding). One in another codec that fits (HEVC from a phone, VP9 from a WebM, for example) is converted to H.264 at about its own picture quality — at most three times its bitrate, as H.264 needs that much more for the same picture — and is never grown to fill the 5 MB; the card reads Converting the video and the notice says it was converted to MP4. A larger one is re-encoded as H.264 — scaled into 1920 × 1080 (1080 × 1920 for an upright video, the phone's rotation applied), at most 30 frames a second, aimed close to 5 MB: a browser's encoder often stays well under the bitrate it is given (or runs over it), so a pass that lands under about 4.25 MB or over 5 MB is encoded again with the difference it measured, and the card reads Fine-tuning the video during that pass. The encoded width is a multiple of 16 (a hardware encoder given a width that is not a multiple of four loses most of the picture's detail), and a key frame is written every 10 seconds, which leaves more of the 5 MB to the picture. Within 5 MB a clip of 10–20 seconds keeps most of its detail; a long one, or one with fast motion and fine texture everywhere, loses visibly — a shorter clip of the same scene looks better than the whole of a long one. A video so long that even 640 × 360 would drop below about 300 kbit/s is cut to the length that fits, and the panel says how many seconds it kept. Either way the sound track and the file's descriptive tags (camera, place, date) are dropped — the sign-in page plays muted. The cover the page shows until the video plays is taken from the video's first frame, so the picture does not jump when playback starts; Change Cover replaces it with a JPEG, PNG or WebP of your own (scaled into the same box in the browser and again on the server, 2 MB at most), and a new video brings its own first-frame cover again. Restore Default removes the video and its cover and the page shows the default video. Compression needs a browser with WebCodecs (current Chrome, Edge, Firefox and Safari); elsewhere an MP4 of at most 5 MB is uploaded as it is, without a cover, and a larger one, or a MOV, WebM or MKV, is refused. The agent stores the video as it arrives, after reading its structure (no frame is decoded on the server), with its descriptive tags, XMP packet and creation times blanked — an MP4 uploaded as it is loses them on the server too: it must be an MP4 whose video track is H.264 (415 UNSUPPORTED_MEDIA_TYPE names the codec otherwise) of at most 5 MB (400 FILE_TOO_LARGE); a damaged file answers 400 INVALID_VIDEO, a cover sent for a page that has no video of its own 400 LOGIN_VIDEO_REQUIRED, and a new video sent without a cover drops the old cover. The video and the cover are files under /branding/ like the logos and follow the addon and the feature switch the same way: when the addon lapses or whitelabel is turned off, both sign-in pages play the default video at the next page load. A sign-in page loads its video after the panel script has read the branding, so a host with its own video never downloads the default one; until then the cover is shown.

Every change — a settings save, a logo upload, a logo removal, a login page video upload or removal, a reset — writes a settings_updated audit row (scope: whitelabel); a save that changes nothing writes none. Colours are HSL triples within range (hue 0–360, saturation and lightness 0–100) and the two switches are booleans ("yes" is refused). Removing a logo that is not set answers 404 LOGO_NOT_FOUND, removing a login page video that is not set 404 LOGIN_VIDEO_NOT_FOUND. While the addon is unlicensed or the feature is off, the form is disabled for the keyboard as well as the mouse; while the addon is unlicensed the agent refuses the settings save, a logo or login page video upload or removal and the reset with 403 LICENSE_ADDON_REQUIRED, so nothing the panel will not publish can be stored (the values already stored stay as they are and the public branding read stays inactive). A limiter answer on any save is reported as an error, and the colour fields fall back to the stored values when their auto-save is refused.

Audit Logs

Every authentication, mutation, and admin action lands in /var/log/whost/audit.jsonl and is surfaced on this page with filters (actor, event, time range). Client-side identity events are included: client login/logout and 2FA challenges, plus password changes (including resets through the mailed link), 2FA enable/disable, backup-code regeneration and recovery-email changes made from either panel. Append-only; past 10,000 entries the oldest are moved to audit.jsonl.1 beside it (an archive past 50 MB becomes .2, replacing the previous one) and the live file keeps the newest 8,000 — the page reads the live file.

Banned Words

Wordlists of banned terms. The lists are enforced: an account name, a primary domain, an addon domain or a subdomain that carries a banned word is refused with 403 BANNED_WORD (the answer names the word and the list) when it is created or changed. Matching is case-insensitive and by substring: the value and the parts it splits into at ., -, _, / and @ are compared with every word of every enabled list, so malware also matches antimalware-tools — keep the lists' words specific. Eight built-in lists ship with the panel (five enabled); a built-in list can be switched off and edited but not deleted (422). The Check Value box asks the same check the gates run. A list file under /etc/whost/wordlists/ that cannot be read is named in a notice on the page and is not applied.

Endpoints used: GET/POST /banned-words, GET/PUT/DELETE /banned-words/{wordlist_id}, POST /banned-words/check.

Still Need Help?

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