From dd139621f9011cd38a4edcf2b2aa3781d114b0a1 Mon Sep 17 00:00:00 2001 From: clofour <208706398+clofour@users.noreply.github.com> Date: Sun, 19 Apr 2026 15:00:19 +0200 Subject: [PATCH 1/2] Implement wildcard certificate --- .../chart/templates/cluster-issuer.yaml | 8 ++- helm/cluster-issuer/chart/values.yaml | 3 +- helm/gitlab/values.yaml | 3 +- helm/wildcard-certificate/chart/.helmignore | 23 +++++++ helm/wildcard-certificate/chart/Chart.yaml | 24 +++++++ .../chart/templates/_helpers.tpl | 62 +++++++++++++++++++ .../chart/templates/wildcard-certificate.yaml | 21 +++++++ helm/wildcard-certificate/chart/values.yaml | 4 ++ helm/wildcard-certificate/values.yaml | 2 + terraform/dns.tf | 9 ++- terraform/helm.tf | 52 +++++++++++----- terraform/kubernetes.tf | 18 +++--- 12 files changed, 197 insertions(+), 32 deletions(-) create mode 100644 helm/wildcard-certificate/chart/.helmignore create mode 100644 helm/wildcard-certificate/chart/Chart.yaml create mode 100644 helm/wildcard-certificate/chart/templates/_helpers.tpl create mode 100644 helm/wildcard-certificate/chart/templates/wildcard-certificate.yaml create mode 100644 helm/wildcard-certificate/chart/values.yaml create mode 100644 helm/wildcard-certificate/values.yaml diff --git a/helm/cluster-issuer/chart/templates/cluster-issuer.yaml b/helm/cluster-issuer/chart/templates/cluster-issuer.yaml index 18ea78c..3a0b539 100644 --- a/helm/cluster-issuer/chart/templates/cluster-issuer.yaml +++ b/helm/cluster-issuer/chart/templates/cluster-issuer.yaml @@ -9,6 +9,8 @@ spec: privateKeySecretRef: name: {{ .Values.privateKeySecretName }} solvers: - - http01: - ingress: - ingressClassName: {{ .Values.ingressClass }} \ No newline at end of file + - dns01: + digitalocean: + tokenSecretRef: + name: {{ .Values.secretName }} + key: {{ .Values.secretKey }} \ No newline at end of file diff --git a/helm/cluster-issuer/chart/values.yaml b/helm/cluster-issuer/chart/values.yaml index 4663d1a..bcd2cf6 100644 --- a/helm/cluster-issuer/chart/values.yaml +++ b/helm/cluster-issuer/chart/values.yaml @@ -1,4 +1,5 @@ name: letsencrypt server: https://acme-v02.api.letsencrypt.org/directory privateKeySecretName: letsencrypt-account-key -ingressClass: nginx \ No newline at end of file +secretName: do-dns-secret +secretKey: password \ No newline at end of file diff --git a/helm/gitlab/values.yaml b/helm/gitlab/values.yaml index a85949e..0a9a04a 100644 --- a/helm/gitlab/values.yaml +++ b/helm/gitlab/values.yaml @@ -18,8 +18,7 @@ global: class: nginx tls: enabled: true - annotations: - cert-manager.io/cluster-issuer: letsencrypt + secretName: "wildcard-certificate" psql: host: ${postgres_host} diff --git a/helm/wildcard-certificate/chart/.helmignore b/helm/wildcard-certificate/chart/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/helm/wildcard-certificate/chart/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/wildcard-certificate/chart/Chart.yaml b/helm/wildcard-certificate/chart/Chart.yaml new file mode 100644 index 0000000..589409c --- /dev/null +++ b/helm/wildcard-certificate/chart/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: wildcard-certificate +description: Wildcard Certificate + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/wildcard-certificate/chart/templates/_helpers.tpl b/helm/wildcard-certificate/chart/templates/_helpers.tpl new file mode 100644 index 0000000..dd5ba3b --- /dev/null +++ b/helm/wildcard-certificate/chart/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "cluster-issuer.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "cluster-issuer.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "cluster-issuer.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "cluster-issuer.labels" -}} +helm.sh/chart: {{ include "cluster-issuer.chart" . }} +{{ include "cluster-issuer.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "cluster-issuer.selectorLabels" -}} +app.kubernetes.io/name: {{ include "cluster-issuer.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "cluster-issuer.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "cluster-issuer.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/wildcard-certificate/chart/templates/wildcard-certificate.yaml b/helm/wildcard-certificate/chart/templates/wildcard-certificate.yaml new file mode 100644 index 0000000..833ac2a --- /dev/null +++ b/helm/wildcard-certificate/chart/templates/wildcard-certificate.yaml @@ -0,0 +1,21 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ .Values.name }} + namespace: {{ .Release.namespace }} +spec: + secretName: {{ .Values.secretName }} + issuerRef: + name: {{ .Values.issuer }} + kind: ClusterIssuer + commonName: {{ .Values.domain }} + dnsNames: + - {{ .Values.domain }} + - "*.{{ .Values.domain }}" + secretTemplate: + annotations: + {{- if .Values.reflectNamespaces }} + reflector.v1.k8s.emberstack.com/reflection-allowed: "true" + reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true" + reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: {{ .Values.reflectNamespaces }} + {{- end}} diff --git a/helm/wildcard-certificate/chart/values.yaml b/helm/wildcard-certificate/chart/values.yaml new file mode 100644 index 0000000..4db2fb2 --- /dev/null +++ b/helm/wildcard-certificate/chart/values.yaml @@ -0,0 +1,4 @@ +name: wildcard-certificate +namespace: default +secretName: wildcard-certificate +issuer: letsencrypt diff --git a/helm/wildcard-certificate/values.yaml b/helm/wildcard-certificate/values.yaml new file mode 100644 index 0000000..1311599 --- /dev/null +++ b/helm/wildcard-certificate/values.yaml @@ -0,0 +1,2 @@ +domain: ${domain} +reflectNamespaces: ${reflectNamespaces} \ No newline at end of file diff --git a/terraform/dns.tf b/terraform/dns.tf index 494a3ff..a7bf822 100644 --- a/terraform/dns.tf +++ b/terraform/dns.tf @@ -1,17 +1,20 @@ locals { lb_ip = try(data.kubernetes_service_v1.ingress_nginx.status[0].load_balancer[0].ingress[0].ip, null) + records = toset([ + var.gitlab_host, var.registry_host + ]) } resource "digitalocean_domain" "main" { name = var.domain_name } -resource "digitalocean_record" "gitlab" { - count = 1 +resource "digitalocean_record" "main" { + for_each = local.records domain = digitalocean_domain.main.name type = "A" - name = var.gitlab_host + name = each.key value = local.lb_ip ttl = 300 } \ No newline at end of file diff --git a/terraform/helm.tf b/terraform/helm.tf index 35ec2a1..2273cd1 100644 --- a/terraform/helm.tf +++ b/terraform/helm.tf @@ -1,18 +1,26 @@ -resource "helm_release" "external_dns" { - name = "external-dns" - namespace = kubernetes_namespace_v1.external_dns.metadata[0].name - repository = "https://kubernetes-sigs.github.io/external-dns" - chart = "external-dns" - version = "1.20.0" +# resource "helm_release" "external_dns" { +# name = "external-dns" +# namespace = kubernetes_namespace_v1.external_dns.metadata[0].name +# repository = "https://kubernetes-sigs.github.io/external-dns" +# chart = "external-dns" +# version = "1.20.0" - values = [ - file("${path.module}/../helm/external-dns/values.yaml") - ] +# values = [ +# file("${path.module}/../helm/external-dns/values.yaml") +# ] - depends_on = [ - kubernetes_namespace_v1.external_dns, - kubernetes_secret_v1.external_dns_do_secret - ] +# depends_on = [ +# kubernetes_namespace_v1.external_dns, +# kubernetes_secret_v1.external_dns_do_secret +# ] +# } + +resource "helm_release" "reflector" { + name = "reflector" + namespace = "kube-system" + repository = "https://emberstack.github.io/helm-charts" + chart = "reflector" + version = "v10.0.35" } resource "helm_release" "cert_manager" { @@ -42,6 +50,22 @@ resource "helm_release" "cluster_issuer" { depends_on = [helm_release.cert_manager] } +resource "helm_release" "wildcard_certificate" { + name = "wildcard-certificate" + namespace = kubernetes_namespace_v1.cert_manager.metadata[0].name + chart = "${path.module}/../helm/wildcard-certificate/chart" + + values = [ + templatefile("${path.module}/../helm/wildcard-certificate/values.yaml", + { + domain = var.domain_name + reflectNamespaces = kubernetes_namespace_v1.gitlab.metadata[0].name + }) + ] + + depends_on = [helm_release.cert_manager] +} + resource "helm_release" "ingress_nginx" { name = "ingress-nginx" namespace = kubernetes_namespace_v1.ingress_nginx.metadata[0].name @@ -90,7 +114,7 @@ resource "helm_release" "gitlab" { helm_release.cert_manager, helm_release.cluster_issuer, helm_release.ingress_nginx, - digitalocean_record.gitlab, + digitalocean_record.main, kubernetes_secret_v1.gitlab_initial_root_password, kubernetes_secret_v1.gitlab_postgres, kubernetes_secret_v1.gitlab_redis, diff --git a/terraform/kubernetes.tf b/terraform/kubernetes.tf index 17f1cf7..78a84dc 100644 --- a/terraform/kubernetes.tf +++ b/terraform/kubernetes.tf @@ -1,10 +1,10 @@ -resource "kubernetes_namespace_v1" "external_dns" { - metadata { - name = "external-dns" - } +# resource "kubernetes_namespace_v1" "external_dns" { +# metadata { +# name = "external-dns" +# } - depends_on = [ digitalocean_kubernetes_cluster.main ] -} +# depends_on = [ digitalocean_kubernetes_cluster.main ] +# } resource "kubernetes_namespace_v1" "ingress_nginx" { metadata { @@ -34,10 +34,10 @@ resource "random_password" "gitlab_root" { length = 64 } -resource "kubernetes_secret_v1" "external_dns_do_secret" { +resource "kubernetes_secret_v1" "do_dns_secret" { metadata { - name = "external-dns-do-secret" - namespace = kubernetes_namespace_v1.external_dns.metadata[0].name + name = "do-dns-secret" + namespace = kubernetes_namespace_v1.cert_manager.metadata[0].name } data = { From b495932fa6369e6440e8ba7e0f33a2b154cf1fb4 Mon Sep 17 00:00:00 2001 From: clofour <208706398+clofour@users.noreply.github.com> Date: Sun, 19 Apr 2026 17:49:41 +0200 Subject: [PATCH 2/2] Bug fixes --- helm/cluster-issuer/chart/Chart.yaml | 2 +- helm/wildcard-certificate/chart/Chart.yaml | 2 +- .../chart/templates/_helpers.tpl | 20 +++++++++---------- .../chart/templates/wildcard-certificate.yaml | 4 ++-- helm/wildcard-certificate/chart/values.yaml | 1 - helm/wildcard-certificate/values.yaml | 2 +- terraform/helm.tf | 6 ++++-- 7 files changed, 19 insertions(+), 18 deletions(-) diff --git a/helm/cluster-issuer/chart/Chart.yaml b/helm/cluster-issuer/chart/Chart.yaml index ffeea63..d8842a0 100644 --- a/helm/cluster-issuer/chart/Chart.yaml +++ b/helm/cluster-issuer/chart/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "1.16.0" +appVersion: "0.1.0" diff --git a/helm/wildcard-certificate/chart/Chart.yaml b/helm/wildcard-certificate/chart/Chart.yaml index 589409c..4a65d0b 100644 --- a/helm/wildcard-certificate/chart/Chart.yaml +++ b/helm/wildcard-certificate/chart/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "1.16.0" +appVersion: "0.1.0" diff --git a/helm/wildcard-certificate/chart/templates/_helpers.tpl b/helm/wildcard-certificate/chart/templates/_helpers.tpl index dd5ba3b..82469f0 100644 --- a/helm/wildcard-certificate/chart/templates/_helpers.tpl +++ b/helm/wildcard-certificate/chart/templates/_helpers.tpl @@ -1,7 +1,7 @@ {{/* Expand the name of the chart. */}} -{{- define "cluster-issuer.name" -}} +{{- define "wildcard-certificate.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} @@ -10,7 +10,7 @@ Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} -{{- define "cluster-issuer.fullname" -}} +{{- define "wildcard-certificate.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} @@ -26,16 +26,16 @@ If release name contains chart name it will be used as a full name. {{/* Create chart name and version as used by the chart label. */}} -{{- define "cluster-issuer.chart" -}} +{{- define "wildcard-certificate.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Common labels */}} -{{- define "cluster-issuer.labels" -}} -helm.sh/chart: {{ include "cluster-issuer.chart" . }} -{{ include "cluster-issuer.selectorLabels" . }} +{{- define "wildcard-certificate.labels" -}} +helm.sh/chart: {{ include "wildcard-certificate.chart" . }} +{{ include "wildcard-certificate.selectorLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} @@ -45,17 +45,17 @@ app.kubernetes.io/managed-by: {{ .Release.Service }} {{/* Selector labels */}} -{{- define "cluster-issuer.selectorLabels" -}} -app.kubernetes.io/name: {{ include "cluster-issuer.name" . }} +{{- define "wildcard-certificate.selectorLabels" -}} +app.kubernetes.io/name: {{ include "wildcard-certificate.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} {{/* Create the name of the service account to use */}} -{{- define "cluster-issuer.serviceAccountName" -}} +{{- define "wildcard-certificate.serviceAccountName" -}} {{- if .Values.serviceAccount.create }} -{{- default (include "cluster-issuer.fullname" .) .Values.serviceAccount.name }} +{{- default (include "wildcard-certificate.fullname" .) .Values.serviceAccount.name }} {{- else }} {{- default "default" .Values.serviceAccount.name }} {{- end }} diff --git a/helm/wildcard-certificate/chart/templates/wildcard-certificate.yaml b/helm/wildcard-certificate/chart/templates/wildcard-certificate.yaml index 833ac2a..0e512a1 100644 --- a/helm/wildcard-certificate/chart/templates/wildcard-certificate.yaml +++ b/helm/wildcard-certificate/chart/templates/wildcard-certificate.yaml @@ -2,7 +2,7 @@ apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: {{ .Values.name }} - namespace: {{ .Release.namespace }} + namespace: {{ .Release.Namespace }} spec: secretName: {{ .Values.secretName }} issuerRef: @@ -17,5 +17,5 @@ spec: {{- if .Values.reflectNamespaces }} reflector.v1.k8s.emberstack.com/reflection-allowed: "true" reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true" - reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: {{ .Values.reflectNamespaces }} + reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "{{ .Values.reflectNamespaces }}" {{- end}} diff --git a/helm/wildcard-certificate/chart/values.yaml b/helm/wildcard-certificate/chart/values.yaml index 4db2fb2..a011a11 100644 --- a/helm/wildcard-certificate/chart/values.yaml +++ b/helm/wildcard-certificate/chart/values.yaml @@ -1,4 +1,3 @@ name: wildcard-certificate -namespace: default secretName: wildcard-certificate issuer: letsencrypt diff --git a/helm/wildcard-certificate/values.yaml b/helm/wildcard-certificate/values.yaml index 1311599..4edfcdf 100644 --- a/helm/wildcard-certificate/values.yaml +++ b/helm/wildcard-certificate/values.yaml @@ -1,2 +1,2 @@ domain: ${domain} -reflectNamespaces: ${reflectNamespaces} \ No newline at end of file +reflectNamespaces: "${reflectNamespaces}" \ No newline at end of file diff --git a/terraform/helm.tf b/terraform/helm.tf index 2273cd1..2a37a53 100644 --- a/terraform/helm.tf +++ b/terraform/helm.tf @@ -20,7 +20,7 @@ resource "helm_release" "reflector" { namespace = "kube-system" repository = "https://emberstack.github.io/helm-charts" chart = "reflector" - version = "v10.0.35" + version = "10.0.35" } resource "helm_release" "cert_manager" { @@ -63,7 +63,7 @@ resource "helm_release" "wildcard_certificate" { }) ] - depends_on = [helm_release.cert_manager] + depends_on = [helm_release.cert_manager, helm_release.cluster_issuer, helm_release.reflector] } resource "helm_release" "ingress_nginx" { @@ -112,6 +112,8 @@ resource "helm_release" "gitlab" { digitalocean_database_connection_pool.main, digitalocean_database_cluster.valkey, helm_release.cert_manager, + helm_release.wildcard_certificate, + helm_release.reflector, helm_release.cluster_issuer, helm_release.ingress_nginx, digitalocean_record.main,