From 326b626fc6c3e16398a677692ebcc38a52e8761c Mon Sep 17 00:00:00 2001 From: Ronni Baslund Date: Mon, 8 Jun 2026 20:36:01 +0200 Subject: [PATCH] feat(infra): full dezky rebrand of Authentik login (logo, favicon, bg, footer) Brand CSS only reaches the flow shadow DOM via CSS vars (colors), not the logo/favicon (deeper shadow root) or the "Powered by authentik" footer (light DOM). So, dev-style: serve real dezky assets + sed the bundle. - web-assets/: dezky-logo.svg, dezky-favicon.svg, dezky-bg.svg (carbon). - server-rebrand.py: patches the authentik-server Deployment with an initContainer that copies /web/dist to an emptyDir, drops the svgs into assets/icons, and seds "Powered by authentik" -> "Powered by Dezky". - brand.yaml: branding_logo / branding_favicon / branding_default_flow_background point at the served svgs; auth-flow title "Welcome to Dezky"; signal-green CSS. Verified live: login now matches dev (logo, title, carbon bg, green button, favicon, Powered by Dezky). Durability caveat documented (reverts on helm upgrade). --- .../production/fleet/authentik/README.md | 29 +++++++++++++++-- .../fleet/authentik/blueprints/brand.yaml | 31 ++++++++----------- .../fleet/authentik/server-rebrand.py | 14 +++++++++ .../fleet/authentik/web-assets/dezky-bg.svg | 1 + .../authentik/web-assets/dezky-favicon.svg | 1 + .../fleet/authentik/web-assets/dezky-logo.svg | 1 + 6 files changed, 57 insertions(+), 20 deletions(-) create mode 100644 infrastructure/production/fleet/authentik/server-rebrand.py create mode 100644 infrastructure/production/fleet/authentik/web-assets/dezky-bg.svg create mode 100644 infrastructure/production/fleet/authentik/web-assets/dezky-favicon.svg create mode 100644 infrastructure/production/fleet/authentik/web-assets/dezky-logo.svg diff --git a/infrastructure/production/fleet/authentik/README.md b/infrastructure/production/fleet/authentik/README.md index 8e762ee..917c89c 100644 --- a/infrastructure/production/fleet/authentik/README.md +++ b/infrastructure/production/fleet/authentik/README.md @@ -70,6 +70,31 @@ Client secrets live in `authentik-secret` (`PORTAL_OIDC_CLIENT_SECRET`, > post-render kustomize patch to make it durable). TODO. ## Still deferred -- **Rebrand** of the "Powered by authentik" string (web-bundle `sed`, needs a - root lifecycle override) — cosmetic; the *colors* are done via the brand CSS. - Pin the **chart version** (currently latest → app `2026.5.2`). +- **Durability:** the server-rebrand Deployment patch + the brand image-field + PATCH revert on a helm upgrade of Authentik — re-run them, or bake a custom + image / post-render kustomize patch. + +## Full visual rebrand (logo / favicon / background / footer) — APPLIED + +Brand custom CSS only reaches shadow DOM via CSS **vars** (so colors work), not +the logo/favicon (deeper shadow root) or the "Powered by authentik" footer +(light DOM). Those use dev's mechanism — real files + a bundle sed: + +- `web-assets/` — `dezky-logo.svg`, `dezky-favicon.svg`, `dezky-bg.svg` (carbon). +- ConfigMap `authentik-web-assets` is built from `web-assets/`. +- `server-rebrand.py` patches the **authentik-server** Deployment: an + initContainer copies `/web/dist` into an emptyDir, drops the 3 svgs into + `/web/dist/assets/icons/`, and seds `Powered by authentik` -> `Powered by + Dezky`. The server then serves the patched bundle. +- The brand's `branding_logo` / `branding_favicon` / + `branding_default_flow_background` point at those served svgs (carried in + brand.yaml; if the blueprint leaves them default, PATCH the brand via API). + +Apply: +``` +kubectl -n dezky-auth create configmap authentik-web-assets --from-file=web-assets/ --dry-run=client -o yaml | kubectl apply -f - +kubectl -n dezky-auth get deploy authentik-server -o json | python3 server-rebrand.py | kubectl apply -f - +``` +> CAVEAT: the server patch + brand PATCH revert on a helm upgrade of Authentik — +> re-run them (or bake a custom image) for durability. diff --git a/infrastructure/production/fleet/authentik/blueprints/brand.yaml b/infrastructure/production/fleet/authentik/blueprints/brand.yaml index 3187d52..329ec9c 100644 --- a/infrastructure/production/fleet/authentik/blueprints/brand.yaml +++ b/infrastructure/production/fleet/authentik/blueprints/brand.yaml @@ -1,8 +1,11 @@ -# dezky branding for the default Authentik brand. branding_logo / -# branding_default_flow_background are FILE-PATH fields (reject data URIs), so -# the logo + carbon background are done via custom CSS (which allows data URIs). -# The auth-flow title is set on the flow itself. ("Powered by authentik" footer -# still needs the separate web-bundle patch.) +# dezky branding for the default Authentik brand. +# - branding_logo points at a dezky SVG injected into the server's web bundle +# by the dezky-rebrand initContainer (see authentik/README "rebrand"). +# - colors (accent, button, carbon background) via custom CSS (CSS vars cross the +# shadow boundary; selectors can't, so the logo had to be a real file). +# - "Powered by authentik" -> "Powered by Dezky" is done by the same +# initContainer sed'ing the bundle (the footer is light-DOM, unreachable by +# brand CSS). version: 1 metadata: name: dezky-brand @@ -15,6 +18,9 @@ entries: domain: authentik-default attrs: branding_title: dezky + branding_logo: /static/dist/assets/icons/dezky-logo.svg + branding_favicon: /static/dist/assets/icons/dezky-favicon.svg + branding_default_flow_background: /static/dist/assets/icons/dezky-bg.svg branding_custom_css: | :root, :host { --ak-accent: #D4FF3A; @@ -23,19 +29,8 @@ entries: --pf-global--link--Color: #D4FF3A; --ak-flow-background: #0A0A0A !important; } - /* dezky logo in place of the authentik wordmark */ - .pf-c-brand, img.pf-c-brand, .ak-brand img, header img { - content: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxODAiIGhlaWdodD0iNDgiIHZpZXdCb3g9IjAgMCAxODAgNDgiPjxyZWN0IHg9IjIiIHk9IjIiIHdpZHRoPSI0NCIgaGVpZ2h0PSI0NCIgcng9IjEzIiBmaWxsPSIjRjRGM0VFIi8+PHRleHQgeD0iMjQiIHk9IjM2IiBmb250LWZhbWlseT0iQXJpYWwsSGVsdmV0aWNhLHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMzIiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMwQTBBMEEiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmQ8L3RleHQ+PGNpcmNsZSBjeD0iMzgiIGN5PSIxMiIgcj0iNC41IiBmaWxsPSIjRDRGRjNBIi8+PHRleHQgeD0iNTgiIHk9IjM0IiBmb250LWZhbWlseT0iQXJpYWwsSGVsdmV0aWNhLHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMjciIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiNGNEYzRUUiPmRlemt5PC90ZXh0Pjwvc3ZnPg==") !important; - height: 48px !important; - width: auto !important; - } - /* carbon background — remove the authentik forest */ - .pf-c-background-image, .pf-c-background-image__src, - ak-flow-executor, .ak-flow-card-background { - background: #0A0A0A !important; - } - img.pf-c-background-image__src, .pf-c-background-image__src { display: none !important; } - /* signal-green primary button + links */ + .pf-c-background-image, .pf-c-background-image__src { background: #0A0A0A !important; } + img.pf-c-background-image__src { display: none !important; } .pf-c-button.pf-m-primary, .pf-v5-c-button.pf-m-primary, .pf-v6-c-button.pf-m-primary { diff --git a/infrastructure/production/fleet/authentik/server-rebrand.py b/infrastructure/production/fleet/authentik/server-rebrand.py new file mode 100644 index 0000000..16245b8 --- /dev/null +++ b/infrastructure/production/fleet/authentik/server-rebrand.py @@ -0,0 +1,14 @@ +import sys,json +d=json.load(sys.stdin); spec=d["spec"]["template"]["spec"]; img=spec["containers"][0]["image"] +spec["volumes"]=[v for v in spec.get("volumes",[]) if v.get("name") not in ("webdist","webassets")] +spec["volumes"]+=[{"name":"webdist","emptyDir":{}},{"name":"webassets","configMap":{"name":"authentik-web-assets"}}] +script=("set -e\n cp -r /web/dist/. /wd/\n cp /assets/dezky-logo.svg /wd/assets/icons/dezky-logo.svg\n" + " cp /assets/dezky-bg.svg /wd/assets/icons/dezky-bg.svg\n cp /assets/dezky-favicon.svg /wd/assets/icons/dezky-favicon.svg\n" + " grep -rl 'Powered by authentik' /wd --include='*.js' | while read f; do sed -i 's/Powered by authentik/Powered by Dezky/g' \"$f\"; done\n echo rebrand-done") +ic=[c for c in spec.get("initContainers",[]) if c.get("name")!="dezky-rebrand"] +ic.append({"name":"dezky-rebrand","image":img,"command":["sh","-c",script],"volumeMounts":[{"name":"webdist","mountPath":"/wd"},{"name":"webassets","mountPath":"/assets"}]}) +spec["initContainers"]=ic +c0=spec["containers"][0] +c0["volumeMounts"]=[m for m in c0.get("volumeMounts",[]) if m.get("name")!="webdist"] +c0["volumeMounts"].append({"name":"webdist","mountPath":"/web/dist"}) +json.dump(d,sys.stdout) diff --git a/infrastructure/production/fleet/authentik/web-assets/dezky-bg.svg b/infrastructure/production/fleet/authentik/web-assets/dezky-bg.svg new file mode 100644 index 0000000..3298edb --- /dev/null +++ b/infrastructure/production/fleet/authentik/web-assets/dezky-bg.svg @@ -0,0 +1 @@ + diff --git a/infrastructure/production/fleet/authentik/web-assets/dezky-favicon.svg b/infrastructure/production/fleet/authentik/web-assets/dezky-favicon.svg new file mode 100644 index 0000000..65f2b68 --- /dev/null +++ b/infrastructure/production/fleet/authentik/web-assets/dezky-favicon.svg @@ -0,0 +1 @@ +d diff --git a/infrastructure/production/fleet/authentik/web-assets/dezky-logo.svg b/infrastructure/production/fleet/authentik/web-assets/dezky-logo.svg new file mode 100644 index 0000000..2b52dd8 --- /dev/null +++ b/infrastructure/production/fleet/authentik/web-assets/dezky-logo.svg @@ -0,0 +1 @@ +ddezky