Retire cert-manager direct deployment repository

This commit is contained in:
2026-10-19 08:05:52 +02:00
parent 40f4a7d19e
commit d217f117fc
11 changed files with 10 additions and 297 deletions
-51
View File
@@ -1,51 +0,0 @@
name: Validate and deploy cert-manager configuration
on: [push, pull_request]
env:
KUBECTL_VERSION: v1.36.3
KUBERNETES_API: https://host.containers.internal:6443
KUBERNETES_TLS_SERVER_NAME: 192.168.0.2
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: bash test.sh
deploy:
if: gitea.ref == 'refs/heads/main'
needs: validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install kubectl
run: |
curl -fsSL -o "${RUNNER_TEMP}/kubectl" "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl"
chmod 0700 "${RUNNER_TEMP}/kubectl"
- name: Configure Kubernetes access
env:
KUBE_CONFIG_BASE64: ${{ secrets.KUBE_CONFIG_BASE64 }}
run: |
test -n "${KUBE_CONFIG_BASE64}"
printf '%s' "${KUBE_CONFIG_BASE64}" | base64 -d > "${RUNNER_TEMP}/kubeconfig"
chmod 0600 "${RUNNER_TEMP}/kubeconfig"
export KUBECONFIG="${RUNNER_TEMP}/kubeconfig"
"${RUNNER_TEMP}/kubectl" config set-cluster cluster --server="${KUBERNETES_API}" --tls-server-name="${KUBERNETES_TLS_SERVER_NAME}"
- name: Apply and verify
run: |
export KUBECONFIG="${RUNNER_TEMP}/kubeconfig"
for file in cloudflare.yaml http-issuer.yaml certificates.yaml; do
"${RUNNER_TEMP}/kubectl" apply --server-side --force-conflicts --dry-run=server -f "$file"
done
for file in cloudflare.yaml http-issuer.yaml certificates.yaml; do
"${RUNNER_TEMP}/kubectl" apply --server-side --force-conflicts -f "$file"
done
for issuer in letsencrypt-dns letsencrypt-http; do
for attempt in {1..60}; do
ready=$("${RUNNER_TEMP}/kubectl" get clusterissuer "$issuer" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}')
[[ "$ready" == True ]] && break
[[ "$attempt" != 60 ]] || exit 1
sleep 5
done
done
for certificate in brunner-ninja watschn-studio brgkepler-com gschissenes-equipment; do
test "$("${RUNNER_TEMP}/kubectl" -n default get certificate "$certificate" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}')" = True
done
+10 -10
View File
@@ -1,12 +1,12 @@
# cert-manager on Kubernetes
# Archived cert-manager deployment repository
The operator is pinned to chart/app `v1.21.1` and remains an administrator
upgrade because it owns CRDs, admission webhooks, and cluster-wide RBAC. Gitea
Actions validates and deploys only the two exact ClusterIssuers and four exact
Certificates; it cannot read Secrets, create/delete resources, or modify the
operator.
This legacy repository is archived and is no longer a deployment source. Argo
CD in [`homelab-gitops`](https://code.brunner.ninja/feedc0de/homelab-gitops/src/branch/main/apps/cert-manager)
is the sole owner of the Jetstack cert-manager chart, homelab ClusterIssuers,
and centrally managed Certificates.
`cloudflare-api-credentials.yaml` is intentionally ignored. Copy the `.example`,
insert the existing token, and run `./install.sh`; when the file is absent the
installer preserves the existing live Secret. Run `./create-ci-kubeconfig.sh`
once and save only its final line as repository secret `KUBE_CONFIG_BASE64`.
The former direct Gitea Actions deploy workflow and its Kubernetes deployer
credentials/RBAC have been retired. Do not use historical manifests or scripts
from this repository to change the live cluster. Make normal changes in
`homelab-gitops`; use the documented Argo CD bootstrap/recovery procedure only
if Argo itself is unavailable.
-60
View File
@@ -1,60 +0,0 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: brunner-ninja
namespace: default
spec:
secretName: brunner-ninja-tls
issuerRef:
name: letsencrypt-dns
kind: ClusterIssuer
dnsNames:
- brunner.ninja
- "*.brunner.ninja"
privateKey:
rotationPolicy: Always
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: watschn-studio
namespace: default
spec:
secretName: watschn-studio-tls
issuerRef:
name: letsencrypt-dns
kind: ClusterIssuer
dnsNames:
- watschn.studio
privateKey:
rotationPolicy: Always
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: brgkepler-com
namespace: default
spec:
secretName: brgkepler-com-tls
issuerRef:
name: letsencrypt-http
kind: ClusterIssuer
dnsNames:
- brgkepler.com
privateKey:
rotationPolicy: Always
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: gschissenes-equipment
namespace: default
spec:
secretName: gschissenes-equipment-tls
issuerRef:
name: letsencrypt-http
kind: ClusterIssuer
dnsNames:
- gschissenes.equipment
privateKey:
rotationPolicy: Always
-46
View File
@@ -1,46 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: cert-manager-config-deployer
namespace: cert-manager
automountServiceAccountToken: false
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cert-manager-config-deployer
rules:
- apiGroups: [cert-manager.io]
resources: [clusterissuers]
resourceNames: [letsencrypt-dns, letsencrypt-http]
verbs: [get, patch, update]
- apiGroups: [cert-manager.io]
resources: [certificates]
resourceNames: [brunner-ninja, watschn-studio, brgkepler-com, gschissenes-equipment]
verbs: [get, patch, update]
- apiGroups: [apps]
resources: [deployments]
resourceNames: [cert-manager, cert-manager-cainjector, cert-manager-webhook]
verbs: [get]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cert-manager-config-deployer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cert-manager-config-deployer
subjects:
- kind: ServiceAccount
name: cert-manager-config-deployer
namespace: cert-manager
---
apiVersion: v1
kind: Secret
metadata:
name: cert-manager-config-deployer-token
namespace: cert-manager
annotations:
kubernetes.io/service-account.name: cert-manager-config-deployer
type: kubernetes.io/service-account-token
-8
View File
@@ -1,8 +0,0 @@
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-token-secret
namespace: cert-manager
type: Opaque
stringData:
api-token: REPLACE_WITH_CLOUDFLARE_API_TOKEN
-17
View File
@@ -1,17 +0,0 @@
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-dns
spec:
acme:
email: daniel@brunner.ninja
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-dns-account-key
solvers:
- dns01:
cloudflare:
email: daniel@brunner.ninja
apiKeySecretRef:
name: cloudflare-api-credentials
key: apiKey
-26
View File
@@ -1,26 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
project_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
namespace=cert-manager
service_account=cert-manager-config-deployer
secret=cert-manager-config-deployer-token
ssh_host=${KUBECTL_SSH_HOST:-}
ssh_config=${SSH_CONFIG:-}
cluster_kubectl() { if [[ -n "$ssh_host" ]]; then if [[ -n "$ssh_config" ]]; then ssh -F "$ssh_config" "$ssh_host" kubectl "$@"; else ssh "$ssh_host" kubectl "$@"; fi; else kubectl "$@"; fi; }
if [[ -n "$ssh_host" ]]; then cluster_kubectl apply -f - < "$project_dir/ci-deployer.yaml" >&2; else cluster_kubectl apply -f "$project_dir/ci-deployer.yaml" >&2; fi
for attempt in {1..30}; do
if cluster_kubectl -n "$namespace" get secret "$secret" -o jsonpath='{.data.token}' 2>/dev/null | grep -q .; then break; fi
[[ "$attempt" != 30 ]] || { echo 'Timed out waiting for service-account token' >&2; exit 1; }
sleep 1
done
work=$(mktemp -d); trap 'rm -rf "$work"' EXIT
server=$(cluster_kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
cluster_kubectl -n "$namespace" get secret "$secret" -o jsonpath='{.data.ca\.crt}' | base64 -d > "$work/ca.crt"
token=$(cluster_kubectl -n "$namespace" get secret "$secret" -o jsonpath='{.data.token}' | base64 -d)
export KUBECONFIG="$work/config"
kubectl config set-cluster cluster --server="$server" --certificate-authority="$work/ca.crt" --embed-certs=true >/dev/null
kubectl config set-credentials "$service_account" --token="$token" >/dev/null
kubectl config set-context cert-manager --cluster=cluster --user="$service_account" --namespace="$namespace" >/dev/null
kubectl config use-context cert-manager >/dev/null
echo 'Store this line as Gitea Actions secret KUBE_CONFIG_BASE64; do not commit it.' >&2
base64 -w0 "$KUBECONFIG"; printf '\n'
-14
View File
@@ -1,14 +0,0 @@
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-http
spec:
acme:
email: daniel@brunner.ninja
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-http-account-key
solvers:
- http01:
ingress:
ingressClassName: traefik
-45
View File
@@ -1,45 +0,0 @@
#!/bin/sh
set -eu
CERT_MANAGER_VERSION=v1.21.1
CERT_MANAGER_CHART=oci://quay.io/jetstack/charts/cert-manager
PROJECT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
CREDENTIALS_FILE=${CLOUDFLARE_CREDENTIALS_FILE:-$PROJECT_DIR/cloudflare-api-credentials.yaml}
kubectl create namespace cert-manager --dry-run=client -o yaml | kubectl apply -f -
if [ -f "$CREDENTIALS_FILE" ]; then
if grep -q 'REPLACE_WITH_' "$CREDENTIALS_FILE"; then
echo "Refusing placeholder credentials in $CREDENTIALS_FILE" >&2
exit 1
fi
kubectl apply -f "$CREDENTIALS_FILE"
elif kubectl -n cert-manager get secret cloudflare-api-token-secret >/dev/null 2>&1; then
echo "Keeping existing cert-manager/cloudflare-api-token-secret Secret."
else
echo "Missing $CREDENTIALS_FILE and the live Cloudflare Secret." >&2
exit 1
fi
helm upgrade --install cert-manager "$CERT_MANAGER_CHART" \
--version "$CERT_MANAGER_VERSION" \
--namespace cert-manager \
--create-namespace \
--take-ownership \
--force-conflicts \
--rollback-on-failure \
--wait \
--timeout 10m \
-f "$PROJECT_DIR/values.yaml"
kubectl apply -f "$PROJECT_DIR/cloudflare.yaml"
kubectl apply -f "$PROJECT_DIR/http-issuer.yaml"
kubectl wait --for=condition=Ready clusterissuer/letsencrypt-dns --timeout=120s
kubectl wait --for=condition=Ready clusterissuer/letsencrypt-http --timeout=120s
kubectl apply -f "$PROJECT_DIR/certificates.yaml"
kubectl wait --for=condition=Ready certificate/brunner-ninja --namespace default --timeout=10m
kubectl wait --for=condition=Ready certificate/watschn-studio --namespace default --timeout=10m
kubectl wait --for=condition=Ready certificate/brgkepler-com --namespace default --timeout=10m
kubectl wait --for=condition=Ready certificate/gschissenes-equipment --namespace default --timeout=10m
-14
View File
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
sh -n "$dir/install.sh"
bash -n "$dir/create-ci-kubeconfig.sh" "$dir/test.sh"
grep -Fxq 'cloudflare-api-credentials.yaml' "$dir/.gitignore"
if grep -R -q 'cloudflare-api-credentials' "$dir/.gitea/workflows"; then
echo 'CI must never read or apply the ignored credential manifest.' >&2
exit 1
fi
image=ghcr.io/yannh/kubeconform:v0.7.0
for file in cloudflare.yaml http-issuer.yaml certificates.yaml; do docker run --rm -i "$image" -strict -exit-on-error -ignore-missing-schemas -summary < "$dir/$file"; done
docker run --rm -i "$image" -strict -exit-on-error -summary < "$dir/ci-deployer.yaml"
echo 'cert-manager configuration is valid; no credential file is tracked by CI.'
-6
View File
@@ -1,6 +0,0 @@
crds:
enabled: true
extraArgs:
- --dns01-recursive-nameservers-only
- --dns01-recursive-nameservers=1.1.1.1:53,8.8.8.8:53