Compare commits

...

10 Commits

Author SHA1 Message Date
Kirill Ilin
3b366e28c6 fix(gateway-api): use stable v1 apiVersion for TLSRoute
v1alpha2 is deprecated in Gateway API v1.5.0 with a removal warning.
Update all TLSRoute resources to use gateway.networking.k8s.io/v1.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
2026-03-13 13:02:18 +05:00
Kirill Ilin
b6195cc8b8 chore(tenant) make generate for gateway
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
2026-03-13 12:42:21 +05:00
Kirill Ilin
1752f0e121 fix(gateway-api): address review findings
- Add HTTP-to-HTTPS redirect HTTPRoute for all Gateways (central and
  per-tenant) to ensure plain HTTP requests are properly redirected
- Add oidc-enabled check to keycloak HTTPRoute condition to match
  the Gateway listener condition
- Use gateway-name from cluster config instead of hardcoded value
  in central Gateway template
- Remove redundant namespace from TLSRoute metadata where it matches
  the HelmRelease install namespace (kubevirt, kubevirt-cdi)

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
2026-03-13 12:23:20 +05:00
Kirill Ilin
991e0ea3e3 feat(gateway): add Gateway API routes for tenant-level services
Add per-component Gateway + HTTPRoute/TLSRoute for tenant-level
services. Each component creates its own Gateway with specific
hostname HTTPS listener and cert-manager annotation for automatic
certificate provisioning via HTTP01 or DNS01.

All Gateways within a tenant share a single LoadBalancer IP through
infrastructure.labels (cozystack.io/gateway: {tenant-name}), matching
the current ingress-nginx model of one LB per tenant.

HTTPRoute (per-component Gateway with TLS terminate):
- monitoring/grafana: routes to grafana-service:3000
- monitoring/alerta: routes to alerta:80
- bucket: routes to {bucketName}-ui:8080
- apps/harbor: routes to {release}:80
- extra/bootbox: routes to bootbox:8080

TLSRoute (per-component Gateway with TLS passthrough):
- extra/seaweedfs: passthrough to filer-external:18888

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
2026-03-13 12:09:32 +05:00
Kirill Ilin
00890e0264 feat(gateway): add _namespace.gateway to tenant model
Add gateway field to tenant namespace configuration, following the
same inheritance pattern as ingress:
- tenant-root defaults to gateway: tenant-root
- Sub-tenants with gateway: true get their own LB
- Sub-tenants without gateway inherit from parent

Add infrastructure.labels to central Gateway for shared LB with
tenant-root services (cozystack.io/gateway: tenant-root).

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
2026-03-13 11:50:39 +05:00
Kirill Ilin
1076719730 feat(gateway): add HTTPRoute/TLSRoute for system services
Add Gateway API route templates alongside existing Ingress templates
for all system-level services. Routes are conditional on
_cluster.gateway-api being enabled.

HTTPRoute (TLS terminate via central Gateway):
- dashboard: routes to incloud-web-gatekeeper:8000
- keycloak: routes to keycloak-http:80

TLSRoute (TLS passthrough via central Gateway):
- cozystack-api: passthrough to kubernetes:443
- kubevirt vm-exportproxy: passthrough to vm-exportproxy:443
- kubevirt-cdi uploadproxy: passthrough to cdi-uploadproxy:443

All routes reference the central Gateway via parentRefs with
sectionName for listener matching. Hostname resolution follows
convention ({service}.{root-host}) with override support via
_cluster.hostnames map.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
2026-03-13 11:28:24 +05:00
Kirill Ilin
8b58140e0d feat(gateway): add central Gateway resource and platform config
Add cozystack-gateway system package that creates a shared Gateway
resource with per-hostname HTTPS listeners and TLS passthrough
listeners for system services. Listeners are dynamically generated
from expose-services config.

Platform changes:
- Add gateway-api flag to _cluster config for component awareness
- Add gateway.name/namespace to platform values for parentRef config
- Add publishing.hostnames map for per-service hostname overrides
- Wire cozystack-gateway package into system bundle (conditional)

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
2026-03-13 11:26:13 +05:00
Kirill Ilin
b15f2f273c fix(cert-manager): make enableGatewayAPI conditional on gateway.gatewayAPI
Previously enableGatewayAPI was hardcoded to true in cert-manager values,
causing startup failures in isp-hosted variant where Gateway API CRDs
are not installed. Now passed via component override only when
gateway.gatewayAPI is enabled.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
2026-03-12 09:45:03 +05:00
Kirill Ilin
7247edc280 feat(external-dns): add Gateway API source when gatewayAPI is enabled
When gateway.gatewayAPI is true, pass gateway-httproute source to the
system external-dns package via components values override.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
2026-03-11 23:27:54 +05:00
Kirill Ilin
2c0a043fa5 feat(gateway-api): add Gateway API support via Cilium
- Upgrade Gateway API CRDs from v1.2.0 to v1.5.0 (experimental channel)
- Add gateway-api-crds as a component in all networking variants,
  with Cilium depending on it to ensure CRDs are available first
