Files
k8s-starter-pack/argocd

Installing Argo CD — command reference

Companion to docs/03-installing-argocd.md and docs/04-app-of-apps.md. Read those for the why; this is the exact commands.

Run these once kubectl get nodes shows your node Ready (see talos/README.md).

1. Install Argo CD

kubectl create namespace argocd
kubectl apply --server-side -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

--server-side matters here, not just as a nice-to-have: one of Argo CD's CRDs (applicationsets.argoproj.io) is large enough that a normal (client-side) kubectl apply fails outright — it tries to stash the whole manifest into an annotation for its 3-way-merge bookkeeping, and that annotation hits Kubernetes' size limit. Server-side apply has the API server do that diffing instead, so this limit doesn't apply.

This is an imperative install: a plain kubectl apply of a manifest bundle that the Argo CD project maintains, rather than a Helm chart or operator. It's the officially documented quickstart path, and it means Argo CD itself isn't part of your GitOps loop — you install it once, by hand, and it then manages everything else declaratively. Bootstrapping has to start somewhere outside the loop; this is that starting point.

The stable in that URL is a moving tag maintained by the Argo CD project that always points at the latest stable release — convenient here, but not reproducible: what it installs today may differ from what it installs in six months. For a production setup, pin an explicit version instead, e.g. .../v2.13.0/manifests/install.yaml — see releases for current tags.

Wait for everything to come up:

kubectl -n argocd wait --for=condition=Available --timeout=300s deployment --all

2. Get the initial admin password

kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d; echo

This secret is auto-generated on first install. Save the password somewhere; you'll change it in a moment.

3. Reach the UI and CLI

Argo CD doesn't expose itself outside the cluster by default. For this learning setup, forward its port to your machine:

kubectl -n argocd port-forward svc/argocd-server 8080:443

Leave that running in its own terminal. In another terminal:

argocd login localhost:8080 --username admin --password <password-from-above> --insecure

--insecure here means "skip TLS certificate verification" — the server's certificate is self-signed by default and there's nothing on the other end but your own port-forward, so this is fine for local access. It is not something to carry into a setup reachable over the real network.

Open https://localhost:8080 in a browser to see the same thing visually.

Optional but recommended — replace the initial password:

argocd account update-password

4. Hand the cluster to Git

app-of-apps/app-of-apps.yaml is the one manifest in this whole repo you apply by hand — everything after it, Argo CD applies for you. Every Application manifest has its own repoURL because child Applications do not inherit it from their parent. Verify they all point at this cluster's public Gitea repository:

grep -R "repoURL:" argocd/app-of-apps apps/*.yaml
git ls-remote https://tea.ahmza.com/ahmza.com/k8s-starter-pack.git HEAD

The remote check must succeed without credentials. Commit and push any pending changes before continuing — child Applications read from Git, not your local disk. Then:

kubectl apply -f argocd/app-of-apps/app-of-apps.yaml

Watch it take over:

argocd app get app-of-apps
argocd app list

You should see app-of-apps sync, then demo, metallb, and longhorn Applications appear underneath it, then sync themselves. See docs/04-app-of-apps.md for what's happening here and docs/checklist.md for the full guided path.

5. Give the UI a real address (MetalLB)

Once metallb (above) is Synced/Healthy and you've configured its address pool (see docs/05-metallb.md), you can retire the port-forward from step 3 and give Argo CD's UI a permanent address instead. This one change is applied directly, not through Git — Argo CD's own install isn't managed by this repo's GitOps loop:

kubectl -n argocd patch svc argocd-server --type merge -p \
  '{"spec":{"type":"LoadBalancer"},"metadata":{"annotations":{"metallb.io/loadBalancerIPs":"10.10.60.10"}}}'
kubectl -n argocd get svc argocd-server

Once EXTERNAL-IP shows 10.10.60.10, https://10.10.60.10 works from routed networks — no port-forward required.