Argo CD¶
Argo CD is installed by Terraform via the official Helm chart, into the argocd namespace, on the same cluster it then manages. The chart version is pinned and the values are inlined in infrastructure/gcp/argocd.tf.
This page covers what Terraform creates. For day-to-day operations (logging in, syncing apps, debugging stuck syncs), see the Argo CD operational page.
Install¶
| Field | Value |
|---|---|
| Helm repo | https://argoproj.github.io/argo-helm |
| Chart | argo-cd |
| Version | 7.7.13 (pinned) |
| Namespace | argocd (created by Helm) |
| Depends on | google_container_node_pool.spot_nodes — pool must exist before Helm can schedule pods |
The pin matters. Argo CD's CRDs change between minor versions, and the chart is the only thing that controls them. Bump version deliberately, never with a "latest" or wildcard.
Values¶
The Terraform values block (yamlencode'd into the chart) overrides three things:
Logging¶
global:
logging:
level: error
The whole platform runs at error level. Useful for keeping log volume down on a single-node cluster, painful when something goes wrong and you need INFO. To temporarily turn it up, either edit argocd.tf and apply, or kubectl patch configmap argocd-cmd-params-cm -n argocd directly (Argo CD reloads on its own).
Server¶
server:
service:
type: ClusterIP
extraArgs: ["--insecure"]
extraEnvs:
- name: GOOGLE_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: google-oauth-credentials
key: client-secret
ClusterIP— the server is not directly exposed. Traefik routesargo-app.tomoda.lifethrough oauth2-proxy and then into the Argo CD ClusterIP service. There is no LoadBalancer for Argo CD.--insecure— server runs HTTP only; TLS is terminated by Traefik upstream.GOOGLE_CLIENT_SECRETis loaded from the K8s secretgoogle-oauth-credentials(keyclient-secret). The argocd.tf comment notes this is "for safety" — the secret is actually consumed by Dex, but the server pod gets it too in case future Argo CD versions move OAuth handling out of Dex.
Dex¶
dex:
env:
- name: GOOGLE_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: google-oauth-credentials
key: client-secret
The same secret is mounted as an env var in the Dex pod. The dex.config below references $GOOGLE_CLIENT_SECRET, which Dex expands at runtime — the literal secret is never written into a ConfigMap.
Auth config¶
configs:
cm:
exec.enabled: "true"
url: "https://argo-app.tomoda.life"
dex.config: |
connectors:
- type: google
id: google
name: Google
config:
clientID: "929386103976-15r47b9idc981ig2socuvkdpvrhm6j3b.apps.googleusercontent.com"
clientSecret: "$GOOGLE_CLIENT_SECRET"
hostedDomains:
- "tomoda.life"
rbac:
policy.default: "role:admin"
| Field | Effect |
|---|---|
url |
The public origin Argo CD generates redirect URLs against. Must match the oauth2-proxy / Traefik host exactly. |
exec.enabled |
Lets Argo CD use the Kubernetes API "exec" plugin auth flow — required for the local CLI. |
Dex clientID |
The internal-environment OAuth client (the literal value is checked into argocd.tf; this is intentional, it is a public client ID, not a secret). |
hostedDomains |
Only tomoda.life Google accounts can log in. External Google accounts are rejected by Dex before Argo CD ever sees them. |
policy.default: role:admin |
Every successfully-authenticated tomoda.life user is admin. Fine for internal tooling, would be a problem if Argo CD ever became multi-tenant. |
How the secret reaches Dex
The K8s secret google-oauth-credentials in the argocd namespace is created by an ExternalSecret (k8s/envs/dev/sys/manifests/external-secrets-config.yaml) that pulls tomoda-google-client-secret from GCP Secret Manager. The first-time provisioning (creating the OAuth client in the GCP Console and storing both ID + secret in GCP SM) is manual — see OAuth & Dex and Secrets Management → Provisioning the Google OAuth client.
Exposure¶
The Argo CD server is ClusterIP only. The public URL https://argo-app.tomoda.life is served by:
- Cloudflare DNS resolves to the Traefik LoadBalancer IP on GKE.
- Traefik terminates TLS and forwards to the oauth2-proxy service.
- oauth2-proxy enforces Google login (using the same OAuth client as Dex).
- After successful auth, oauth2-proxy proxies to the Argo CD
ClusterIP. - Argo CD itself sees the request as already-authenticated and matches the user against its Dex config a second time.
The double-OAuth ("oauth2-proxy at the edge, Dex inside Argo CD") is redundant but harmless: oauth2-proxy gates the network, Dex gates Argo CD's authorisation.
What lives outside this Terraform¶
google-oauth-credentialssecret — populated manually or by External Secrets from Secret Manager. Not in Terraform.- Argo CD Applications — every app the platform deploys is configured by manifests in the GitOps repo (
k8s/), not byargocd.tf. This file only installs Argo CD itself. - Image Updater — installed as a separate workload in the
argocdnamespace (manifests ink8s/). The GCP-side IAM is inimage_updater_iam.tf, notargocd.tf.