- Add gateway.gatewayAPI platform config (enables Cilium
  gatewayAPI.enabled=true), can be used alongside gateway.ingress
- Enable Gateway API support in cert-manager

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
2026-03-11 23:27:30 +05:00
28 changed files with 9172 additions and 1287 deletions

View File

@@ -0,0 +1,75 @@
{{- $gatewayAPI := (index .Values._cluster "gateway-api") | default "false" }}
{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }}
{{- $gateway := .Values._namespace.gateway | default "" }}
{{- $host := .Values._namespace.host }}
{{- $harborHost := .Values.host | default (printf "%s.%s" .Release.Name $host) }}
{{- if and (eq $gatewayAPI "true") (ne $gateway "") }}
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: {{ .Release.Name }}-harbor
annotations:
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
spec:
gatewayClassName: cilium
infrastructure:
labels:
cozystack.io/gateway: {{ $gateway }}
listeners:
- name: http
protocol: HTTP
port: 80
hostname: {{ $harborHost | quote }}
allowedRoutes:
namespaces:
from: Same
- name: https
protocol: HTTPS
port: 443
hostname: {{ $harborHost | quote }}
tls:
mode: Terminate
certificateRefs:
- name: {{ .Release.Name }}-harbor-gateway-tls
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: {{ .Release.Name }}-harbor-redirect-to-https
spec:
parentRefs:
- name: {{ .Release.Name }}-harbor
sectionName: http
hostnames:
- {{ $harborHost | quote }}
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: {{ .Release.Name }}-harbor
spec:
parentRefs:
- name: {{ .Release.Name }}-harbor
sectionName: https
hostnames:
- {{ $harborHost | quote }}
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: {{ .Release.Name }}
port: 80
{{- end }}

View File

@@ -80,6 +80,7 @@ tenant-u1
| `etcd` | Deploy own Etcd cluster. | `bool` | `false` |
| `monitoring` | Deploy own Monitoring Stack. | `bool` | `false` |
| `ingress` | Deploy own Ingress Controller. | `bool` | `false` |
| `gateway` | Deploy own Gateway API gateway (separate LB for this tenant). | `bool` | `false` |
| `seaweedfs` | Deploy own SeaweedFS. | `bool` | `false` |
| `resourceQuotas` | Define resource quotas for the tenant. | `map[string]quantity` | `{}` |

View File

@@ -29,6 +29,11 @@
{{- $ingress = $tenantName }}
{{- end }}
{{- $gateway := $parentNamespace.gateway | default "" }}
{{- if .Values.gateway }}
{{- $gateway = $tenantName }}
{{- end }}
{{- $monitoring := $parentNamespace.monitoring | default "" }}
{{- if .Values.monitoring }}
{{- $monitoring = $tenantName }}
@@ -55,6 +60,7 @@ metadata:
{{/* Labels for network policies */}}
namespace.cozystack.io/etcd: {{ $etcd | quote }}
namespace.cozystack.io/ingress: {{ $ingress | quote }}
namespace.cozystack.io/gateway: {{ $gateway | quote }}
namespace.cozystack.io/monitoring: {{ $monitoring | quote }}
namespace.cozystack.io/seaweedfs: {{ $seaweedfs | quote }}
namespace.cozystack.io/host: {{ $computedHost | quote }}
@@ -83,6 +89,7 @@ stringData:
_namespace:
etcd: {{ $etcd | quote }}
ingress: {{ $ingress | quote }}
gateway: {{ $gateway | quote }}
monitoring: {{ $monitoring | quote }}
seaweedfs: {{ $seaweedfs | quote }}
host: {{ $computedHost | quote }}

View File

