aly badawy/homelab
all systems operational
// guides · gitops

Bootstrapping GitOps

What happens when you run ./provision/activate-gitops.sh. The sync-wave sequence, how imperative installs are adopted, and how to watch the rollout live.

~6 min to full health 14 Applications sync-wave -1 → 3

activate-gitops.sh is intentionally the final step — it applies a single file (k8s/apps/root.yaml) and then gets out of the way. After that, Git is the sole source of truth and ArgoCD drives everything. No more imperative kubectl apply.

01 What activate-gitops.sh does

terminal bash
$ ./provision/activate-gitops.sh

The script does three things:

  1. Preflight checks — verifies kubectl reaches the cluster, ArgoCD is installed, and Longhorn is installed. Fails fast if either is missing.
  2. Applies k8s/apps/root.yaml — this creates the root Application in ArgoCD. The root app watches k8s/apps/ in the repo and creates a child Application for every YAML file it finds there.
  3. Prints instructions — how to watch the rollout, how to get the initial admin password, and the ArgoCD UI URL.
Imperative bootstrap → GitOps adoption. ArgoCD and Longhorn were installed imperatively by rebuild.sh. When the root app deploys k8s/apps/argocd.yaml and k8s/apps/longhorn.yaml, ArgoCD "adopts" those installs — it compares the live state to the Helm values in k8s/components/*/ and finds zero diff, because the bootstrap used the same source. No re-install, no downtime.

02 Sync-wave sequence

ArgoCD deploys apps in wave order. Within a wave, it waits for all resources to be healthy before advancing to the next wave. The full sequence from activation to fully healthy cluster:

WaveApplicationsWhy this order
−1 vault Must be unsealed before ESO (wave 1) can read secrets. PVC reattachment is the bottleneck — ~4–5 min after pod start.
0 argocd, longhorn Platform adoption. ArgoCD adopts itself (no diff). Longhorn adopts its bootstrapped install.
1 ingress-nginx, cert-manager, external-secrets Ingress and TLS must be ready before apps need HTTPS. ESO must connect to Vault before apps need secrets.
2 monitor, db, auth, cloud, immich, whoami, aly User-facing apps. By now ingress, TLS, secrets, and storage are all healthy.

03 Vault unseal after activation

Vault's pod starts sealed. The vault-auto-unseal CronJob (deployed as part of the vault Application) runs every minute. It checks TCP port 8200 with nc, then runs timeout 5 vault status. Exit code 2 = sealed → unseals. The Longhorn PVC reattachment is the bottleneck — expect Vault to unseal 4–5 minutes after the pod starts.

Once Vault is unsealed, the eso-recovery CronJob detects that the ClusterSecretStore is degraded and restarts the ESO deployments to clear backoff. ESO reconnects, syncs all ExternalSecret resources, and apps get their secrets. Total time from activation to fully healthy: ~6 minutes.

04 Watching the rollout

useful commands during activation bash
# watch all Applications converge to Synced/Healthy
$ kubectl get applications -n argocd -w

# watch Vault unseal (look for "Vault is unsealed" in logs)
$ kubectl logs -n security -l job-name --tail=20 -f

# check ClusterSecretStore status
$ kubectl get clustersecretstore k8s-secrets

# initial ArgoCD admin password (rotate after first login)
$ kubectl -n argocd get secret argocd-initial-admin-secret \
    -o jsonpath='{.data.password}' | base64 -d; echo

# open ArgoCD before ingress is live
$ kubectl port-forward -n argocd svc/argocd-server 8080:80
# → http://localhost:8080  username: admin

# once ingress-nginx syncs, access via HTTPS
# → https://argo.in.alybadawy.com

05 Post-activation checklist

  1. Wait for all 14 Applications to show Synced + Healthy in ArgoCD.
  2. Confirm Vault is unsealed: kubectl exec -n security vault-0 -- vault status.
  3. Confirm ESO is connected: kubectl get clustersecretstore k8s-secrets should show Valid.
  4. Open argo.in.alybadawy.com and rotate the admin password.
  5. Open grafana.in.alybadawy.com and verify metrics are flowing.
  6. Delete the initial admin secret: kubectl delete secret argocd-initial-admin-secret -n argocd.
last updated 2026-06-08 · view source on GitHub