# Setting Up Argo CD on Kubernetes

Argo CD is a Kubernetes-native, declarative GitOps tool for deploying applications at scale. It pulls application manifests directly from a Git repository and syncs them to a Kubernetes cluster, supports YAML, Kustomize, Jsonnet, and Helm, and ships with a built-in web UI for monitoring sync status and application health. This guide installs Argo CD on a Kubernetes cluster, sets up access to its web UI and CLI, and deploys applications through both a YAML manifest and the Argo CD dashboard. By the end, you'll have Argo CD running behind TLS with two applications deployed and synced through it, following GitOps continuous delivery practices documented in [**Vultr Docs**](https://docs.vultr.com/how-to-set-up-argo-cd-on-kubernetes).

Before you begin, you'll need access to a Kubernetes cluster with at least three nodes, a Linux-based local or remote instance to test the Argo CD CLI, the `kubectl` CLI installed and configured on your local machine, the [Helm client](https://helm.sh/docs/using_helm/#installing-the-helm-client) installed locally, and a domain name for your Argo CD installation (for example, `argo.example.com`).

* * *

## 1\. Install Argo CD

**1\. Create a namespace for Argo CD:**

```console
kubectl create namespace argocd
```

**2\. Create a new directory for Argo CD in your home directory:**

```console
mkdir ~/argocd
```

**3\. Switch to the** `argocd` **directory:**

```console
cd ~/argocd
```

**4\. Clone the Argo CD Helm repository:**

```console
git clone https://github.com/argoproj/argo-helm.git
```

**5\. Navigate to the** `argo-cd` **chart directory:**

```console
cd argo-helm/charts/argo-cd/
```

**6\. Update Helm dependencies:**

```console
helm dependency up
```

**7\. Install Argo CD into the** `argocd` **namespace using Helm:**

```console
helm install argocd . -f values.yaml -n argocd
```

On success, you'll see metadata about the installation:

```plaintext
NAME: argocd
LAST DEPLOYED: Sun Jun 11 18:13:17 2023
NAMESPACE: argocd
STATUS: deployed
...
```

**8\. Verify that Argo CD is deployed to the** `argocd` **namespace:**

```console
kubectl get pods -n argocd
```

The output should display pods with names starting with `argocd-`.

**9\. Check the running services and ports:**

```console
kubectl get services -n argocd
```

Output:

```plaintext
NAME                               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
...
argocd-server                      ClusterIP   10.101.247.167   <none>        80/TCP,443/TCP      53s
```

The `argocd-server` service serves the Argo CD UI.

## 2\. Access the Argo CD UI

The Argo CD UI isn't reachable from outside the cluster by default. Use port forwarding to expose it locally without exposing the service externally.

**1.** Extract the default `admin` password from the `argocd-initial-admin-secret` secret:

```console
kubectl get secrets -n argocd argocd-initial-admin-secret -o yaml
```

The encrypted password appears in the output:

```plaintext
apiVersion: v1
data:
  password: TU1DaWRNQVJXNWJ3S1FBNA==
kind: Secret
...
```

Copy the encrypted password (`TU1DaWRNQVJXNWJ3S1FBNA==` above) for decoding.

**2\. Decode the password:**

```console
echo TU1DaWRNQVJXNWJ3S1FBNA== | base64 --decode
```

**3\. Forward port** `443` **of the** `argocd-server` **service to port** `8080` **on your localhost:**

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

Output:

```plaintext
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080
```

This occupies your current terminal session.

**4.** Open the Argo CD UI in a browser:

```plaintext
http://127.0.0.1:8080
```

**5.** Sign in with username `admin` and the decoded password. You can only access the dashboard while the port forward is active — press `Ctrl + C` in the terminal to end it.

### Optional: Access Argo CD Using the CLI Tool

Keep the port forward from the previous step active in one terminal, then open a new terminal for the following steps.

**1.** Download the Argo CD CLI tool:

```console
wget https://github.com/argoproj/argo-cd/releases/download/v2.7.4/argocd-linux-amd64
```