@@ -7,6 +7,11 @@
"type": "boolean",
"default": false
},
"gateway": {
"description": "Deploy own Gateway API gateway (separate LB for this tenant).",
"type": "boolean",
"default": false
},
"host": {
"description": "The hostname used to access tenant services (defaults to using the tenant name as a subdomain for its parent tenant host).",
"type": "string",

View File

@@ -14,6 +14,9 @@ monitoring: false
## @param {bool} ingress - Deploy own Ingress Controller.
ingress: false
## @param {bool} gateway - Deploy own Gateway API gateway (separate LB for this tenant).
gateway: false
## @param {bool} seaweedfs - Deploy own SeaweedFS.
seaweedfs: false

View File

@@ -0,0 +1,22 @@
---
apiVersion: cozystack.io/v1alpha1
kind: PackageSource
metadata:
name: cozystack.cozystack-gateway
spec:
sourceRef:
kind: OCIRepository
name: cozystack-packages
namespace: cozy-system
path: /
variants:
- name: default
dependsOn:
- cozystack.networking
- cozystack.cert-manager
components:
- name: cozystack-gateway
path: system/cozystack-gateway
install:
namespace: cozy-gateway
releaseName: cozystack-gateway

View File

@@ -15,6 +15,12 @@ spec:
- name: cilium
dependsOn: []
components:
- name: gateway-api-crds
path: system/gateway-api-crds
install:
namespace: cozy-gateway-api-crds
releaseName: gateway-api-crds
dependsOn: []
- name: cilium
path: system/cilium
valuesFiles:
@@ -24,7 +30,8 @@ spec:
privileged: true
namespace: cozy-cilium
releaseName: cilium
dependsOn: []
dependsOn:
- gateway-api-crds
- name: cilium-networkpolicy
path: system/cilium-networkpolicy
install:
@@ -36,6 +43,12 @@ spec:
- name: cilium-kilo
dependsOn: []
components:
- name: gateway-api-crds
path: system/gateway-api-crds
install:
namespace: cozy-gateway-api-crds
releaseName: gateway-api-crds
dependsOn: []
- name: cilium
path: system/cilium
valuesFiles:
@@ -46,7 +59,8 @@ spec:
privileged: true
namespace: cozy-cilium
releaseName: cilium
dependsOn: []
dependsOn:
- gateway-api-crds
- name: kilo
path: system/kilo
valuesFiles:
@@ -62,6 +76,12 @@ spec:
- name: cilium-generic
dependsOn: []
components:
- name: gateway-api-crds
path: system/gateway-api-crds
install:
namespace: cozy-gateway-api-crds
releaseName: gateway-api-crds
dependsOn: []
- name: cilium
path: system/cilium
valuesFiles:
@@ -70,7 +90,8 @@ spec:
privileged: true
namespace: cozy-cilium
releaseName: cilium
dependsOn: []
dependsOn:
- gateway-api-crds
- name: cilium-networkpolicy
path: system/cilium-networkpolicy
install:
@@ -82,6 +103,12 @@ spec:
- name: kubeovn-cilium
dependsOn: []
components:
- name: gateway-api-crds
path: system/gateway-api-crds
install:
namespace: cozy-gateway-api-crds
releaseName: gateway-api-crds
dependsOn: []
- name: cilium
path: system/cilium
valuesFiles:
@@ -92,7 +119,8 @@ spec:
privileged: true
namespace: cozy-cilium
releaseName: cilium
dependsOn: []
dependsOn:
- gateway-api-crds
- name: cilium-networkpolicy
path: system/cilium-networkpolicy
install:
@@ -113,6 +141,12 @@ spec:
- name: kubeovn-cilium-generic
dependsOn: []
components:
- name: gateway-api-crds
path: system/gateway-api-crds
install:
namespace: cozy-gateway-api-crds
releaseName: gateway-api-crds
dependsOn: []
- name: cilium
path: system/cilium
valuesFiles:
@@ -122,7 +156,8 @@ spec:
privileged: true
namespace: cozy-cilium
releaseName: cilium
dependsOn: []
dependsOn:
- gateway-api-crds
- name: cilium-networkpolicy
path: system/cilium-networkpolicy
install:

View File

@@ -39,6 +39,13 @@ stringData:
scheduling:
{{- . | toYaml | nindent 8 }}
{{- end }}
gateway-api: {{ .Values.gateway.gatewayAPI | quote }}
gateway-name: {{ .Values.gateway.name | quote }}
gateway-namespace: {{ .Values.gateway.namespace | quote }}
{{- with .Values.publishing.hostnames }}
hostnames:
{{- . | toYaml | nindent 8 }}
{{- end }}
{{- with $kubeRootCa.data }}
kube-root-ca: {{ index . "ca.crt" | b64enc | quote }}
{{- end }}

View File

@@ -16,10 +16,14 @@
{{- $kubeovnValues := dict "kube-ovn" $kubeovnDict -}}
{{- $_ := set $networkingComponents "kubeovn" (dict "values" $kubeovnValues) -}}
{{- /* For Talos (isp-full): use KubePrism endpoint and disable cgroup autoMount */ -}}
{{- $ciliumValues := dict "cilium" (dict
{{- $ciliumDict := dict
"k8sServiceHost" "localhost"
"k8sServicePort" "7445"
"cgroup" (dict "autoMount" (dict "enabled" false))) -}}
"cgroup" (dict "autoMount" (dict "enabled" false)) -}}
{{- if .Values.gateway.gatewayAPI -}}
{{- $_ := set $ciliumDict "gatewayAPI" (dict "enabled" true) -}}
{{- end -}}
{{- $ciliumValues := dict "cilium" $ciliumDict -}}
{{- $_ := set $networkingComponents "cilium" (dict "values" $ciliumValues) -}}
{{- end -}}
{{include "cozystack.platform.package" (list "cozystack.networking" "kubeovn-cilium" $ $networkingComponents) }}
@@ -83,10 +87,14 @@
{{- $kubeovnValues := dict "kube-ovn" $kubeovnDict -}}
{{- $_ := set $networkingComponents "kubeovn" (dict "values" $kubeovnValues) -}}
{{- /* Cilium configuration - for generic k8s, always enable cgroup autoMount */ -}}
{{- $ciliumValues := dict "cilium" (dict
{{- $ciliumDict := dict
"k8sServiceHost" $apiHost
"k8sServicePort" $apiPort
"cgroup" (dict "autoMount" (dict "enabled" true))) -}}
"cgroup" (dict "autoMount" (dict "enabled" true)) -}}
{{- if .Values.gateway.gatewayAPI -}}
{{- $_ := set $ciliumDict "gatewayAPI" (dict "enabled" true) -}}
{{- end -}}
{{- $ciliumValues := dict "cilium" $ciliumDict -}}
{{- $_ := set $networkingComponents "cilium" (dict "values" $ciliumValues) -}}
{{- end -}}
{{- /* Use kubeovn-cilium-generic variant (no values-talos.yaml) */ -}}
@@ -118,7 +126,15 @@
{{- end }}
# Common Packages
{{include "cozystack.platform.package.default" (list "cozystack.cert-manager" $) }}
{{- $certManagerComponents := dict -}}
{{- if .Values.gateway.gatewayAPI -}}
{{- $certManagerValues := dict "cert-manager" (dict "config" (dict "enableGatewayAPI" true)) -}}
{{- $_ := set $certManagerComponents "cert-manager" (dict "values" $certManagerValues) -}}
{{- end -}}
{{include "cozystack.platform.package" (list "cozystack.cert-manager" "default" $ $certManagerComponents) }}
{{- if .Values.gateway.gatewayAPI }}
{{include "cozystack.platform.package.default" (list "cozystack.cozystack-gateway" $) }}
{{- end }}
{{include "cozystack.platform.package.default" (list "cozystack.flux-plunger" $) }}
{{include "cozystack.platform.package.default" (list "cozystack.victoria-metrics-operator" $) }}
{{- $tenantComponents := dict -}}
@@ -148,7 +164,16 @@
# Optional System Packages (controlled via bundles.enabledPackages)
{{include "cozystack.platform.package.optional.default" (list "cozystack.nfs-driver" $) }}
{{include "cozystack.platform.package.optional.default" (list "cozystack.telepresence" $) }}
{{include "cozystack.platform.package.optional.default" (list "cozystack.external-dns" $) }}
{{- $externalDnsComponents := dict -}}
{{- if .Values.gateway.gatewayAPI -}}
{{- $externalDnsValues := dict "external-dns" (dict "sources" (list "service" "ingress" "gateway-httproute")) -}}
{{- $_ := set $externalDnsComponents "external-dns" (dict "values" $externalDnsValues) -}}
{{- end -}}
{{- $disabled := default (list) .Values.bundles.disabledPackages -}}
{{- $enabled := default (list) .Values.bundles.enabledPackages -}}
{{- if and (has "cozystack.external-dns" $enabled) (not (has "cozystack.external-dns" $disabled)) -}}
{{include "cozystack.platform.package" (list "cozystack.external-dns" "default" $ $externalDnsComponents) }}
{{- end }}
{{include "cozystack.platform.package.optional.default" (list "cozystack.external-dns-application" $) }}
{{include "cozystack.platform.package.optional.default" (list "cozystack.external-secrets-operator" $) }}
{{- if has "cozystack.bootbox" (default (list) .Values.bundles.enabledPackages) }}

View File

@@ -34,6 +34,16 @@ networking:
# Set this to comma-separated list of master node IPs to override.
kubeovn:
MASTER_NODES: ""
# Gateway configuration
# ingress and gatewayAPI can be enabled independently;
# future work will wire gateway.ingress into ingress controller selection
gateway:
ingress: true
gatewayAPI: false
# Gateway name and namespace for system-level Gateway resource
# Components reference this Gateway via parentRefs
name: cozystack
namespace: cozy-gateway
# Service publishing and ingress configuration
publishing:
host: "example.org"
@@ -43,6 +53,15 @@ publishing:
- dashboard
- vm-exportproxy
- cdi-uploadproxy
# Hostname overrides for system services
# By default, hostname = {service-name}.{host}
# Override individual hostnames when the convention doesn't fit
#
# Example:
# hostnames:
# keycloak: "auth.example.org"
# dashboard: "panel.example.org"
hostnames: {}
apiServerEndpoint: "" # example: "https://api.example.org"
externalIPs: []
certificates:

View File

@@ -0,0 +1,75 @@
{{- $gatewayAPI := (index .Values._cluster "gateway-api") | default "false" }}
{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }}
{{- $gateway := .Values._namespace.gateway | default "" }}
{{- $host := .Values._namespace.host }}
{{- $bootboxHost := printf "bootbox.%s" (.Values.host | default $host) }}
{{- if and (eq $gatewayAPI "true") (ne $gateway "") }}
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: bootbox
annotations:
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
spec:
gatewayClassName: cilium
infrastructure:
labels:
cozystack.io/gateway: {{ $gateway }}
listeners:
- name: http
protocol: HTTP
port: 80
hostname: {{ $bootboxHost | quote }}
allowedRoutes:
namespaces:
from: Same
- name: https
protocol: HTTPS
port: 443
hostname: {{ $bootboxHost | quote }}
tls:
mode: Terminate
certificateRefs:
- name: bootbox-gateway-tls
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: bootbox-redirect-to-https
spec:
parentRefs:
- name: bootbox
sectionName: http
hostnames:
- {{ $bootboxHost | quote }}
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: bootbox
spec:
parentRefs:
- name: bootbox
sectionName: https
hostnames:
- {{ $bootboxHost | quote }}
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: bootbox
port: 8080
{{- end }}

