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.

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:
| Variable | Default | What it changes |
|---|---|---|
BRANDING_NAME | ServerAvatar | The browser tab title, and the product's name inside translated sentences |
BRANDING_LOGO | ServerAvatar wordmark | The sidebar logo in light mode |
BRANDING_LOGO_DARK | ServerAvatar wordmark | The sidebar logo in dark mode |
BRANDING_ICON | ServerAvatar mark | The compact logo, light mode |
BRANDING_ICON_DARK | ServerAvatar mark | The compact logo, dark mode |
BRANDING_FAVICON | ServerAvatar mark | The browser tab icon |
BRANDING_PRIMARY_COLOR | #076aff | The 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.
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:clearRestart 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-frontendSubstitute 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.
- The backend reads the environment into
config/branding.php. - It serves the result, unauthenticated, at
GET /api/branding. - 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_NAMEbecomes 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_COLORis 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://orhttps://URL, or a root-relative path like/logo.png. Protocol-relative//host/logo.png,data:andjavascript:URLs are rejected and never reach ansrc. - 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:
| Artifact | With the default slug |
|---|---|
| Application directory | /var/www/panel |
| System account | panel |
| PHP-FPM unit and socket | panel-fpm.service, /run/php/panel-fpm.sock |
| Frontend and queue units | panel-frontend.service, panel-queue.service |
| Web server vhost | panel.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=lempThe 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_SLUGis 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.