This installs version `2.7.4`. Check the `Assets` section of the [official releases page](https://github.com/argoproj/argo-cd/releases/) for the latest version.

**2\. Move the binary to** `/usr/local/bin/`**:**

```console
sudo mv argocd-linux-amd64 /usr/local/bin/argocd
```

**3\. Grant execute permissions:**

```console
sudo chmod +x /usr/local/bin/argocd
```

**4.** Log in to the Argo CD server:

```console
argocd login localhost:8080
```

Accept the server certificate, then enter username `admin` and the decoded password:

```plaintext
WARNING: server certificate had error: x509: certificate signed by unknown authority. Proceed insecurely (y/n)? y
Username: admin
Password: 
```

On success:

```plaintext
'admin:login' logged in successfully
Context 'localhost:8080' updated
```

**5\. Change the default admin password:**

```console
argocd account update-password
```

You'll be prompted for your existing password, a new password, and confirmation.

## 3\. Deploy Argo CD Applications

You can deploy Argo CD applications via a YAML manifest, the web UI, or the CLI.

### Creating and Deploying an Application Using a YAML Manifest

**1\. Create a YAML file for the application:**

```console
nano argocd-app.yaml
```

Add the following:

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: argo-application
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://gitlab.com/jasmine.harit/argocd-app-config.git
    targetRevision: HEAD
    path: dev
  destination: 
    server: https://kubernetes.default.svc
    namespace: myapp
  syncPolicy:
    syncOptions:
    - CreateNamespace=true
    automated:
      selfHeal: true
      prune: true
```

Save and close the file.

**2\. Apply the configuration:**

```console
kubectl apply -f argocd-app.yaml
```

**3\. Check the deployment status:**

```console
kubectl get app -n argocd
```

Output:

```plaintext
NAME               SYNC STATUS   HEALTH STATUS
argo-application   Synced        Healthy
```

You can also verify this with the CLI:

```console
argocd app list
```

Output:

```plaintext
NAME                     CLUSTER                         NAMESPACE  PROJECT  STATUS  HEALTH   SYNCPOLICY  CONDITIONS       REPO                                                    PATH  TARGET
argocd/argo-application  https://kubernetes.default.svc  myapp      default  Synced  Healthy  Auto-Prune  <none>      https://gitlab.com/jasmine.harit/argocd-app-config.git  dev   HEAD
```

**4\. Get detailed information about the application:**

```console
argocd app get argo-application
```

Output:

```plaintext
Name:               argocd/argo-application
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          myapp
URL:                https://localhost:8080/applications/argo-application
Repo:               https://gitlab.com/jasmine.harit/argocd-app-config.git
Target:             HEAD
Path:               dev
SyncWindow:         Sync Allowed
Sync Policy:        Automated (Prune)
Sync Status:        Synced to HEAD (9c92bf8)
Health Status:      Healthy

GROUP  KIND        NAMESPACE  NAME           STATUS   HEALTH   HOOK  MESSAGE
       Namespace              myapp          Running  Synced         namespace/myapp created
       Service     myapp      myapp-service  Synced   Healthy        service/myapp-service created
apps   Deployment  myapp      myapp1         Synced   Healthy        deployment.apps/myapp1 created
```

**5.** Refresh the web dashboard to see the deployed application.

### Creating and Deploying an Application via the Dashboard and CLI

**1.** In the Argo CD UI, click **NEW APP** to open the Application configuration screen.

*   In **GENERAL**, define the application name, project, and sync policy.
    
*   In **SOURCE**, enter the repository path, revision, and URL — for example, the [argocd-example-apps](https://github.com/argoproj/argocd-example-apps.git) repository with the `helm-guestbook` application as the path.
    
*   In **DESTINATION**, enter your cluster URL and namespace.
    
*   Click **CREATE** to deploy the application.
    

**2.** Check the application status with the CLI:

```console
argocd app get guestbook
```

Output:

```plaintext
Name:               argocd/guestbook
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          argocd
URL:                https://argocd.example.com/applications/guestbook
Repo:               https://github.com/argoproj/argocd-example-apps.git
Target:             HEAD
Path:               helm-guestbook
SyncWindow:         Sync Allowed
Sync Policy:        <none>
Sync Status:        OutOfSync from HEAD (4773b9f)
Health Status:      Missing

GROUP  KIND        NAMESPACE  NAME                      STATUS     HEALTH   HOOK  MESSAGE
       Service     argocd     guestbook-helm-guestbook  OutOfSync  Missing        
apps   Deployment  argocd     guestbook-helm-guestbook  OutOfSync  Missing 
```

The application is deployed but `OutOfSync`. Sync it with:

```console
argocd app sync guestbook
```

This fetches the necessary manifests from the repository and applies them using `kubectl`.

**3.** On the web dashboard, verify the application's health status and click into it for more details.

## 4\. Secure Argo CD with TLS Encryption

Expose the Argo CD server through the Nginx Ingress controller, terminated with TLS.

**1.** Install the Nginx Ingress controller on your cluster:

```console
helm install my-ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx --create-namespace
```

This installs the controller into a new `ingress-nginx` namespace, naming its resources `my-ingress-nginx-*`.

**2\. Check the Ingress service to get the load balancer IP address:**

```console
kubectl get services -n ingress-nginx
```

Output:

```plaintext
NAME                                    TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)                      AGE
my-ingress-nginx-controller             LoadBalancer   10.97.77.219   192.0.2.10     80:31808/TCP,443:30834/TCP   5m50s
my-ingress-nginx-controller-admission   ClusterIP      10.108.64.48   <none>         443/TCP                      5m50s
```

Note the `EXTERNAL-IP` of `my-ingress-nginx-controller` and create an **A** DNS record for your domain (e.g., `argo.example.com`) pointing to it with your DNS provider. It may take a few minutes for `EXTERNAL-IP` to populate — until then it shows as `<pending>`.

**3.** Install cert-manager:

```console
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.2/cert-manager.yaml
```

This installs cert-manager `v1.17.2` into the `cert-manager` namespace. Check the [official releases page](https://github.com/cert-manager/cert-manager/releases) for the latest version.

**4\. Create a manifest for an Issuer resource:**

```console
nano issuer.yaml
```

Add the following, replacing `admin@example.com` with your email address (required for the Issuer to work):

```yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: tls-certificate-issuer
  namespace: default
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@example.com
    privateKeySecretRef:
      name: letsencrypt-private-key
    solvers:
      - http01:
          ingress:
            class: nginx