View File

@@ -0,0 +1,41 @@
{{- $gatewayAPI := (index .Values._cluster "gateway-api") | default "false" }}
{{- $gateway := .Values._namespace.gateway | default "" }}
{{- $host := .Values._namespace.host }}
{{- if and (eq $gatewayAPI "true") (ne $gateway "") (not (eq .Values.topology "Client")) (.Values.filer.grpcHost) }}
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: seaweedfs-filer
spec:
gatewayClassName: cilium
infrastructure:
labels:
cozystack.io/gateway: {{ $gateway }}
listeners:
- name: tls-passthrough
protocol: TLS
port: 443
hostname: {{ .Values.filer.grpcHost | default (printf "filer.%s" $host) | quote }}
tls:
mode: Passthrough
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: TLSRoute
metadata:
name: seaweedfs-filer
spec:
parentRefs:
- name: seaweedfs-filer
sectionName: tls-passthrough
hostnames:
- {{ .Values.filer.grpcHost | default (printf "filer.%s" $host) | quote }}
rules:
- backendRefs:
- name: {{ $.Release.Name }}-filer-external
port: 18888
{{- end }}

View File

@@ -0,0 +1,75 @@
{{- $gatewayAPI := (index .Values._cluster "gateway-api") | default "false" }}
{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }}
{{- $gateway := .Values._namespace.gateway | default "" }}
{{- $host := .Values._namespace.host }}
{{- $bucketHost := printf "%s.%s" .Values.bucketName $host }}
{{- if and (eq $gatewayAPI "true") (ne $gateway "") }}
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: {{ .Values.bucketName }}-ui
annotations:
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
spec:
gatewayClassName: cilium
infrastructure:
labels:
cozystack.io/gateway: {{ $gateway }}
listeners:
- name: http
protocol: HTTP
port: 80
hostname: {{ $bucketHost | quote }}
allowedRoutes:
namespaces:
from: Same
- name: https
protocol: HTTPS
port: 443
hostname: {{ $bucketHost | quote }}
tls:
mode: Terminate
certificateRefs:
- name: {{ .Values.bucketName }}-ui-gateway-tls
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: {{ .Values.bucketName }}-ui-redirect-to-https
spec:
parentRefs:
- name: {{ .Values.bucketName }}-ui
sectionName: http
hostnames:
- {{ $bucketHost | quote }}
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: {{ .Values.bucketName }}-ui
spec:
parentRefs:
- name: {{ .Values.bucketName }}-ui
sectionName: https
hostnames:
- {{ $bucketHost | quote }}
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: {{ .Values.bucketName }}-ui
port: 8080
{{- end }}

