ArgoCD - The Fancy Local Setup
ArgoCD is a Kubernetes-native continous delivery (CD) tool that follows GitOps principles. It treats the Git repos as the single source of truth for the desired state of the cluster. ArgoCD is a powerful tool that can be used to manage the lifecycle of your Kubernetes resources.
In this post, I'll walk you through how you can setup ArgoCD for local development with Minikube, and we will make our deployment a bit more fancy by making our ArgoCD public accessible using Cloudflare Tunnel. This is a great way to test your ArgoCD setup before deploying to a remote cluster.
Local kubernetes cluster with Minikube
I'm doing this on a Mac, and using Minikube to run a local Kubernetes cluster.
minikube start --driver=docker
Also, we'll need enable the ingress
and ingress-dns
addons (more detailed explanations below):
minikube addons enable ingress
minikube addons enable ingress-dns
Install ArgoCD
Installing ArgoCD on our local cluster is quite simple.
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
This creates a namespace called argocd
and installs the ArgoCD resources under that namespace.
If you're an SRE/DevOps engineer who is responsible for deploying and managing ArgoCD in your organization, I suggest that you study the content of the install.yaml
to understand what has just happened. Basically, it contains the manifests of all resources (e.g. CRDs, RBAC, Secrets, Service Account, etc.) needed to run ArgoCD. And it's often that those manifests are checked into the git repository of your organization's infrastructure.
Access ArgoCD
We can verify that ArgoCD is running by checking the pods in the argocd
namespace:
kubectl get pods -n argocd
And you should see the list of pods running in the argocd
namespace similar to what's shown below.
NAME READY STATUS RESTARTS AGE
argocd-application-controller-0 1/1 Running 0 8h
argocd-applicationset-controller-67c79fccd-962l4 1/1 Running 0 8h
argocd-dex-server-76686f75bd-999bq 1/1 Running 0 8h
argocd-notifications-controller-588d87b767-dvpf9 1/1 Running 0 8h
argocd-redis-59c6f8b4b5-x4bsw 1/1 Running 0 8h
argocd-repo-server-57db679bf7-cqjr5 1/1 Running 0 8h
argocd-server-67b6bf4f8d-t94sr 1/1 Running 0 8h
And let's also check the services in the argocd
namespace:
kubectl get svc -n argocd
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
argocd-applicationset-controller ClusterIP 10.105.162.22 <none> 7000/TCP,8080/TCP 8h
argocd-dex-server ClusterIP 10.111.144.208 <none> 5556/TCP,5557/TCP,5558/TCP 8h
argocd-metrics ClusterIP 10.108.157.170 <none> 8082/TCP 8h
argocd-notifications-controller-metrics ClusterIP 10.110.243.143 <none> 9001/TCP 8h
argocd-redis ClusterIP 10.101.145.107 <none> 6379/TCP 8h
argocd-repo-server ClusterIP 10.104.93.133 <none> 8081/TCP,8084/TCP 8h
argocd-server ClusterIP 10.105.203.252 <none> 80/TCP,443/TCP 8h
argocd-server-metrics ClusterIP 10.99.6.168 <none> 8083/TCP 8h
To access the ArgoCD UI, we can do a port-forwarding to the argocd-server
service:
kubectl port-forward svc/argocd-server -n argocd 8080:443
And then we can access the ArgoCD UI at https://localhost:8080
.

The default username is admin
, and its password is kept in the argocd-initial-admin-secret
secret.
kubectl get secret argocd-initial-admin-secret -n argocd -o jsonpath="{.data.password}" | base64 -d
Local DNS
It's a bit annoying to have to port-forward every time we want to access the ArgoCD UI. We can leverage the ingress-dns
addon to create a local DNS record for the ArgoCD UI, and have it accessible at https://argocd.minikube
. Before moving, let's make sure that we have enabled the ingress-dns
in our minikube
minikube addons enable ingress-dns
First, we'll need to add the minikube ip as a DNS server.
Create a file in /etc/resolver/argocd.minikube
with the following contents:
domain minikube
nameserver 192.168.49.2 # replace with your `minikube ip`
search_order 1
timeout 5
Then, we'll create a ingress rule for our ArgoCD
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-ingress
namespace: argocd
annotations:
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
ingressClassName: nginx
rules:
- host: argocd.minikube
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 443
Apply the ingress rule:
kubectl apply -f argocd-server-ingress.yaml
Now, you should be able to access the ArgoCD UI at https://argocd.minikube
.

