Skip to content

Brand the Authelia login portal with the SUS 🤨 logo - #94

Merged
dev-dull merged 1 commit into
mainfrom
feat/authelia-login-branding
Jul 28, 2026
Merged

Brand the Authelia login portal with the SUS 🤨 logo#94
dev-dull merged 1 commit into
mainfrom
feat/authelia-login-branding

Conversation

@dev-dull

Copy link
Copy Markdown
Owner

Replaces Authelia's default person icon on the login card with the SUS 🤨, and otherwise leaves the portal as Authelia ships it (including the "Sign in" text).

What it does

  • Bundles charts/sus/assets/logo.png — the SUS 🤨 (Noto Emoji, Apache-2.0, safe to redistribute) — and serves it as the login-portal logo via Authelia's server.asset_path.
  • New auth.authelia.branding values: enabled (default true), theme (light/dark/grey/auto), and logoPngBase64 for operators to drop in their own logo.
  • New templates/authelia/assets-configmap.yaml carries the logo (binaryData); the Authelia deployment subPath-mounts it and rolls on change via a checksum annotation. All gated by branding.enabled, so nothing renders when auth is off.

Scope note

An earlier draft also retitled the login text to "Single Use Software Login", but Authelia uses one translation key for both the form header and the submit button, so that made the button read "SINGLE USE SOFTWARE LOGIN" too. Dropped the text override — this PR is logo-only.

Verification (live on k3d)

  • Authelia boots with asset_path; /static/media/logo.png serves the bundled 🤨 byte-for-byte with data-logooverride="true".
  • Asset tree contains only logo.png (no locale override); /locales/en/portal.json returns Authelia's defaults, so "Sign in" is unchanged.
  • helm lint / helm template clean; auth-off renders no branding resources.

🤖 Generated with Claude Code

Replaces Authelia's default person icon on the login card with the SUS 🤨
(Noto Emoji, Apache-2.0, bundled at charts/sus/assets/logo.png) via a server
asset override (server.asset_path). Configurable under auth.authelia.branding
(enabled, theme, logoPngBase64 to supply your own logo). The rest of the portal,
including the "Sign in" text, is left as Authelia ships it.

New templates/authelia/assets-configmap.yaml carries the logo (binaryData via
.Files.Get); the deployment subPath-mounts it into the asset tree and rolls on
change via a checksum annotation. Gated by branding.enabled (default true), so
it's off when auth is off.

Verified live on k3d: Authelia boots with asset_path and serves the bundled 🤨
at /static/media/logo.png (data-logooverride="true").

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

Claude finished @dev-dull's task in 4m 11s —— View job


Review: Authelia login-portal branding

  • Gather context (chart layout, .helmignore, publish workflow)
  • Read the diff and changed files
  • Render helm template — auth on, auth off, branding.enabled=false, custom logo
  • Probe failure modes (wrapped base64, missing asset)
  • Post findings

Solid, well-scoped change — the mechanics are right and the tricky parts are handled deliberately: the subPath mount avoids shadowing Authelia's asset tree, and the checksum/authelia-assets annotation covers the fact that subPath mounts don't hot-reload on ConfigMap change. The scope note about Authelia's shared translation key for header + submit button is the correct call.

What I verified locally (helm v4.2.3, same version CI pins):

Check Result
helm lint charts/sus clean (only the pre-existing icon is recommended info)
auth.enabled=true assets ConfigMap, asset_path: /config/assets, volume + subPath mount, checksum annotation all present
auth.enabled=false zero matches for authelia/asset/logo in the whole render — stays opt-in ✅
branding.enabled=false assets ConfigMap, volume, mount, asset_path all dropped (see finding 3 re: theme)
logoPngBase64 override replaces binaryData as expected
Mount layout /config isn't itself a volume, so kubelet creates /config/assets/ for the subPath file — no conflict with the configuration.yml mount
Chart packaging default .helmignore doesn't exclude assets/, so the PNG ships with helm package

I couldn't byte-compare the rendered base64 against the PNG (the python3/helm package calls I wanted are outside this job's allowlist), so I'm taking your k3d byte-for-byte check at face value there. Adding Bash(helm package:*) to --allowedTools in .github/workflows/claude-review.yaml would let a future review confirm the asset actually lands in the tarball.

