Serving: Ingress vs Gateway API¶
By default every NextcloudInstance is exposed through a networking.k8s.io/v1
Ingress, built from spec.ingress. spec.ingress.mode lets you switch a
single instance to Gateway API (gateway.networking.k8s.io) instead, which
attaches an HTTPRoute to an existing Gateway rather than creating an
Ingress object.
This is additive and opt-in. ingress.mode defaults to Ingress, so
every instance that never sets it — which is every instance created before
this field existed — keeps rendering exactly as before. Nothing about
existing behavior changes unless you explicitly set mode: GatewayAPI.
When to use which¶
Ingress(default) — the operator managesingress.className,ingress.annotations(including thecert-manager.io/cluster-issuerinjection), and TLS, and the upstream chart renders a standard Ingress object. This is the right choice unless you already have a Gateway APIGatewayyou want this instance attached to.GatewayAPI— use this when your cluster's ingress layer is a Gateway APIGateway(e.g. Envoy Gateway, Istio) rather than an Ingress controller, or when several apps need to share one Gateway's listeners.
Configuration¶
spec:
ingress:
host: cloud.example.com
mode: GatewayAPI
gateway:
parentRef:
name: public-gateway
namespace: gateway-system # optional — omit for a same-namespace Gateway
sectionName: https # REQUIRED whenever mode: GatewayAPI
See examples/nextcloud-with-gatewayapi.yaml for a full example.
spec.ingress.gateway.parentRef:
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Name of the Gateway this instance's HTTPRoute attaches to. |
namespace |
string | no | Namespace of the Gateway, if different from this instance's namespace. |
sectionName |
string | yes, when mode: GatewayAPI |
Name of a specific listener on the Gateway to attach to. |
Why sectionName is required¶
An HTTPRoute with no sectionName attaches to every listener on the
referenced Gateway — including any plaintext HTTP listener. On a shared
Gateway that terminates both HTTP and HTTPS (the HTTP listener commonly
exists only to redirect to HTTPS), an unpinned route bypasses that redirect
and serves the instance over plaintext HTTP too. Nextcloud has a single
route and a single host (unlike some apps with a separate admin console),
so there is no case where an unpinned route is safe here.
This is enforced twice:
- CRD admission —
NextcloudInstanceandNextcloudboth carry ax-kubernetes-validationsrule rejectingmode: GatewayAPIwith nogateway.parentRef.sectionName, so a misconfigured CR is rejected before the operator ever reconciles it. - Reconcile time —
NextcloudProfiledefaults andNextcloudPooltemplates cannot carry that CRD rule (their ingress-carrying fields are free-form, to stay forward-compatible with the upstream chart), so the operator also rejects it with a clear error whenever the merged configuration — however it was assembled — reachesbuild_helm_values()without a pinnedsectionName.
What stays the same regardless of mode¶
spec.ingress.enabled keeps meaning "this instance is externally exposed,"
independent of mode — it is not repurposed to mean "an Ingress object
exists." Because of that, none of the following change based on serving
mode:
- the instance's derived URL (
status.urland what other CRs — signaling and recording servers — build for it), - Nextcloud's reverse-proxy trust configuration
(
trustedProxies/forwardedForHeaders/overwriteprotocol, written intobnerd.config.php), - the OIDC "requires HTTPS" warning.
An instance never renders both objects¶
mode: GatewayAPI always forces the chart's ingress.enabled off, so an
instance never has both an Ingress and an HTTPRoute at once. This holds
even against spec.helm.values.ingress.enabled: true (the Layer-4 escape
hatch, which normally has the highest priority and overrides everything the
operator computes): with mode: GatewayAPI, that combination is rejected
outright with an error rather than silently letting either side win —
silently re-enabling the Ingress would recreate the exact hazard this mode
exists to prevent, and silently discarding the value would ignore
configuration you explicitly wrote.
Known limitation: readiness diagnostics¶
The operator's workload-readiness check (surfaced in status) reads the
rendered Ingress object for GatewayAPI: false (default) instances. There
is currently no equivalent HTTPRoute status read for GatewayAPI: true
instances — this is a deliberate scope decision for the initial Gateway API
support, tracked as a follow-up, not an oversight. It does not affect
serving: the instance is reachable exactly the same way; only this one
diagnostic signal has parity with Ingress-mode instances pending.