Skip to content

White label ​

A Mankomail instance can carry another brand than its own: your name, your logos, your colors. There are two ways to set it.

  • Self-hosted: environment variables (BRAND_*), read at boot.
  • Linked to a control plane (a fleet of instances operated together): the brand configured in the control plane's back office, received by the instance and applied without a restart.

When both exist, the control plane wins field by field: a field it does not define keeps the environment value, and otherwise the product default.

Where the brand shows ​

ElementWhere it appearsDefault
NameSidebar, sign-in and invitation pages, browser tab title, system emailsMankomail
Logo (light, dark)Sidebar, sign-in page. A logo replaces the monogram and the name text next to itThe monogram
FaviconBrowser tabThe monogram, drawn in the primary color when there is one
Primary colorThe theme accent: primary buttons, active navigation item, links, focus ringThe theme's accent
Accent colorSign-in page panel—
Help linkSign-in page, member menu, suspension bannerNone
“Powered by Mankomail”Sign-in page, system emails. Shown only when the brand name differs from the product nameShown
Sign-in page text and imageSubtitle and left panel of the sign-in pageThe product text, no image
Email sender name and footerApproval request emailsThe brand name, no footer
Custom domainLinks generated in emails (approval buttons, invitation links)PUBLIC_BASE_URL

The last three rows can only be set from a control plane.

Colors stay readable ​

A brand color is not always readable as an interface color: a dark red is fine on a light page and unreadable on a dark one, a pale yellow the opposite. The instance keeps the hue of the primary color and recomputes its lightness for each of the three themes, in light and in dark mode, so that text in the accent color stays at 4.5:1 against the page, button labels stay readable, and the focus ring stays visible. The color you see may therefore be slightly lighter or darker than the one you set.

The computed colors are kept in the browser, so that the next page load shows them from the first frame.

Self-hosted: environment variables ​

Set the variables in .env, then recreate the application container:

bash
BRAND_NAME="Acme Mail"
BRAND_LOGO_URL=https://cdn.acme.example/logo.svg
BRAND_LOGO_DARK_URL=https://cdn.acme.example/logo-dark.svg
BRAND_FAVICON_URL=https://cdn.acme.example/favicon.png
BRAND_PRIMARY_COLOR=#7A1F35
BRAND_ACCENT_COLOR=#FFE680
BRAND_SUPPORT_URL=https://help.acme.example
BRAND_HIDE_POWERED_BY=false
bash
docker compose -f compose.reference.yaml up -d app
  • Images must be reachable by the users' browsers. Use https URLs: the page's security policy allows https: images, plus the exact origin of an http: URL set in these variables.
  • An invalid value (a color that is not #RRGGBB, a malformed URL) is ignored with a configuration: line in the boot log; the default applies.

The full list is in Environment variables.

Linked to a control plane ​

A control plane is a separate service that operates a fleet of instances (one per customer organisation): it receives their usage, sends them their brand, plan and entitlements, and can suspend them. The instance only makes outgoing HTTPS calls; nothing ever connects to it.

The link is on only when the three variables are set together:

bash
CONTROL_PLANE_URL=https://api.example.com/api/instances/v1
CONTROL_PLANE_INSTANCE_ID=ins_01k6x…
CONTROL_PLANE_SECRET_FILE=/run/secrets/control_plane_secret

Without them, the instance calls nothing and sends nothing anywhere. If only one or two are set, the link stays off and the boot log names the missing one.

What the instance sends and receives ​

Every call is signed with the shared secret (HMAC-SHA256 over the method, path, timestamp, a single-use nonce and the body). The machine clock must be within five minutes of real time: run NTP.

CallFrequencyContent
HeartbeatEvery minuteVersion and health: database, pending migrations, job queue delay, mailboxes in error
UsageEvery five minutesHourly totals: executions and steps by final status, emails received and sent by provider, connected mailboxes, active members (seen in the last 30 days), AI tokens and cost by provider and model, storage, API calls
ConfigurationEvery five minutes, and as soon as the heartbeat announces a changeBrand, plan, entitlements, instance status

Usage is counted from the instance's own database. It carries no email content, no address and no subject: only counts.

When the control plane is unreachable ​

The instance keeps working:

  • the last valid configuration stays applied (it is stored in the database);
  • failed calls are retried with an increasing delay, up to 30 minutes;
  • usage hours that were not acknowledged stay queued and are sent when the link comes back, oldest first. Each hour is reported as a total that replaces the previous one, so sending it twice never counts it twice.

Suspension ​

When the control plane suspends the instance, it switches to read-only:

  • every user sees a red banner explaining the situation, with the help link when there is one;
  • the API refuses changes with the error instance.suspended (signing in and out still work);
  • incoming webhooks receive 503 with Retry-After, so that the sender retries later instead of losing them;
  • workflows, synchronisation and sending are paused. Nothing is lost: jobs stay queued and resume when the suspension is lifted.

Plan and entitlements ​

The plan and entitlements received are visible to administrators and readable by the instance, but they do not restrict any feature yet. The quotas set in environment variables still apply.

Checking the result ​

Administration › Instance (administrators only) shows:

  • whether the link is configured, the announced status, and for each call its last success and last error, in plain words;
  • the number of usage hours waiting to be sent;
  • the plan and entitlements received;
  • every brand field with its value and its origin (control plane, environment, default) and, for the ones set by environment, the variable to change.

Nothing is editable on this page: the brand changes in the control plane's back office, or in the environment variables followed by a restart.