Findings (3 inline, none blocking):

  1. assets-configmap.yaml:13 — the base64 value is interpolated unquoted, so a line-wrapped logoPngBase64 fails the render with an opaque could not find expected ':' pointing at the template rather than the value. Reachable via the values.yaml hint: on GNU coreutils base64 -i is --ignore-garbage, not "input file", so encoding still wraps at 76 columns. Same line: a missing assets/logo.png renders logo.png: (null), which applies cleanly and mounts a 0-byte logo — silent breakage instead of a loud failure. Both reproduced; one | nospace | required ... | quote chain covers both.
  2. configmap.yaml:19 — comment claims the override covers "logo/favicon and text"; only logo.png is shipped. Leftover from the dropped draft.
  3. values.yaml:117-120theme is nested under branding but applies even when branding.enabled: false; also an invalid theme passes lint/template and only fails at container startup.

No security concerns: the ConfigMap holds a public image, the mount is readOnly, and nothing here touches the app→platform trust boundary or reads client-supplied values. No test-coverage gap specific to this PR — the chart has no unit-test harness today, so that's a pre-existing gap rather than something this change introduces.

Nothing was committed; the working tree is clean (all render artifacts removed).
• branch feat/authelia-login-branding

{{- include "sus.labels" . | nindent 4 }}
app.kubernetes.io/component: authelia
binaryData:
logo.png: {{ .Values.auth.authelia.branding.logoPngBase64 | default (.Files.Get "assets/logo.png" | b64enc) }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A line-wrapped logoPngBase64 breaks the render with an opaque error. The value is interpolated unquoted, so any newline in it corrupts the YAML. This is easy to hit because the guidance in values.yaml is base64 -i logo.png, and on GNU coreutils -i is --ignore-garbage (not "input file"), so encoding still wraps at 76 columns. Reproduced locally with a two-line value:

Error: YAML parse error on sus/templates/authelia/assets-configmap.yaml:
error converting YAML to JSON: yaml: line 19: could not find expected ':'

The error points at the template, not at the operator's value, so it's a rough debugging experience.

Separately, if assets/logo.png ever goes missing (or gets .helmignored), .Files.Get returns "" and this renders logo.png: — a null value that applies cleanly and mounts a 0-byte logo.png, i.e. a silently broken image on the login page rather than a loud failure.

Both are covered by normalizing whitespace, quoting, and requiring a non-empty result:

Suggested change
logo.png: {{ .Values.auth.authelia.branding.logoPngBase64 | default (.Files.Get "assets/logo.png" | b64enc) }}
logo.png: {{ .Values.auth.authelia.branding.logoPngBase64 | default (.Files.Get "assets/logo.png" | b64enc) | nospace | required "auth.authelia.branding: no logo available — set auth.authelia.branding.logoPngBase64 or restore charts/sus/assets/logo.png" | quote }}

Worth updating the values.yaml hint to base64 -w0 logo.png too (or base64 < logo.png | tr -d '\n' for portability across GNU/BSD).

server:
address: 'tcp://:9091'
{{- if .Values.auth.authelia.branding.enabled }}
# Override the portal logo/favicon and text (see the -assets ConfigMap).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment from the earlier draft: the assets ConfigMap carries only logo.png, so neither the favicon nor the portal text is overridden here (the PR body says the text override was intentionally dropped). As written this sends a future reader looking for a locales/ entry that doesn't exist.

Suggested change
# Override the portal logo/favicon and text (see the -assets ConfigMap).
# Override the portal logo (see the -assets ConfigMap).

Comment thread charts/sus/values.yaml
Comment on lines +117 to +120
branding:
enabled: true
# Portal color scheme: light | dark | grey | auto.
theme: light

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor wiring surprise: theme sits under branding but is consumed unconditionally in configmap.yaml, so it still takes effect with branding.enabled: false. Confirmed via helm template --set auth.authelia.branding.enabled=false — the render drops the assets ConfigMap, the volume, and asset_path, but keeps theme. Either hoist theme up a level next to image, or note in the comment that it applies regardless of enabled (which reads as "logo override on/off").

Also worth a one-line note that Authelia only accepts light | dark | grey | auto — an invalid value passes helm template/helm lint and only fails at container startup with a config-validation error.

@dev-dull
dev-dull merged commit 582346e into main Jul 28, 2026
1 check passed
@dev-dull
dev-dull deleted the feat/authelia-login-branding branch July 28, 2026 19:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant