Content Management that can withstand the plundering hoards

Automatic Ipseity authentication

When Ipseity is installed, a Website can omit spec.cms.authentication and spec.cms.hostname. The controller defaults the CMS hostname to cms.<spec.domain> and provisions a public OIDC client and initial administrator membership in the Website's namespace. Explicit authentication references take precedence and do not provision Ipseity resources.

apiVersion: cms.tlspu.com/v1alpha1
kind: Website
metadata:
  name: example
  namespace: websites-example
spec:
  domain: example.com
  description: Example website

Create the namespace first. description becomes the client's display name, falling back to the domain. A custom spec.cms.hostname is respected in both the CMS Ingress and the client's callback URI and allowed origin. Defaults are applied to generated resources without writing them back to the Website spec.

Set spec.cms.enabled: false to keep a Website frontend-only, even when Ipseity is installed. Do not combine this with a CMS hostname or authentication reference. With no Ipseity installation, an omitted CMS remains frontend-only; an explicit hostname or enabled: true requires authentication and blocks when none can be provided. Losing Ipseity after automatic provisioning also blocks CMS routing and scales its Deployment to zero until discovery recovers.

Provider discovery

Ipseity has no CRDs. The controller finds its Deployment using app: ipseity or app.kubernetes.io/name: ipseity on the Deployment or its Pod template. It follows same-namespace Service selectors and Ingress backends to find the public host serving /oidc, then sets discoveryURL to https://<host>/oidc. The CMS fetches /.well-known/openid-configuration below that base. There is no hardcoded provider URL. Automatic provisioning requires public HTTPS endpoints.

Multiple matching Deployments or Ingress hosts block automatic provisioning rather than selecting an arbitrary identity provider. A literal IPSEITY_OIDC_ISSUER in the selected Deployment can identify the canonical host among aliases, but it must match an actual discovered Ingress route. Issuer environment variables sourced through valueFrom are not dereferenced.

These controller settings disambiguate the installation and select the initial administrator. Explicit flags take precedence over their environment fallbacks.

Flag Environment fallback Default
--ipseity-namespace VIKING_IPSEITY_NAMESPACE discover across namespaces
--ipseity-deployment VIKING_IPSEITY_DEPLOYMENT any matching Deployment
--ipseity-ingress VIKING_IPSEITY_INGRESS any associated Ingress
--ipseity-admin-realm VIKING_IPSEITY_ADMIN_REALM ipseity
--ipseity-admin-subject VIKING_IPSEITY_ADMIN_SUBJECT adrian

Discovery is rechecked every 30 seconds for Websites without explicit authentication. Ingress endpoint changes update the generated Secret and roll CMS pods. Discovery/provisioning failures are reported as IpseityUnavailable or IpseityProvisioningFailed on the Website's Ready condition.

Created records and access

The controller merges ipseity.io/realm: "true" onto the Website namespace, preserving other labels, and creates:

Resource Name Purpose
Client ConfigMap ipseity-client-<domain> public client, consent required, client ID/name = domain, realm = Website namespace
Membership ConfigMap ipseity-membership-ipseity-adrian by default cross-realm membership for the configured home identity, role admins
Authentication Secret <domain>-ingress-oauth2 CMS OIDC settings and stable session-signing key

ConfigMaps carry Ipseity's app, managed-by, entity and name labels and JSON in data.payload. The client permits the effective CMS origin and https://<cms-hostname>/oauth2/callback, with allowed scopes openid profile groups roles email. The Secret selects Authorization Code with PKCE (publicClient: "true"), requests openid profile groups roles, and sets rolesClaim: roles, allowedRoles: admins and publishRoles: admins. The controller generates 32 random bytes for jwtSecret, stored as base64, and preserves that key on subsequent reconciles. Invalid existing key material blocks provisioning rather than silently rotating sessions.

The home identity must already exist in Ipseity. With the defaults, sign in as ipseity/adrian using that account's existing password and MFA. The membership is created once per namespace; later administrator changes to its grants or disabled state are preserved. Changing the controller's initial administrator settings creates a new membership and leaves previous memberships for an administrator to review.

The realm boundary is the namespace. Websites sharing a namespace share its realm and administrator membership, while each has a separate client ID and audience. Use separate namespaces when clients need separate realms. The target namespace must differ from the administrator's home realm. Automatic client IDs must fit Ipseity's Kubernetes name label (at most 63 characters); longer domains require explicitly configured authentication.

Retention and upgrades

Deleting a Website, disabling its CMS, changing its domain or switching to explicit authentication retains the namespace realm label and every Ipseity ConfigMap. These ConfigMaps have no Website owner references, so Kubernetes garbage collection also leaves them in place. An administrator removes obsolete clients and memberships later. Published/private PVC retention is unchanged.

The generated authentication Secret is Website-owned and is removed when obsolete or when the Website is deleted. Explicitly supplied authentication Secrets are never adopted or removed. Existing unowned credentials and client ConfigMaps are not overwritten: the automatic client records its creating Website UID in an annotation. Recreating a deleted Website under the same name produces a new UID, so an administrator must review/remove its retained client ConfigMap before automatic provisioning can recreate it. Matching existing memberships are reused without resetting their grants.

Deploy the updated Website CRD and controller RBAC before the new controller image. The RBAC adds namespace get/patch, ConfigMap create/update, and Secret create/update/delete; controller writes to Secrets are restricted to its own automatic authentication resources. Review existing frontend-only Websites and set cms.enabled: false if they should stay frontend-only when Ipseity is detected. The local Orbit copies must match deploy/01-crd.yaml and deploy/02-operator-rbac.yaml.