Files
home-docker/terraform/argocd.tf
T
2026-07-04 11:34:02 +10:00

236 lines
5.8 KiB
Terraform

resource "kubernetes_namespace" "argocd" {
metadata {
name = "argocd"
}
}
# Install cert-manager
resource "helm_release" "cert_manager" {
name = "cert-manager"
repository = "https://charts.jetstack.io"
chart = "cert-manager"
version = "v1.20.2"
namespace = "cert-manager"
create_namespace = true
set {
name = "installCRDs"
value = "true"
}
set {
name = "prometheus.enabled"
value = "false"
}
set {
name = "webhook.timeoutSeconds"
value = "4"
}
}
# Install nginx-ingress
resource "helm_release" "ingress_nginx" {
name = "ingress-nginx"
repository = "https://kubernetes.github.io/ingress-nginx"
chart = "ingress-nginx"
version = "4.14.2"
namespace = "ingress-nginx"
create_namespace = true
set {
name = "controller.service.type"
value = "NodePort"
}
set {
name = "controller.service.nodePorts.http"
value = "80"
}
set {
name = "controller.service.nodePorts.https"
value = "443"
}
set {
name = "controller.ingressClassResource.default"
value = "true"
}
set {
name = "controller.watchIngressWithoutClass"
value = "true"
}
set {
name = "controller.hostPort.enabled"
value = "true"
}
set {
name = "controller.service.externalTrafficPolicy"
value = "Local"
}
set {
name = "controller.metrics.enabled"
value = "true"
}
set {
name = "controller.metrics.serviceMonitor.enabled"
value = "true"
}
set {
name = "controller.metrics.serviceMonitor.namespace"
value = "prometheus"
}
set {
name = "controller.metrics.serviceMonitor.additionalLabels.release"
value = "prometheus"
}
set {
name = "controller.metrics.serviceMonitor.additionalLabels.app"
value = "ingress-nginx"
}
}
# Check for cert-manager CRDs before proceeding
resource "null_resource" "wait_for_cert_manager_crds" {
depends_on = [helm_release.cert_manager]
provisioner "local-exec" {
command = <<-EOT
# Wait for cert-manager to be ready
echo "Waiting for cert-manager CRDs to be available..."
# Wait for the webhook to be ready first
echo "Waiting for cert-manager webhook pod to be ready..."
kubectl -n cert-manager wait --for=condition=ready pod -l app=webhook --timeout=120s
# Try up to 10 times with increasing sleep between attempts
for i in $(seq 1 10); do
echo "Attempt $i to verify cert-manager CRDs..."
# Check if the ClusterIssuer CRD exists
if kubectl get crd clusterissuers.cert-manager.io > /dev/null 2>&1; then
echo "ClusterIssuer CRD found!"
exit 0
fi
# Increase wait time with each attempt
sleep_time=$((i * 5))
echo "CRDs not found yet, waiting $sleep_time seconds..."
sleep $sleep_time
done
# If we get here, we've failed to find the CRDs
echo "Failed to find cert-manager CRDs after multiple attempts"
exit 1
EOT
}
}
# Note: ClusterIssuer is now managed outside of Terraform
# TODO: Automate the ClusterIssuer creation
# We've already created it manually with the setup_argocd.sh script
# Install ArgoCD
# This is the single source of truth for the ArgoCD deployment (previously
# also managed ad-hoc via `helm upgrade -f argocd-values.yaml`, which has been
# retired in favor of Terraform).
resource "helm_release" "argocd" {
name = "argocd"
repository = "https://argoproj.github.io/argo-helm"
chart = "argo-cd"
version = "10.1.1"
namespace = kubernetes_namespace.argocd.metadata[0].name
# Homelab: single-node K3s, no HA needed.
values = [<<-EOT
# Dex/notifications disabled - neither SSO federation nor notification
# channels are configured, so avoid running two extra pods for nothing.
dex:
enabled: false
notifications:
enabled: false
redis-ha:
enabled: false
redis:
enabled: false
# Use the Redis instance running on the K3s host itself instead of the
# chart's bundled redis.
# NOTE: this Redis has no auth (`requirepass` empty) and listens on
# 0.0.0.0:6379 - reachable by anything on 192.168.1.0/24.
externalRedis:
host: 192.168.1.2
port: 6379
controller:
metrics:
enabled: true
serviceMonitor:
enabled: true
configs:
cm:
timeout.reconciliation: 60s
server:
replicas: 1
# Ingress terminates TLS, so the server can listen over plain HTTP.
extraArgs:
- --insecure
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: "nginx"
kubernetes.io/tls-acme: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/proxy-body-size: 102400m
nginx.ingress.kubernetes.io/auth-url: "https://pass.junv.cc/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://pass.junv.cc/oauth2/start?rd=https://$host$escaped_request_uri"
hostname: "argo.junv.cc"
# `tls` is a boolean for this chart (not a list) - the actual secret
# is always named `argocd-server-tls`.
tls: true
metrics:
enabled: true
serviceMonitor:
enabled: true
repoServer:
replicas: 1
metrics:
enabled: true
serviceMonitor:
enabled: true
applicationSet:
metrics:
enabled: true
serviceMonitor:
enabled: true
global:
logging:
level: "warn"
EOT
]
depends_on = [
helm_release.cert_manager,
helm_release.ingress_nginx
]
# Add timeout to ensure ArgoCD has enough time to install
timeout = 900
# Add retry logic in case of failure
recreate_pods = true
}