2026-08-22 17:30:45 +01:00
|
|
|
# Installing Argo CD — command reference
|
|
|
|
|
|
|
|
|
|
Companion to [`docs/03-installing-argocd.md`](../docs/03-installing-argocd.md)
|
|
|
|
|
and [`docs/04-app-of-apps.md`](../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`](../talos/README.md)).
|
|
|
|
|
|
|
|
|
|
## 1. Install Argo CD
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
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](https://github.com/argoproj/argo-cd/releases)
|
|
|
|
|
for current tags.
|
|
|
|
|
|
|
|
|
|
Wait for everything to come up:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
kubectl -n argocd wait --for=condition=Available --timeout=300s deployment --all
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 2. Get the initial admin password
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
kubectl -n argocd port-forward svc/argocd-server 8080:443
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Leave that running in its own terminal. In another terminal:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
argocd account update-password
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 4. Hand the cluster to Git
|
|
|
|
|
|
|
|
|
|
[`app-of-apps/app-of-apps.yaml`](app-of-apps/app-of-apps.yaml) is the one
|
|
|
|
|
manifest in this whole repo you apply by hand — everything after it, Argo
|
2026-09-03 01:54:37 +01:00
|
|
|
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:
|
2026-08-22 17:30:45 +01:00
|
|
|
|
|
|
|
|
```sh
|
2026-09-03 01:54:37 +01:00
|
|
|
grep -R "repoURL:" argocd/app-of-apps apps/*.yaml
|
2026-09-04 12:42:43 +00:00
|
|
|
git ls-remote https://tea.ahmza.com/ahmza.com/k8s-starter-pack.git HEAD
|
2026-08-22 17:30:45 +01:00
|
|
|
```
|
|
|
|
|
|
2026-09-03 01:54:37 +01:00
|
|
|
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:
|
2026-08-22 17:30:45 +01:00
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
kubectl apply -f argocd/app-of-apps/app-of-apps.yaml
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Watch it take over:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
argocd app get app-of-apps
|
|
|
|
|
argocd app list
|
|
|
|
|
```
|
|
|
|
|
|
2026-08-22 18:25:38 +01:00
|
|
|
You should see `app-of-apps` sync, then `demo`, `metallb`, and `longhorn`
|
|
|
|
|
Applications appear underneath it, then sync themselves. See
|
2026-08-22 17:30:45 +01:00
|
|
|
[`docs/04-app-of-apps.md`](../docs/04-app-of-apps.md) for what's happening
|
|
|
|
|
here and [`docs/checklist.md`](../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`](../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:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
kubectl -n argocd patch svc argocd-server --type merge -p \
|
2026-09-03 02:19:46 +01:00
|
|
|
'{"spec":{"type":"LoadBalancer"},"metadata":{"annotations":{"metallb.io/loadBalancerIPs":"10.10.60.10"}}}'
|
2026-08-22 17:30:45 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
kubectl -n argocd get svc argocd-server
|
|
|
|
|
```
|
|
|
|
|
|
2026-09-03 02:19:46 +01:00
|
|
|
Once `EXTERNAL-IP` shows `10.10.60.10`, `https://10.10.60.10` works
|
|
|
|
|
from routed networks — no port-forward required.
|