diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index eb826cf0957785083b776d8f38458848a7d6a38c..63ffb262855169327a8403fbd9fc0665296a76e6 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -330,8 +330,13 @@ setup-stackspin:
     - cp install/kustomization.yaml ${CLUSTER_DIR}
     - kubectl create namespace flux-system
     - kubectl apply -k ${CLUSTER_DIR}
+    # Add an override so cert-manager uses the ZeroSSL ClusterIssuer
+    - kubectl create namespace cert-manager
+    - kubectl apply -n cert-manager -f ./install/overrides/stackspin-cert-manager-override.yaml
     # Install flux and general, non-app specific secrets
     - bash ./install/install-stackspin.sh
+    # Install custom ClusterIssuer for ZeroSSL production certificates
+    - bash ./.gitlab/ci_scripts/install_zerossl_issuer.sh
   extends:
     - .ssh_setup
     - .report_artifacts
diff --git a/.gitlab/ci_scripts/install_zerossl_issuer.sh b/.gitlab/ci_scripts/install_zerossl_issuer.sh
new file mode 100755
index 0000000000000000000000000000000000000000..855cc440a1420cda803c030f9b03d9bd077f9d0f
--- /dev/null
+++ b/.gitlab/ci_scripts/install_zerossl_issuer.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+#
+# Waits until cert-manager HelmRelease is ready, and then installs a ZeroSSL
+# ClusterIssuer with our credentials into the cert-manager namespace
+#
+# Usage:
+#
+#   ./install_zerossl_issuer.sh
+set -euo pipefail
+
+# Create secret with HMAC key
+kubectl -n cert-manager create secret generic zerossl-eabsecret --from-literal "secret=${ZEROSSL_EAB_HMAC_KEY}"
+
+# Wait until cert-manager is ready
+"$(dirname "$0")/retry_cmd_until_success.sh" 30 10 "flux get helmrelease -n cert-manager --status-selector ready=true --no-header | grep cert-manager"
+
+# Add ZeroSSL ClusterIssuer
+kubectl apply -n cert-manager -f - <<EOF
+---
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+  name: zerossl-issuer
+spec:
+  acme:
+    # The ACME server URL
+    server: https://acme.zerossl.com/v2/DV90
+    externalAccountBinding:
+      keyID: ${ZEROSSL_EAB_KID}
+      keySecretRef:
+        name: zerossl-eabsecret
+        key: secret
+      keyAlgorithm: HS256
+    # Name of a secret used to store the ACME account private key
+    privateKeySecretRef:
+      name: zerossl-prod
+    solvers:
+      - http01:
+          ingress:
+            class: nginx
+EOF
diff --git a/install/overrides/stackspin-cert-manager-override.yaml b/install/overrides/stackspin-cert-manager-override.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b9b845f0e198d60d5b1c9d132bb8d86c6e483bae
--- /dev/null
+++ b/install/overrides/stackspin-cert-manager-override.yaml
@@ -0,0 +1,10 @@
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: stackspin-cert-manager-values
+data:
+  values.yaml: |
+    ingressShim:
+      defaultIssuerName: zerossl-issuer
+      defaultIssuerKind: ClusterIssuer