> ## Documentation Index
> Fetch the complete documentation index at: https://siderolabs-fe86397c-config-evolution.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy Argo CD

> In this guide you will learn how to deploy Argo CD on Talos Linux with kubectl or at bootstrap time, or on Omni-managed clusters using manifest sync.

export const k8s_release = '1.36.1';

[Argo CD](https://argo-cd.readthedocs.io/en/stable/) is a declarative, GitOps-based continuous delivery controller for Kubernetes. It continuously reconciles the live state of your cluster against the desired state defined in a Git repository, making it a natural fit for managing workloads on Talos Linux.

This guide covers how to deploy Argo CD on Talos Linux, either by bootstrapping it through the machine configuration or through Omni manifest sync for clusters managed by Omni.

## Prerequisites

Before you begin, ensure you have the following:

* Talos 1.3 or later.
* `kubectl` configured to access your cluster.
* `talosctl` installed and configured, if deploying on Talos without Omni.
* `omnictl` installed and configured, if deploying using Omni. See [Install and configure omnictl](../../omni/getting-started/install-and-configure-omnictl).

## Installation on self-managed Talos clusters

On Talos, you can install Argo CD after the cluster is up, or embed the install manifest in the machine configuration so it is running as soon as the cluster is healthy.

<Tabs>
  <Tab title="After bootstrap">
    Install Argo CD with `kubectl` once the cluster is up and healthy.

    **Step 1.** Create the `argocd` namespace:

    ```bash theme={null}
    kubectl create namespace argocd
    ```

    **Step 2.** Apply the Argo CD install manifest:

    ```bash theme={null}
    kubectl apply -n argocd \
      -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
    ```

    **Step 3.** Verify that the Argo CD pods are running in the `argocd` namespace:

    ```bash theme={null}
    kubectl get pods -n argocd
    ```

    You should see pods for `argocd-server`, `argocd-repo-server`, `argocd-application-controller`, and supporting components all in a `Running` state.
  </Tab>

  <Tab title="At bootstrap time">
    Embed the install manifest in the control plane machine configuration so Argo CD is running as soon as the cluster is healthy.

    **Step 1.** Download the Argo CD install manifest:

    ```bash theme={null}
    curl -Lo argocd-install.yaml \
      https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
    ```

    **Step 2.** Use kustomize to set the `argocd` namespace on every resource:

    ```bash theme={null}
    cat <<EOF > kustomization.yaml
    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    namespace: argocd
    resources:
      - argocd-install.yaml
    EOF

    kubectl kustomize . > argocd-install-namespaced.yaml
    ```

    **Step 3.** Prepend the namespace definition so the namespace and its resources are created together:

    ```bash theme={null}
    cat <<EOF > argocd-namespace.yaml
    apiVersion: v1
    kind: Namespace
    metadata:
      name: argocd
    ---
    EOF

    cat argocd-namespace.yaml argocd-install-namespaced.yaml > argocd-complete.yaml
    ```

    **Step 4.** Generate the patch file, embedding the manifest under `contents`:

    ```bash theme={null}
    yq -n '.cluster.inlineManifests = [{"name": "argocd", "contents": load_str("argocd-complete.yaml")}]' \
      > argocd-inline-manifest.yaml
    ```

    `yq` embeds the manifest as a block scalar and handles the indentation for you, so the generated patch is valid YAML.

    **Step 5.** Set a variable containing the IP addresses of your control plane nodes:

    ```bash theme={null}
    CP_IPS="<control-plane-ip-1>,<control-plane-ip-2>,<control-plane-ip-3>"
    ```

    **Step 6.** Apply the patch to your control plane nodes:

    ```bash theme={null}
    talosctl patch machineconfig \
      --patch @argocd-inline-manifest.yaml \
      --endpoints $CP_IPS \
      --nodes $CP_IPS \
      --talosconfig=./talosconfig
    ```

    **Step 7.** If this is a new cluster, bootstrap it. Run this **only once** per cluster.

    ```bash theme={null}
    talosctl bootstrap --nodes <control-plane-ip> --talosconfig=./talosconfig
    ```

    **Step 8.** Once the cluster is healthy, verify that the Argo CD pods are running in the `argocd` namespace:

    ```bash theme={null}
    kubectl get pods -n argocd
    ```
  </Tab>
</Tabs>

From here, Argo CD manages itself and any applications you configure in your Git repository.

## Installation on Omni-managed clusters

If you manage your clusters with [Omni](https://www.siderolabs.com/omni-for-kubernetes-cluster-management), you can deploy Argo CD declaratively using [Omni manifest sync](../../omni/cluster-management/sync-kubernetes-manifests). Because Argo CD manages its own state after bootstrapping, the manifest is applied with `mode: one-time`, Omni installs it once, and Argo CD takes over from there.

Manifest sync does not support fetching manifests from remote URLs, so you first download the Argo CD install manifest locally, then reference it in your cluster template.

**Step 1:** Download the Argo CD install manifest:

```bash theme={null}
curl -Lo argocd-install.yaml \
  https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
```

**Step 2**: Use kustomize to inject namespace fields into every resource in the Argo CD upstream manifest. [Omni manifest sync](../../omni/cluster-management/sync-kubernetes-manifests) requires namespaces to be explicitly set on every resource:

```bash theme={null}
cat <<EOF > kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: argocd
resources:
  - argocd-install.yaml
EOF
```

**Step 3:** Build the namespaced manifest:

```bash theme={null}
kubectl kustomize . > argocd-install-namespaced.yaml
```

**Step 4:** Create the namespace prerequisite that defines the `argocd` namespace:

```bash theme={null}
cat <<EOF > argocd-prereqs.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: argocd
EOF
```

**Step 5.** Create the cluster template and reference both manifests `argocd-install-namespaced.yaml` and `argocd-prereqs.yaml`:

```bash theme={null}
cat <<EOF > cluster-template.yaml
kind: Cluster
name: <your-cluster>
kubernetes:
  version: v1.x.x
  manifests:
    - name: argocd-prereqs
      file: argocd-prereqs.yaml
      mode: full
    - name: argocd-install
      file: argocd-install-namespaced.yaml
      mode: one-time
talos:
  version: v1.x.x
---
kind: ControlPlane
machines:
  - <machine-id>
---
kind: Workers
machines:
  - <machine-id>
EOF
```

The `argocd-prereqs` manifest uses `mode: full` so Omni continuously ensures the namespace exists. The `argocd-install` manifest uses `mode: one-time` because Argo CD manages its own resources after the initial apply.

**Step 6:** Apply the cluster template:

```bash theme={null}
omnictl cluster template sync --file cluster-template.yaml
```

Omni stores the manifest definitions and waits until the Kubernetes API is available and the cluster is healthy before applying them.

**Step 7:** Verify that the Argo CD pods are running:

```bash theme={null}
kubectl get pods -n argocd
```

All Argo CD pods should appear in a `Running` state. To inspect the manifest sync status, run:

```bash theme={null}
omnictl get clusterkubernetesmanifestsstatuses <cluster-name>
```

See [Sync Kubernetes Manifests](../../omni/cluster-management/sync-kubernetes-manifests) for more details on sync modes and status monitoring.

**Step 8:** Access the Argo CD UI:

```bash theme={null}
kubectl port-forward svc/argocd-server -n argocd 8080:443
```

Open `https://localhost:8080` and log in with the username `admin`. Retrieve the initial password with:

```bash theme={null}
kubectl get secret argocd-initial-admin-secret -n argocd \
  -o jsonpath="{.data.password}" | base64 -d
```