View File

@@ -0,0 +1 @@
cert-manager: {}

View File

@@ -0,0 +1,25 @@
{{- $gatewayAPI := (index .Values._cluster "gateway-api") | default "false" }}
{{- $host := index .Values._cluster "root-host" }}
{{- $hostnames := .Values._cluster.hostnames | default dict }}
{{- $exposeServices := splitList "," ((index .Values._cluster "expose-services") | default "") }}
{{- $gatewayName := (index .Values._cluster "gateway-name") | default "cozystack" }}
{{- $gatewayNamespace := (index .Values._cluster "gateway-namespace") | default "cozy-gateway" }}
{{- if and (eq $gatewayAPI "true") (has "api" $exposeServices) }}
apiVersion: gateway.networking.k8s.io/v1
kind: TLSRoute
metadata:
name: kubernetes-api
namespace: default
spec:
parentRefs:
- name: {{ $gatewayName }}
namespace: {{ $gatewayNamespace }}
sectionName: tls-passthrough-api
hostnames:
- {{ index $hostnames "api" | default (printf "api.%s" $host) | quote }}
rules:
- backendRefs:
- name: kubernetes
port: 443
{{- end }}

View File

@@ -16,5 +16,6 @@ stringData:
host: {{ index .Values._cluster "root-host" | quote }}
etcd: tenant-root
ingress: tenant-root
gateway: tenant-root
monitoring: tenant-root
seaweedfs: tenant-root

View File

@@ -0,0 +1,3 @@
apiVersion: v2
name: cozy-cozystack-gateway
version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process

View File