And voila! We now have an ArgoCD deployment in our local k8s cluster that is accessible via a local domain.
Cloudflare Tunnel
Here comes the fancy part of our setup. You can actually make our ArgoCD UI accessible via a public domain so you can share it with your teammates. We'll use Cloudflare Tunnel to achieve this.
Cloudflare Tunnel runs a lightweight cloudflared daemon on your machine or server, creating a secure, outbound-only tunnel to Cloudflare’s global edge network—so your Argo CD UI can be exposed publicly without opening incoming firewall ports or needing a public IP. You can a DNS record at that tunnel and Cloudflare will securely route browser traffic through its network into your local Argo CD instance, with full support for Zero‑Trust authentication, HTTPS, and firewall protection.
A prerequisite for this is that you have a Cloudflare account and a domain managed by Cloudflare.
You can use clickops (i.e., Cloudflare's dashboard) to create a tunnel. However, I prefer to use the CLI to create a tunnel.
First, install the cloudflared
CLI:
brew install cloudflared
Then log into your Cloudflare account, here you can select the domain you want to use for the tunnel.
cloudflared tunnel login
Then, create a tunnel:
cloudflared tunnel create argocd-minikube-mbp
If your cloudflared is setup correctly, the tunnel should be created and you should see the following output:
Tunnel credentials written to /Users/<you-username>/.cloudflared/<your-tunnel-id>.json. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel.
Created tunnel argocd-minikube-mbp with id <your-tunnel-id>
Next, we create a configuration file at ~/.cloudflared/config.yml
for this tunnel with the following contents:
tunnel: <your-tunnel-id>
credentials-file: /Users/$USER/.cloudflared/<your-tunnel-id>.json
ingress:
- hostname: argocd.violincoding.com
service: https://argocd.minikube
originRequest:
noTLSVerify: true
- service: http_status:404
In this case, I have a domain violincoding.com
managed by Cloudflare, so I'll use argocd.violincoding.com
as the hostname for the tunnel.
And you can start the tunnel by running
cloudflared tunnel run argocd-minikube-mbp
And the log stream should look like this:

And ArgoCD should be accessible at https://argocd.violincoding.com
.
There is one problem with this setup though. If we stop our terminal, the tunnel will stop running. We can fix this by running the tunnel in the background.
In MacOS, we can create a launch daemon to run the tunnel in the background.
Create a file at /Library/LaunchDaemons/com.cloudflare.cloudflared.plist
with the following contents:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.cloudflare.cloudflared</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/bin/cloudflared</string>
<string>tunnel</string>
<string>run</string>
<string><your-tunnel-id></string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/Library/Logs/com.cloudflare.cloudflared.out.log</string>
<key>StandardErrorPath</key>
<string>/Library/Logs/com.cloudflare.cloudflared.err.log</string>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>
<key>ThrottleInterval</key>
<integer>5</integer>
</dict>
</plist>
And then load the launch daemon:
launchctl load /Library/LaunchDaemons/com.cloudflare.cloudflared.plist
launchctl start com.cloudflare.cloudflared
And now if you go to https://argocd.violincoding.com
, you should be able to access the ArgoCD UI.

Sweet! We now have an ArgoCD deployment in our local k8s cluster that is accessible via a public domain.
Clean up
Here is how you can clean up the resources we've created.
- Delete the tunnel:
cloudflared tunnel delete <your-tunnel-id>
- Delete the launch daemon:
launchctl unload /Library/LaunchDaemons/com.cloudflare.cloudflared.plist
launchctl stop com.cloudflare.cloudflared
sudo rm /Library/LaunchDaemons/com.cloudflare.cloudflared.plist
- Remove everything in the
argocd
namespace:
kubectl delete namespace argocd
Conclusion
In this post, I've showed you how to setup ArgoCD in a local development environment using Minikube, and how to make it publicly accessible using Cloudflare Tunnel. This is a great way to test your ArgoCD setup before deploying to a remote cluster.