```

Save and exit.

**5\. Create a manifest for the Ingress resource for the** `argocd-server` **service:**

```console
nano ingress.yaml
```

Add the following:

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-argocd
  namespace: argocd
  annotations:
    cert-manager.io/issuer: tls-certificate-issuer
spec:
  ingressClassName: nginx
  rules:
  - host: argo.example.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: argocd-server
            port:
              number: 80
  tls:
  - hosts:
      - argo.example.com
    secretName: argocd-tls
```

Save and exit.

**6\. Check the TLS certificate status:**

```console
kubectl get certificate -n argocd
```

Output:

```plaintext
NAME         READY   SECRET       AGE
argocd-tls   False   argocd-tls   5m43s
```

The status changes to `True` after a short wait.

**7.** Verify by visiting your domain (`https://argo.example.com`) in a browser.

## Next Steps

*   Wire Argo CD into your CI pipeline to trigger automated syncs on every merge.
    
*   Configure RBAC and SSO (OIDC/SAML) for team access to the Argo CD dashboard.
    
*   Set up notifications (Slack, email) for sync and health status changes.
    
*   Explore App-of-Apps and ApplicationSets for managing multiple applications at scale.
    

For the full guide with additional tips, visit the original article on [**Vultr Docs**](https://docs.vultr.com/how-to-set-up-argo-cd-on-kubernetes).