@@ -0,0 +1,99 @@
{{- $rootHost := index .Values._cluster "root-host" }}
{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }}
{{- $exposeServices := splitList "," ((index .Values._cluster "expose-services") | default "") }}
{{- $oidcEnabled := (index .Values._cluster "oidc-enabled") | default "false" }}
{{- $hostnames := .Values._cluster.hostnames | default dict }}
{{- $gatewayName := (index .Values._cluster "gateway-name") | default "cozystack" }}
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: {{ $gatewayName }}
annotations:
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
spec:
gatewayClassName: cilium
infrastructure:
labels:
cozystack.io/gateway: tenant-root
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
{{- if has "dashboard" $exposeServices }}
- name: https-dashboard
protocol: HTTPS
port: 443
hostname: {{ index $hostnames "dashboard" | default (printf "dashboard.%s" $rootHost) | quote }}
tls:
mode: Terminate
certificateRefs:
- name: gateway-dashboard-tls
allowedRoutes:
namespaces:
from: All
{{- end }}
{{- if eq $oidcEnabled "true" }}
- name: https-keycloak
protocol: HTTPS
port: 443
hostname: {{ index $hostnames "keycloak" | default (printf "keycloak.%s" $rootHost) | quote }}
tls:
mode: Terminate
certificateRefs:
- name: gateway-keycloak-tls
allowedRoutes:
namespaces:
from: All
{{- end }}
{{- if has "api" $exposeServices }}
- name: tls-passthrough-api
protocol: TLS
port: 443
hostname: {{ index $hostnames "api" | default (printf "api.%s" $rootHost) | quote }}
tls:
mode: Passthrough
allowedRoutes:
namespaces:
from: All
{{- end }}
{{- if has "vm-exportproxy" $exposeServices }}
- name: tls-passthrough-vm-exportproxy
protocol: TLS
port: 443
hostname: {{ index $hostnames "vm-exportproxy" | default (printf "vm-exportproxy.%s" $rootHost) | quote }}
tls:
mode: Passthrough
allowedRoutes:
namespaces:
from: All
{{- end }}
{{- if has "cdi-uploadproxy" $exposeServices }}
- name: tls-passthrough-cdi-uploadproxy
protocol: TLS
port: 443
hostname: {{ index $hostnames "cdi-uploadproxy" | default (printf "cdi-uploadproxy.%s" $rootHost) | quote }}
tls:
mode: Passthrough
allowedRoutes:
namespaces:
from: All
{{- end }}
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: {{ $gatewayName }}-redirect-to-https
spec:
parentRefs:
- name: {{ $gatewayName }}
sectionName: http
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301

View File

@@ -0,0 +1 @@
_cluster: {}

View File

@@ -0,0 +1,28 @@
{{- $gatewayAPI := (index .Values._cluster "gateway-api") | default "false" }}
{{- $host := index .Values._cluster "root-host" }}
{{- $hostnames := .Values._cluster.hostnames | default dict }}
{{- $exposeServices := splitList "," ((index .Values._cluster "expose-services") | default "") }}
{{- $gatewayName := (index .Values._cluster "gateway-name") | default "cozystack" }}
{{- $gatewayNamespace := (index .Values._cluster "gateway-namespace") | default "cozy-gateway" }}
{{- if and (eq $gatewayAPI "true") (has "dashboard" $exposeServices) }}
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: dashboard-web
spec:
parentRefs:
- name: {{ $gatewayName }}
namespace: {{ $gatewayNamespace }}
sectionName: https-dashboard
hostnames:
- {{ index $hostnames "dashboard" | default (printf "dashboard.%s" $host) | quote }}
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: incloud-web-gatekeeper
port: 8000
{{- end }}

View File

@@ -6,4 +6,4 @@ include ../../../hack/package.mk
update:
rm -rf templates
mkdir templates
kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd/experimental?ref=v1.2.0" > templates/crds-experimental.yaml
kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd/experimental?ref=v1.5.0" > templates/crds-experimental.yaml

View File

@@ -0,0 +1,30 @@
{{- $gatewayAPI := (index .Values._cluster "gateway-api") | default "false" }}
{{- $host := index .Values._cluster "root-host" }}
{{- $hostnames := .Values._cluster.hostnames | default dict }}
{{- $gatewayName := (index .Values._cluster "gateway-name") | default "cozystack" }}
{{- $gatewayNamespace := (index .Values._cluster "gateway-namespace") | default "cozy-gateway" }}
{{- $keycloakHost := .Values.ingress.host | default (index $hostnames "keycloak") | default (printf "keycloak.%s" $host) }}
{{- $oidcEnabled := (index .Values._cluster "oidc-enabled") | default "false" }}
{{- if and (eq $gatewayAPI "true") (eq $oidcEnabled "true") }}
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: keycloak
spec:
parentRefs:
- name: {{ $gatewayName }}
namespace: {{ $gatewayNamespace }}
sectionName: https-keycloak
hostnames:
- {{ $keycloakHost | quote }}
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: keycloak-http
port: 80
{{- end }}

View File

