feat: add Gateway API support (#1073)

Add full Gateway API support for exposing Gitea via HTTPRoute, TCPRoute, BackendTLSPolicy, and ClientSettingsPolicy resources.

New templates:
- `httpRoute.yaml` — renders an HTTPRoute with configurable
  parentRefs, hostnames, and rules (defaults to PathPrefix `/`)
- `tcpRoute.yaml` — renders a TCPRoute for SSH traffic
- `backendTLSPolicy.yaml` — renders a BackendTLSPolicy for
  encrypted backend connections with required validation config
- `clientSettingsPolicy.yaml` — renders an NGINX Gateway Fabric
  ClientSettingsPolicy to raise the request body size limit

Infrastructure:
- `gatewayAPI.enabled` global toggle gates all resources
- Resources grouped under `gatewayAPI.core.*` and `gatewayAPI.nginx.*`
- Helper templates extracted into dedicated `_*.tpl` files
- Service name helpers (`gitea.service.http.name`, `gitea.service.ssh.name`)
  extracted into `_services.tpl`; service templates renamed to camelCase
- `ROOT_URL`, `DOMAIN`, and `SSH_DOMAIN` auto-resolve from
  `httpRoute.hostnames[0]`; `httpRoute.tls` switches to `https`

Documentation:
- New `docs/gateway-api.md` with topology examples, BackendTLSPolicy
  setup, sectionName guidance, SSH considerations, and NGINX body
  size limit configuration
- `.github/copilot-instructions.md` with project conventions
- README parameter table auto-generated via `make readme`

Tests:
- Helm unit tests for all four new resource templates
- Config tests for hostname/TLS resolution from Gateway API values

Co-authored-by: Todd Marimon <toddmarimon@gmail.com>
This commit is contained in:
Todd Marimon
2026-07-19 16:25:28 +00:00
committed by Markus Pesch
parent 5005037dbf
commit 7747a001f7
25 changed files with 1200 additions and 40 deletions
+30
View File
@@ -0,0 +1,30 @@
{{/* vim: set filetype=mustache: */}}
{{/* annotations */}}
{{- define "gitea.backendTLSPolicy.annotations" -}}
{{- with .Values.gatewayAPI.core.backendTLSPolicy.annotations }}
{{- toYaml . -}}
{{- end }}
{{- end }}
{{/* enabled */}}
{{- define "gitea.backendTLSPolicy.enabled" -}}
{{- if and .Values.gatewayAPI.enabled
.Values.gatewayAPI.core.backendTLSPolicy.enabled
-}}
true
{{- else -}}
false
{{- end -}}
{{- end }}
{{/* labels */}}
{{- define "gitea.backendTLSPolicy.labels" -}}
{{ include "gitea.labels" . }}
{{- with .Values.gatewayAPI.core.backendTLSPolicy.labels }}
{{ toYaml . }}
{{- end }}
{{- end }}
@@ -0,0 +1,30 @@
{{/* vim: set filetype=mustache: */}}
{{/* annotations */}}
{{- define "gitea.clientSettingsPolicies.annotations" -}}
{{- with .Values.gatewayAPI.nginx.clientSettingsPolicies.annotations }}
{{- toYaml . -}}
{{- end }}
{{- end }}
{{/* enabled */}}
{{- define "gitea.clientSettingsPolicies.enabled" -}}
{{- if and .Values.gatewayAPI.enabled
.Values.gatewayAPI.nginx.clientSettingsPolicies.enabled
-}}
true
{{- else -}}
false
{{- end -}}
{{- end }}
{{/* labels */}}
{{- define "gitea.clientSettingsPolicies.labels" -}}
{{ include "gitea.labels" . }}
{{- with .Values.gatewayAPI.nginx.clientSettingsPolicies.labels }}
{{ toYaml . }}
{{- end }}
{{- end }}
+30
View File
@@ -0,0 +1,30 @@
{{/* vim: set filetype=mustache: */}}
{{/* annotations */}}
{{- define "gitea.httpRoute.annotations" -}}
{{- with .Values.gatewayAPI.core.httpRoute.annotations }}
{{- toYaml . -}}
{{- end }}
{{- end }}
{{/* enabled */}}
{{- define "gitea.httpRoute.enabled" -}}
{{- if and .Values.gatewayAPI.enabled
.Values.gatewayAPI.core.httpRoute.enabled
-}}
true
{{- else -}}
false
{{- end -}}
{{- end }}
{{/* labels */}}
{{- define "gitea.httpRoute.labels" -}}
{{ include "gitea.labels" . }}
{{- with .Values.gatewayAPI.core.httpRoute.labels }}
{{ toYaml . }}
{{- end }}
{{- end }}
+11
View File
@@ -0,0 +1,11 @@
{{/* vim: set filetype=mustache: */}}
{{/* names */}}
{{- define "gitea.service.http.name" -}}
{{ include "gitea.fullname" . }}-http
{{- end }}
{{- define "gitea.service.ssh.name" -}}
{{ include "gitea.fullname" . }}-ssh
{{- end }}
+30
View File
@@ -0,0 +1,30 @@
{{/* vim: set filetype=mustache: */}}
{{/* annotations */}}
{{- define "gitea.tcpRoute.annotations" -}}
{{- with .Values.gatewayAPI.core.tcpRoute.annotations }}
{{- toYaml . -}}
{{- end }}
{{- end }}
{{/* enabled */}}
{{- define "gitea.tcpRoute.enabled" -}}
{{- if and .Values.gatewayAPI.enabled
.Values.gatewayAPI.core.tcpRoute.enabled
-}}
true
{{- else -}}
false
{{- end -}}
{{- end }}
{{/* labels */}}
{{- define "gitea.tcpRoute.labels" -}}
{{ include "gitea.labels" . }}
{{- with .Values.gatewayAPI.core.tcpRoute.labels }}
{{ toYaml . }}
{{- end }}
{{- end }}
+30
View File
@@ -0,0 +1,30 @@
{{- if eq (include "gitea.backendTLSPolicy.enabled" .) "true" -}}
{{- if not (keys .Values.gatewayAPI.core.backendTLSPolicy.validation) }}
{{- fail "gatewayAPI.core.backendTLSPolicy.validation is required" }}
{{- end }}
---
apiVersion: gateway.networking.k8s.io/v1
kind: BackendTLSPolicy
metadata:
{{- with (include "gitea.backendTLSPolicy.annotations" .) }}
annotations:
{{- . | nindent 4 }}
{{- end }}
{{- with (include "gitea.backendTLSPolicy.labels" .) }}
labels:
{{- . | nindent 4 }}
{{- end }}
name: {{ include "gitea.fullname" . }}
namespace: {{ .Values.namespace | default .Release.Namespace }}
spec:
targetRefs:
{{- if .Values.gatewayAPI.core.backendTLSPolicy.targetRefs }}
{{- toYaml .Values.gatewayAPI.core.backendTLSPolicy.targetRefs | nindent 4 }}
{{- else }}
- group: ""
kind: Service
name: {{ include "gitea.service.http.name" . }}
{{- end }}
validation:
{{- toYaml .Values.gatewayAPI.core.backendTLSPolicy.validation | nindent 4 }}
{{- end }}
+30
View File
@@ -0,0 +1,30 @@
{{- if eq (include "gitea.clientSettingsPolicies.enabled" .) "true" -}}
{{- if not (keys .Values.gatewayAPI.nginx.clientSettingsPolicies.body) }}
{{- fail "gatewayAPI.nginx.clientSettingsPolicies.body is required" }}
{{- end }}
---
apiVersion: gateway.nginx.org/v1alpha1
kind: ClientSettingsPolicy
metadata:
{{- with (include "gitea.clientSettingsPolicies.annotations" .) }}
annotations:
{{- . | nindent 4 }}
{{- end }}
{{- with (include "gitea.clientSettingsPolicies.labels" .) }}
labels:
{{- . | nindent 4 }}
{{- end }}
name: {{ include "gitea.fullname" . }}
namespace: {{ .Values.namespace | default .Release.Namespace }}
spec:
targetRef:
{{- if .Values.gatewayAPI.nginx.clientSettingsPolicies.targetRef }}
{{- toYaml .Values.gatewayAPI.nginx.clientSettingsPolicies.targetRef | nindent 4 }}
{{- else }}
group: gateway.networking.k8s.io
kind: HTTPRoute
name: {{ include "gitea.fullname" . }}
{{- end }}
body:
{{- toYaml .Values.gatewayAPI.nginx.clientSettingsPolicies.body | nindent 4 }}
{{- end }}
+42
View File
@@ -0,0 +1,42 @@
{{- if eq (include "gitea.httpRoute.enabled" .) "true" -}}
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
{{- with (include "gitea.httpRoute.annotations" .) }}
annotations:
{{- . | nindent 4 }}
{{- end }}
{{- with (include "gitea.httpRoute.labels" .) }}
labels:
{{- . | nindent 4 }}
{{- end }}
name: {{ include "gitea.fullname" . }}
namespace: {{ .Values.namespace | default .Release.Namespace }}
spec:
parentRefs:
{{- if .Values.gatewayAPI.core.httpRoute.parentRefs }}
{{- toYaml .Values.gatewayAPI.core.httpRoute.parentRefs | nindent 4 }}
{{- else }}
{{- fail "gatewayAPI.core.httpRoute.parentRefs is required" }}
{{- end }}
{{- with .Values.gatewayAPI.core.httpRoute.hostnames }}
hostnames:
{{- tpl (toYaml .) $ | nindent 4 }}
{{- end }}
rules:
{{- if .Values.gatewayAPI.core.httpRoute.rules }}
{{- tpl (toYaml .Values.gatewayAPI.core.httpRoute.rules) $ | nindent 4 }}
{{- else }}
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ""
kind: Service
name: {{ include "gitea.service.http.name" . }}
port: {{ .Values.service.http.port }}
weight: 1
{{- end }}
{{- end }}
@@ -1,15 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "gitea.fullname" . }}-http
namespace: {{ .Values.namespace | default .Release.Namespace }}
annotations:
{{- toYaml .Values.service.http.annotations | nindent 4 }}
labels:
{{- include "gitea.labels" . | nindent 4 }}
{{- if .Values.service.http.labels }}
{{- toYaml .Values.service.http.labels | nindent 4 }}
{{- end }}
annotations:
{{- toYaml .Values.service.http.annotations | nindent 4 }}
name: {{ include "gitea.service.http.name" . }}
namespace: {{ .Values.namespace | default .Release.Namespace }}
spec:
type: {{ .Values.service.http.type }}
{{- if eq .Values.service.http.type "LoadBalancer" }}
+3 -3
View File
@@ -36,7 +36,7 @@ spec:
pathType: {{ default "Prefix" $.Values.ingress.pathType }}
backend:
service:
name: {{ $fullName }}-http
name: {{ include "gitea.service.http.name" $ }}
port:
number: {{ $httpPort }}
{{- else }}
@@ -44,7 +44,7 @@ spec:
pathType: {{ .pathType | default "Prefix" }}
backend:
service:
name: {{ $fullName }}-http
name: {{ include "gitea.service.http.name" $ }}
port:
number: {{ $httpPort }}
{{- end }}
@@ -54,7 +54,7 @@ spec:
pathType: "Prefix"
backend:
service:
name: {{ $fullName }}-http
name: {{ include "gitea.service.http.name" $ }}
port:
number: {{ $httpPort }}
{{- end }}
+1 -1
View File
@@ -20,7 +20,7 @@ spec:
{{- end }}
to:
kind: Service
name: {{ $fullName }}-http
name: {{ include "gitea.service.http.name" . }}
port:
targetPort: http
wildcardPolicy: {{ .Values.route.wildcardPolicy }}
@@ -1,15 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "gitea.fullname" . }}-ssh
namespace: {{ .Values.namespace | default .Release.Namespace }}
annotations:
{{- toYaml .Values.service.ssh.annotations | nindent 4 }}
labels:
{{- include "gitea.labels" . | nindent 4 }}
{{- if .Values.service.ssh.labels }}
{{- toYaml .Values.service.ssh.labels | nindent 4 }}
{{- end }}
annotations:
{{- toYaml .Values.service.ssh.annotations | nindent 4 }}
name: {{ include "gitea.service.ssh.name" . }}
namespace: {{ .Values.namespace | default .Release.Namespace }}
spec:
type: {{ .Values.service.ssh.type }}
{{- if eq .Values.service.ssh.type "LoadBalancer" }}
+34
View File
@@ -0,0 +1,34 @@
{{- if eq (include "gitea.tcpRoute.enabled" .) "true" -}}
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
{{- with (include "gitea.tcpRoute.annotations" .) }}
annotations:
{{- . | nindent 4 }}
{{- end }}
{{- with (include "gitea.tcpRoute.labels" .) }}
labels:
{{- . | nindent 4 }}
{{- end }}
name: {{ include "gitea.fullname" . }}
namespace: {{ .Values.namespace | default .Release.Namespace }}
spec:
parentRefs:
{{- if .Values.gatewayAPI.core.tcpRoute.parentRefs }}
{{- toYaml .Values.gatewayAPI.core.tcpRoute.parentRefs | nindent 4 }}
{{- else }}
{{- fail "gatewayAPI.core.tcpRoute.parentRefs is required" }}
{{- end }}
rules:
{{- if .Values.gatewayAPI.core.tcpRoute.rules }}
{{- tpl (toYaml .Values.gatewayAPI.core.tcpRoute.rules) $ | nindent 4 }}
{{- else }}
- backendRefs:
- group: ""
kind: Service
name: {{ include "gitea.service.ssh.name" . }}
port: {{ .Values.service.ssh.port }}
weight: 1
{{- end }}
{{- end }}