Branded builds
A build can carry another name than xvii: make BRAND=acme DISPLAY=acme (DISPLAY defaults to BRAND).
The core stays xvii; everything a person sees, runs or installs says the brand.
What sets it
- Go:
-X go.xvii.network/kit/brand.Name=$(BRAND) -X go.xvii.network/kit/brand.Display=$(DISPLAY).
brand.Name is the technical name (binaries acme, acme-node, units acme-pages, paths
/etc/acme, /var/lib/acme, the acme-admin group, env prefixes ACME_… through brand.EnvKey,
Docker labels through brand.Label); brand.DisplayName() is the name in text people read.
- Panels: make passes
VITE_BRAND=$(DISPLAY) (titles, product names) and VITE_CLI=$(BRAND) (commands);
panel/.env holds the xvii defaults. Read them through @/components/xvii/brand: BUILD, CLI and
cli("pages deploy"), never import.meta.env directly and never a literal "xvii".
- CLI: services write command text as
xvii … (summaries, help, examples, flag usage, errors);
kit/cli prints it as the build's name (cli.Branded). Code outside the CLI's packages that writes a
command (a page, a mail, an event, an API error) uses brand.Name.
- The instance's look (a name, colours, a logo, a background) is something else: superusers set it in
home and every panel paints it at run time. A build's brand is fixed when it's built.
What stays xvii on every build
The protocol's names: Go module paths (go.xvii.network/…), the @xvii registry, headers (X-Xvii-…),
key prefixes (sk-xvii-…), storage keys (xvii:…), XVII_RELEASE_KEYS, CLIProxyAPI's access provider, and
"powered by xvii" credits (brand.Tagline). A line that must say xvii whatever the build ends with a
brand: keep comment.
Checks
docs/scripts/check-brand.py [repo …] lists every place a branded build would still say xvii: panels'
copy and servers' text, outside the CLI's packages. Run it with a change that adds copy.
Releasing a branded instance
A brand signs its own releases. ci/brands/<brand>.env names it (BRAND, DISPLAY), its server, its
public release key (RELEASE_KEYS, built in as kit/release.BrandKeys), whether its builds trust the
project's key too (TRUST_PROJECT, false for a brand that takes only its own) and where its seed is on
the signing machine. The panels' icon shows the display name's first two letters (MARK).
ci/brand-release.sh <brand> REPO --import builds a clean checkout of a tag vX.Y.Z as vX.Y.Z-<brand>,
signs it with the brand's key and imports it into the brand's store; installing it stays a person's step
(home's Update, or <brand>-node install SERVICE VERSION, which health-checks and rolls back). Ship
node first: a build that trusts only the brand's key can't take a release signed by the project's.
The CLI is make publish BRAND=<brand> DISPLAY=… RELEASE_KEYS=… TRUST_PROJECT=… SOURCE=https://<home>/releases SIGNING_KEY_FILE=… SERVER=root@<host> VERSION=vX.Y.Z-<brand> from a clean checkout of the tag.
Before node trusts only the brand's key, add it to the instance (XVII_RELEASE_KEYS in
/etc/<brand>/instance.env) so the running node takes the first release the brand signed.