@@ -0,0 +1,24 @@
{{- $gatewayAPI := (index .Values._cluster "gateway-api") | default "false" }}
{{- $host := index .Values._cluster "root-host" }}
{{- $hostnames := .Values._cluster.hostnames | default dict }}
{{- $exposeServices := splitList "," ((index .Values._cluster "expose-services") | default "") }}
{{- $gatewayName := (index .Values._cluster "gateway-name") | default "cozystack" }}
{{- $gatewayNamespace := (index .Values._cluster "gateway-namespace") | default "cozy-gateway" }}
{{- if and (eq $gatewayAPI "true") (has "cdi-uploadproxy" $exposeServices) }}
apiVersion: gateway.networking.k8s.io/v1
kind: TLSRoute
metadata:
name: cdi-uploadproxy
spec:
parentRefs:
- name: {{ $gatewayName }}
namespace: {{ $gatewayNamespace }}
sectionName: tls-passthrough-cdi-uploadproxy
hostnames:
- {{ index $hostnames "cdi-uploadproxy" | default (printf "cdi-uploadproxy.%s" $host) | quote }}
rules:
- backendRefs:
- name: cdi-uploadproxy
port: 443
{{- end }}

View File

@@ -0,0 +1,24 @@
{{- $gatewayAPI := (index .Values._cluster "gateway-api") | default "false" }}
{{- $host := index .Values._cluster "root-host" }}
{{- $hostnames := .Values._cluster.hostnames | default dict }}
{{- $exposeServices := splitList "," ((index .Values._cluster "expose-services") | default "") }}
{{- $gatewayName := (index .Values._cluster "gateway-name") | default "cozystack" }}
{{- $gatewayNamespace := (index .Values._cluster "gateway-namespace") | default "cozy-gateway" }}
{{- if and (eq $gatewayAPI "true") (has "vm-exportproxy" $exposeServices) }}
apiVersion: gateway.networking.k8s.io/v1
kind: TLSRoute
metadata:
name: vm-exportproxy
spec:
parentRefs:
- name: {{ $gatewayName }}
namespace: {{ $gatewayNamespace }}
sectionName: tls-passthrough-vm-exportproxy
hostnames:
- {{ index $hostnames "vm-exportproxy" | default (printf "vm-exportproxy.%s" $host) | quote }}
rules:
- backendRefs:
- name: vm-exportproxy
port: 443
{{- end }}

View File

@@ -0,0 +1,75 @@
{{- $gatewayAPI := (index .Values._cluster "gateway-api") | default "false" }}
{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }}
{{- $gateway := .Values._namespace.gateway | default "" }}
{{- $host := .Values._namespace.host }}
{{- $alertaHost := printf "alerta.%s" (.Values.host | default $host) }}
{{- if and (eq $gatewayAPI "true") (ne $gateway "") }}
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: alerta
annotations:
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
spec:
gatewayClassName: cilium
infrastructure:
labels:
cozystack.io/gateway: {{ $gateway }}
listeners:
- name: http
protocol: HTTP
port: 80
hostname: {{ $alertaHost | quote }}
allowedRoutes:
namespaces:
from: Same
- name: https
protocol: HTTPS
port: 443
hostname: {{ $alertaHost | quote }}
tls:
mode: Terminate
certificateRefs:
- name: alerta-gateway-tls
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: alerta-redirect-to-https
spec:
parentRefs:
- name: alerta
sectionName: http
hostnames:
- {{ $alertaHost | quote }}
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: alerta
spec:
parentRefs:
- name: alerta
sectionName: https
hostnames:
- {{ $alertaHost | quote }}
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: alerta
port: 80
{{- end }}

View File

@@ -0,0 +1,75 @@
{{- $gatewayAPI := (index .Values._cluster "gateway-api") | default "false" }}
{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }}
{{- $gateway := .Values._namespace.gateway | default "" }}
{{- $host := .Values._namespace.host }}
{{- $grafanaHost := printf "grafana.%s" (.Values.host | default $host) }}
{{- if and (eq $gatewayAPI "true") (ne $gateway "") }}
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: grafana
annotations:
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
spec:
gatewayClassName: cilium
infrastructure:
labels:
cozystack.io/gateway: {{ $gateway }}
listeners:
- name: http
protocol: HTTP
port: 80
hostname: {{ $grafanaHost | quote }}
allowedRoutes:
namespaces:
from: Same
- name: https
protocol: HTTPS
port: 443
hostname: {{ $grafanaHost | quote }}
tls:
mode: Terminate
certificateRefs:
- name: grafana-gateway-tls
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: grafana-redirect-to-https
spec:
parentRefs:
- name: grafana
sectionName: http
hostnames:
- {{ $grafanaHost | quote }}
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: grafana
spec:
parentRefs:
- name: grafana
sectionName: https
hostnames:
- {{ $grafanaHost | quote }}
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: grafana-service
port: 3000
{{- end }}

View File

