This guide walks you through setting up ArgoCD — a declarative, GitOps-based continuous delivery tool — on a bare-metal Kubernetes cluster. By the end, you’ll have ArgoCD fully accessible through a web browser via an NGINX Ingress Controller, and you’ll deploy sample applications using both the CLI and the Web UI.
Note: This guide assumes you already have a running Kubernetes cluster (e.g., set up with kubeadm). If you don’t have one yet, check out my previous post on Kubernetes Single-Node Setup.
Table of Contents
- Installing ArgoCD
- Setting Up NGINX Ingress Controller
- Creating an Ingress for ArgoCD
- Installing the ArgoCD CLI
- Initial Login and Password Setup
- Accessing the ArgoCD Web UI
- Tuning the Refresh Interval
- Deploying an Application via CLI
- Deploying an Application via Web UI
- ArgoCD CLI Tips
1. Installing ArgoCD
1.1 Download the Installation Manifest
First, download the official ArgoCD installation manifest:
wget https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml1.2 Configure a Custom Root Path (Optional)
If you want to access ArgoCD through a sub-path (e.g., http://<your-ip>/argocd-lab) instead of using a dedicated domain, you’ll need to modify the argocd-server Deployment in the downloaded install.yaml.
Find the Deployment resource named argocd-server and add the --rootpath, --basehref, and --insecure arguments:
apiVersion: apps/v1kind: Deploymentmetadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server...# Add these under spec.template.spec.containers[0].argsspec: containers: - args: - /usr/local/bin/argocd-server - --staticassets - /shared/app - --insecure - --rootpath - /argocd-lab - --basehref - /argocd-labNote: The path
/argocd-labis used in this guide as an example to avoid conflicts with ArgoCD’s default/argocdpath. Feel free to change it to whatever path suits your needs — just make sure it stays consistent across your Ingress configuration and CLI login commands. If you’re using a dedicated domain or want ArgoCD on the root URL, you can skip the--rootpathand--basehrefflags entirely.
1.3 Create the Namespace and Deploy
Create the argocd namespace and apply the manifest:
kubectl create namespace argocdkubectl apply -f install.yaml -n argocd2. Setting Up NGINX Ingress Controller
A Note on NGINX Ingress: We are using NGINX Ingress Controller here because it is very easy to set up for demonstration purposes. However, if you are planning to deploy this in a production environment, you should consider alternatives that provide better long-term security support and active maintenance (such as Traefik, HAProxy, Contour, etc.).
Important for bare-metal/on-prem clusters: Clusters bootstrapped with kubeadm don’t come with a built-in Ingress Controller. Without one, any
Ingressresource you create won’t work —kubectl get ingresswill show noADDRESS, and you’ll getconnection refusederrors when trying to access services.
2.1 Check If an Ingress Controller Exists
kubectl get ingressclassIf the output is No resources found, you need to install one.
2.2 Install NGINX Ingress Controller
Since we’re on bare-metal (no cloud LoadBalancer), install the NGINX Ingress Controller using the bare-metal manifest:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.3/deploy/static/provider/baremetal/deploy.yaml2.3 Enable Host Networking
Edit the ingress-nginx-controller Deployment to enable hostNetwork, which allows the controller to bind directly to port 80/443 on the node — no external LoadBalancer or MetalLB required:
kubectl edit deployment ingress-nginx-controller -n ingress-nginxAdd hostNetwork: true under spec.template.spec, at the same level as containers:
spec: template: spec: hostNetwork: true containers: - name: controller ...2.4 Verify the Installation
Wait a moment, then confirm the controller pod is running and the IngressClass is registered:
kubectl get pods -n ingress-nginxkubectl get ingressclassExpected output:
NAME CONTROLLER PARAMETERS AGEnginx k8s.io/ingress-nginx <none> 30s3. Creating an Ingress for ArgoCD
Create an ingress.yaml file to expose ArgoCD through the /argocd-lab path:
apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: argocd-server-ingress namespace: argocd annotations: ingress.kubernetes.io/ssl-redirect: "false"spec: rules: - http: paths: - path: /argocd-lab pathType: Prefix backend: service: name: argocd-server port: number: 80Apply it:
kubectl apply -f ingress.yaml4. Installing the ArgoCD CLI
Download and install the ArgoCD CLI binary:
curl -SL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocdClean up the downloaded file:
rm argocd-linux-amd64Verify the installation:
argocd versionExpected output:
argocd: v3.4.4+443415b BuildDate: 2026-06-18T09:15:00Z GitCommit: 443415b5527ac55366e0760c93ef0e1abd0cf273 GitTreeState: clean GoVersion: go1.26.0 Compiler: gc Platform: linux/amd64Note: You may see a
fatalmessage about the server address being unspecified — this is normal before logging in.
5. Initial Login and Password Setup
5.1 Retrieve the Default Admin Password
ArgoCD generates a random initial password for the admin account during installation:
argocd admin initial-password -n argocdExample output:
[PASSWORD]
This password must be only used for first time login. We strongly recommendyou update the password using `argocd account update-password`.5.2 Log In via CLI
Log in using the generated password. Replace <your-ip> with your node’s IP address:
argocd login <your-ip>:80 --grpc-web-root-path=/argocd-lab --plaintext --insecureWhen prompted, enter admin as the username and the password from the previous step.
5.3 Change the Admin Password
For security, update the default password immediately:
argocd account update-password*** Enter password of currently logged in user (admin):*** Enter new password for user admin:*** Confirm new password for user admin:Password updatedContext '<your-ip>:80/argocd-lab' updated6. Accessing the ArgoCD Web UI
Open your browser and navigate to:
http://<your-ip>/argocd-labLog in with the admin username and the password you just set.

7. Tuning the Refresh Interval
By default, ArgoCD polls your Git repositories every 3 minutes to check for changes. If you want faster feedback (e.g., during development), you can lower this interval.
Create a config.yaml file:
apiVersion: v1kind: ConfigMapmetadata: name: argocd-cm namespace: argocd labels: app.kubernetes.io/name: argocd-cm app.kubernetes.io/part-of: argocddata: timeout.reconciliation: 20sApply the configuration:
kubectl apply -f config.yamlVerify the change:
kubectl describe configmap -n argocd argocd-cmRestart the repo server to pick up the new setting:
kubectl -n argocd rollout restart deploy argocd-repo-serverTip: A 20-second interval is great for development and testing, but for production environments you may want to keep it at the default 3 minutes (or higher) to reduce load on both ArgoCD and your Git server.
8. Deploying an Application via CLI
8.1 Create the Application
Create a sample application called simple-deploy pointing to a Git repository:
argocd app create simple-deploy \ --repo https://github.com/maliqpotter/argo-simple-project.git \ --path simple-demo \ --dest-server https://kubernetes.default.svc \ --dest-namespace defaultapplication 'simple-deploy' created8.2 Check the Application Status
argocd app get simple-deployThe initial status will be OutOfSync because no Kubernetes resources have been created yet:
Name: argocd/simple-deployProject: defaultServer: https://kubernetes.default.svcNamespace: defaultSource:- Repo: https://github.com/maliqpotter/argo-simple-project.git Path: simple-demoSync Status: OutOfSync from (1873ef1)Health Status: Missing
GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGEapps Deployment default simple-nginx OutOfSync Missing8.3 Sync (Deploy) the Application
Trigger a sync to deploy the application:
argocd app sync simple-deployOnce the sync completes, verify the status:
argocd app get simple-deployName: argocd/simple-deployProject: defaultServer: https://kubernetes.default.svcNamespace: defaultSource:- Repo: https://github.com/maliqpotter/argo-simple-project.git Path: simple-demoSync Policy: ManualSync Status: Synced to (1873ef1)Health Status: Healthy
GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGEapps Deployment default simple-nginx Synced Healthy deployment.apps/simple-nginx created8.4 Verify the Resources
Check that the pods and deployment were created:
kubectl get pod -n defaultNAME READY STATUS RESTARTS AGEsimple-deploy-5d7468b6f8-75w68 1/1 Running 0 2m11ssimple-deploy-5d7468b6f8-mkkph 1/1 Running 0 2m11ssimple-deploy-5d7468b6f8-mkgdz 1/1 Running 0 2m11skubectl get deployment -n defaultNAME READY UP-TO-DATE AVAILABLE AGEsimple-deploy 3/3 3 3 2m38s9. Deploying an Application via Web UI
In addition to the CLI, you can create and deploy applications directly from the ArgoCD dashboard.
9.1 Open the Dashboard
After logging in, you’ll see the ArgoCD dashboard showing your existing applications (like the simple-deploy app we just created via CLI).
Click the + NEW APP button to create a new application.

9.2 Fill in the General Settings
Under the GENERAL section, configure:
- Application Name:
nginx-with-ingress - Project Name:
default - Sync Policy:
Manual(orAutomaticif you want auto-sync)

9.3 Configure the Source and Destination
Under the SOURCE section:
- Repository URL:
https://github.com/maliqpotter/argo-simple-project.git - Revision:
HEAD(or the specific branch you want, e.g.,main) - Path:
nginx-with-ingress
Under the DESTINATION section:
- Cluster URL:
https://kubernetes.default.svc - Namespace:
default
Then click the CREATE button at the top of the form.

9.4 Sync the Application
Once the nginx-with-ingress application appears on the dashboard with an OutOfSync status, click the SYNC button on the application card, then click SYNCHRONIZE to confirm.

After the sync completes, the application status will change to Synced and Healthy. You can click into the application to see a visual map of all the Kubernetes resources that were created (Deployments, ReplicaSets, Pods, etc.).
10. ArgoCD CLI Tips
10.1 Set Default Namespace
Since ArgoCD is installed in the argocd namespace, you can set it as your default to avoid typing -n argocd on every command:
Option A — Set the kubectl context:
kubectl config set-context --current --namespace=argocdOption B — Use an environment variable:
export ARGOCD_OPTS='--port-forward-namespace argocd'10.2 Enable Bash Completion
Speed up your CLI workflow with tab completion:
argocd completion bash | sudo tee /etc/bash_completion.d/argocdsource ~/.bashrcReferences
- ArgoCD Official Documentation — argoproj.github.io
- NGINX Ingress Controller — kubernetes.github.io
- ArgoCD CLI Reference — argo-cd.readthedocs.io
This guide is based on a real-world deployment. Adjust IPs, paths, and version numbers to match your own environment.