ServerAvatarDocs
Reference & troubleshooting

Branding & white-labelling

Put your own name, logos, favicon and accent colour on the panel with seven environment variables — and name every file on the server with your own slug.

OSS Panel is built to be re-branded. Nothing in the product assumes its own name is the one your customers should see, and the branding is resolved in exactly one place rather than scattered across templates.

The top of the panel: the product logo in the sidebar header, with the language switcher, theme toggle and account avatar in the header bar on the right

Not the same thing as the White-Label product

This page is about re-branding this panel — one server, one set of environment variables. ServerAvatar's separate White-Label product is a reseller platform, which is a different thing entirely.

The seven values

They live in the backend's .env, at /var/www/panel/backend/.env:

VariableDefaultWhat it changes
BRANDING_NAMEServerAvatarThe browser tab title, and the product's name inside translated sentences
BRANDING_LOGOServerAvatar wordmarkThe sidebar logo in light mode
BRANDING_LOGO_DARKServerAvatar wordmarkThe sidebar logo in dark mode
BRANDING_ICONServerAvatar markThe compact logo, light mode
BRANDING_ICON_DARKServerAvatar markThe compact logo, dark mode
BRANDING_FAVICONServerAvatar markThe browser tab icon
BRANDING_PRIMARY_COLOR#076affThe accent colour the whole theme is generated from

That is the complete list. There is no branding screen in the panel and no database table behind it — which is the point: a deployment sets these once and the panel is theirs.

Change the brand

Edit the backend .env. Add only the values you want to change; anything you leave out keeps its default.

/var/www/panel/backend/.env
BRANDING_NAME="Acme Hosting"
BRANDING_LOGO="https://assets.example.test/acme-logo.png"
BRANDING_LOGO_DARK="https://assets.example.test/acme-logo-dark.png"
BRANDING_FAVICON="https://assets.example.test/acme-icon.png"
BRANDING_PRIMARY_COLOR="#7c3aed"

Clear the backend's config cache, so the new values are read rather than the compiled copy.

cd /var/www/panel/backend
php artisan config:clear

Restart the frontend. It caches the branding response for an hour, so without this the old brand keeps rendering until the cache expires on its own.

systemctl restart panel-frontend

Substitute your own slug if you installed with one — the unit is ${PANEL_SLUG}-frontend.service.

How it reaches the browser

Worth knowing, because it explains the one-hour delay and where to look when a value does not take.

  1. The backend reads the environment into config/branding.php.
  2. It serves the result, unauthenticated, at GET /api/branding.
  3. The frontend fetches that once and re-validates it every 3600 seconds, then merges it over the defaults and renders.

You can check what the backend is actually publishing at any time:

curl -s https://api.example.test/api/branding
{
  "branding": {
    "name": "ServerAvatar",
    "logo": "https://app.serveravatar.com/logo/SaLogoDark.png",
    "logo_dark": "https://app.serveravatar.com/logo/dark-logo.png",
    "icon": "https://app.serveravatar.com/logo/logo-sm.png",
    "icon_dark": "https://app.serveravatar.com/logo/dark-logo-sm.png",
    "favicon": "https://app.serveravatar.com/logo/logo-sm.png",
    "primary_color": "#076aff"
  }
}

If that response already shows your brand but the panel does not, the frontend is still serving its cached copy — restart it.

What the panel does with each value

  • BRANDING_NAME becomes the page title: a page sets a plain title and the brand is appended, so you get Dashboard · Acme Hosting. It is also substituted into the sentences the product writes about itself — "Update Acme Hosting itself. Hosted applications stay online; only this panel restarts."
  • BRANDING_PRIMARY_COLOR is not used as-is. A full palette is generated from it and injected as a stylesheet in the page head, so buttons, links, focus rings and charts all move together. Any CSS colour the panel can parse works; hex is the conventional choice.
  • The logo pair and icon pair are light/dark variants. Set both, or the panel falls back to the default for the mode you skipped.

Rules the values must satisfy

Each field is validated on its own, and one bad value never discards the others — it falls back to its default while the rest of your branding applies.

  • Assets must be an absolute http:// or https:// URL, or a root-relative path like /logo.png. Protocol-relative //host/logo.png, data: and javascript: URLs are rejected and never reach an src.
  • The colour must be one the panel can actually read. An unparseable value would otherwise drop the generated theme, so it falls back to #076aff.
  • An empty name is not a name. BRANDING_NAME= with nothing after it is a set variable, so it resolves to the default rather than to an empty string.

Naming the server itself: PANEL_SLUG

Branding covers what a customer sees in the browser. PANEL_SLUG covers what they would find if they logged into the server over SSH.

It is an installer variable, defaulting to panel, and every artifact the installer creates is named from it — nothing carries a product name:

ArtifactWith the default slug
Application directory/var/www/panel
System accountpanel
PHP-FPM unit and socketpanel-fpm.service, /run/php/panel-fpm.sock
Frontend and queue unitspanel-frontend.service, panel-queue.service
Web server vhostpanel.conf
Install log/var/log/panel-install.log

So a reseller installs with their own slug and the server looks like theirs throughout:

sudo PANEL_SLUG=acme bash install.sh --stack=lemp

The variable has to reach the script itself, so set it on the sudo command rather than before it — and download the installer first, since a piped script is read by a bash that your shell's variables do not reach either.

This is enforced, not just intended

The product's own test suite fails the build if an upstream brand name appears in anything written onto a customer's server — cron files, Fail2ban config, a site's .env, a systemd unit — or anywhere in the installer. config/branding.php is the single exemption, because being overridable is the whole reason it exists.

Caveats

  • PANEL_SLUG is an install-time decision. Changing it afterwards means renaming the account, the directory, every unit and every config that points at them. Pick it before you install.
  • The branding endpoint is public. It has to be — the login page needs a logo before anyone has signed in. Do not put anything confidential in these values.
  • Asset URLs are fetched by the visitor's browser, not proxied by the panel. Host them somewhere your customers can reach, and on HTTPS, or the page will show mixed-content warnings.
  • There is no per-user or per-tenant branding. One server, one brand.

On this page