@@ -8,7 +8,7 @@ spec:
singular: tenant
plural: tenants
openAPISchema: |-
{"title":"Chart Values","type":"object","properties":{"etcd":{"description":"Deploy own Etcd cluster.","type":"boolean","default":false},"host":{"description":"The hostname used to access tenant services (defaults to using the tenant name as a subdomain for its parent tenant host).","type":"string","default":""},"ingress":{"description":"Deploy own Ingress Controller.","type":"boolean","default":false},"monitoring":{"description":"Deploy own Monitoring Stack.","type":"boolean","default":false},"resourceQuotas":{"description":"Define resource quotas for the tenant.","type":"object","default":{},"additionalProperties":{"pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}},"seaweedfs":{"description":"Deploy own SeaweedFS.","type":"boolean","default":false}}}
{"title":"Chart Values","type":"object","properties":{"etcd":{"description":"Deploy own Etcd cluster.","type":"boolean","default":false},"gateway":{"description":"Deploy own Gateway API gateway (separate LB for this tenant).","type":"boolean","default":false},"host":{"description":"The hostname used to access tenant services (defaults to using the tenant name as a subdomain for its parent tenant host).","type":"string","default":""},"ingress":{"description":"Deploy own Ingress Controller.","type":"boolean","default":false},"monitoring":{"description":"Deploy own Monitoring Stack.","type":"boolean","default":false},"resourceQuotas":{"description":"Define resource quotas for the tenant.","type":"object","default":{},"additionalProperties":{"pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}},"seaweedfs":{"description":"Deploy own SeaweedFS.","type":"boolean","default":false}}}
release:
prefix: tenant-
labels:
@@ -23,7 +23,7 @@ spec:
plural: Tenants
description: Separated tenant namespace
icon: PHN2ZyB3aWR0aD0iMTQ0IiBoZWlnaHQ9IjE0NCIgdmlld0JveD0iMCAwIDE0NCAxNDQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxNDQiIGhlaWdodD0iMTQ0IiByeD0iMjQiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcl82ODdfMzQwMykiLz4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzY4N18zNDAzKSI+CjxwYXRoIGQ9Ik03MiAyOUM2Ni4zOTI2IDI5IDYxLjAxNDggMzEuMjM4OCA1Ny4wNDk3IDM1LjIyNEM1My4wODQ3IDM5LjIwOTEgNTAuODU3MSA0NC42MTQxIDUwLjg1NzEgNTAuMjVDNTAuODU3MSA1NS44ODU5IDUzLjA4NDcgNjEuMjkwOSA1Ny4wNDk3IDY1LjI3NkM2MS4wMTQ4IDY5LjI2MTIgNjYuMzkyNiA3MS41IDcyIDcxLjVDNzcuNjA3NCA3MS41IDgyLjk4NTIgNjkuMjYxMiA4Ni45NTAzIDY1LjI3NkM5MC45MTUzIDYxLjI5MDkgOTMuMTQyOSA1NS44ODU5IDkzLjE0MjkgNTAuMjVDOTMuMTQyOSA0NC42MTQxIDkwLjkxNTMgMzkuMjA5MSA4Ni45NTAzIDM1LjIyNEM4Mi45ODUyIDMxLjIzODggNzcuNjA3NCAyOSA3MiAyOVpNNjAuOTgyNiA4My4zMDM3QzYwLjQ1NCA4Mi41ODk4IDU5LjU5NTEgODIuMTkxNCA1OC43MTk2IDgyLjI3NDRDNDUuMzg5NyA4My43MzU0IDM1IDk1LjEwNzQgMzUgMTA4LjkwM0MzNSAxMTEuNzI2IDM3LjI3OTUgMTE0IDQwLjA3MSAxMTRIMTAzLjkyOUMxMDYuNzM3IDExNCAxMDkgMTExLjcwOSAxMDkgMTA4LjkwM0MxMDkgOTUuMTA3NCA5OC42MTAzIDgzLjc1MiA4NS4yNjM4IDgyLjI5MUM4NC4zODg0IDgyLjE5MTQgODMuNTI5NSA4Mi42MDY0IDgzLjAwMDkgODMuMzIwM0w3NC4wOTc4IDk1LjI0MDJDNzMuMDQwNiA5Ni42NTE0IDcwLjkyNjMgOTYuNjUxNCA2OS44NjkyIDk1LjI0MDJMNjAuOTY2MSA4My4zMjAzTDYwLjk4MjYgODMuMzAzN1oiIGZpbGw9ImJsYWNrIi8+CjwvZz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl82ODdfMzQwMyIgeDE9IjcyIiB5MT0iMTQ0IiB4Mj0iLTEuMjgxN2UtMDUiIHkyPSI0IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiNDMEQ2RkYiLz4KPHN0b3Agb2Zmc2V0PSIwLjMiIHN0b3AtY29sb3I9IiNDNERBRkYiLz4KPHN0b3Agb2Zmc2V0PSIwLjY1IiBzdG9wLWNvbG9yPSIjRDNFOUZGIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI0U5RkZGRiIvPgo8L2xpbmVhckdyYWRpZW50Pgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzY4N18zNDAzIj4KPHJlY3Qgd2lkdGg9Ijc0IiBoZWlnaHQ9Ijg1IiBmaWxsPSJ3aGl0ZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzUgMjkpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==
keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "host"], ["spec", "etcd"], ["spec", "monitoring"], ["spec", "ingress"], ["spec", "seaweedfs"], ["spec", "resourceQuotas"]]
keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "host"], ["spec", "etcd"], ["spec", "monitoring"], ["spec", "ingress"], ["spec", "gateway"], ["spec", "seaweedfs"], ["spec", "resourceQuotas"]]
secrets:
exclude: []
include: []