Deploy Keploy with ArgoCD
This guide walks you through deploying Keploy's k8s-proxy using ArgoCD (GitOps) on a Kubernetes cluster, with Contour as the ingress controller.
If you already use ArgoCD to manage your applications, adding Keploy requires just two files—an ArgoCD Application YAML and a Contour HTTPProxy YAML. No changes to your existing app code or manifests.
[!NOTE] This guide assumes you have already completed the Kubernetes Setup and have a running Kind cluster with Keploy connected.
Prerequisites
Ensure you have the following before you begin:
- A running Kubernetes cluster (Kind, EKS, GKE, AKS)
- ArgoCD installed on the cluster
- kubectl and Helm installed
- Keploy Enterprise account (with an access key)
1) Install ArgoCD
Skip this if ArgoCD is already installed on your cluster.
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl -n argocd rollout status deployment/argocd-server
Get the admin password:
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d; echo
Access the ArgoCD UI:
kubectl -n argocd port-forward svc/argocd-server 8443:443 &
Open https://localhost:8443 in your browser. Login with username admin and the password from above.
2) Deploy Contour ingress controller
Keploy's k8s-proxy serves HTTPS natively on its backend port. You need an ingress controller that supports TLS passthrough—forwarding the encrypted connection directly to the k8s-proxy without terminating it.
Contour is a CNCF ingress controller powered by Envoy that supports this via its HTTPProxy CRD.
2.1 Install Contour
kubectl apply -f https://projectcontour.io/quickstart/contour.yaml
Wait for it to be ready:
kubectl -n projectcontour rollout status deployment/contour
kubectl -n projectcontour rollout status daemonset/envoy
2.2 Patch Envoy for Kind/VM clusters
Kind only maps specific ports to the host. Since TLS passthrough uses Envoy's HTTPS listener (port 443), you need to assign it to the mapped NodePort:
kubectl patch svc envoy -n projectcontour --type='json' -p='[
{"op": "replace", "path": "/spec/type", "value": "NodePort"},
{"op": "replace", "path": "/spec/ports/0/nodePort", "value": 30081},
{"op": "replace", "path": "/spec/ports/1/nodePort", "value": 30080}
]'
This puts the HTTPS listener on NodePort 30080 (mapped to the host) and the HTTP listener on 30081.
[!TIP] For cloud clusters (EKS/GKE/AKS), skip this patch. The default LoadBalancer type works—your cloud provider assigns an external IP automatically.
2.3 Verify Contour
kubectl get pods -n projectcontour
kubectl get svc -n projectcontour
Expected output:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
envoy NodePort 10.96.65.35 <none> 80:30081/TCP,443:30080/TCP 2m
3) Create the Keploy access key secret
Skip if you already created this during the Kubernetes Setup.
Go to the Keploy UI → Clusters → Connect New Cluster. Enter your cluster name and ingress URL (e.g. https://your-host:30080). Click Connect to get your access key.
kubectl create namespace keploy
kubectl -n keploy create secret generic keploy-credentials \
--from-literal=access-key="<YOUR_ACCESS_KEY>"
[!WARNING] Never commit access keys to Git. Use
existingSecretin Helm values or a secrets manager (Sealed Secrets, Vault, External Secrets Operator).
4) Create the ArgoCD Application for k8s-proxy
Create a file named keploy-k8s-proxy.yaml:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: keploy-k8s-proxy
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
chart: k8s-proxy-chart
repoURL: registry-1.docker.io/keploy
targetRevision: "3.3.10"
helm:
values: |
replicaCount: 1
environment: "staging"
selfHosted: false
fullnameOverride: "k8s-proxy"
keploy:
existingSecret: "keploy-credentials"
existingSecretKey: "access-key"
clusterName: "<YOUR_CLUSTER_NAME>"
apiServerUrl: "https://api.keploy.io"
ingressUrl: "https://<YOUR_INGRESS_HOST>:30080"
service:
type: ClusterIP
mongodb:
enabled: false
minio:
enabled: false
destination:
server: https://kubernetes.default.svc
namespace: keploy
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Replace:
<YOUR_CLUSTER_NAME>—the name you entered in the Keploy UI<YOUR_INGRESS_HOST>—the hostname that resolves to your cluster (e.g. your VM IP or a DNS name):30080—the NodePort from the Contour patch above. For cloud clusters (EKS/GKE/AKS) using a LoadBalancer, use:443instead
Apply it:
kubectl apply -f keploy-k8s-proxy.yaml
5) Create the HTTPProxy for TLS passthrough
The k8s-proxy serves HTTPS on its backend. A standard Kubernetes Ingress only supports HTTP backends, so you need Contour's HTTPProxy CRD with TLS passthrough.
Create a file named k8s-proxy-httpproxy.yaml:
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: k8s-proxy-ingress
namespace: keploy
spec:
virtualhost:
fqdn: <YOUR_INGRESS_HOST>
tls:
passthrough: true
tcpproxy:
services:
- name: k8s-proxy
port: 8080
Replace <YOUR_INGRESS_HOST> with the same hostname used in keploy.ingressUrl.
Apply it:
kubectl apply -f k8s-proxy-httpproxy.yaml
How TLS passthrough works
Client (Keploy cloud)
│
│ HTTPS (encrypted)
▼
Envoy (port 30080) ← reads SNI hostname, does NOT decrypt
│
│ forwards encrypted bytes
▼
k8s-proxy (port 8080) ← terminates TLS itself
Envoy looks at the SNI (Server Name Indication)—the hostname in the TLS Client Hello—to decide where to route the connection. It then passes the encrypted bytes straight through to the k8s-proxy without inspecting them. This is why the fqdn in the HTTPProxy must match the hostname the client uses.
[!NOTE] SNI matching means you must access the
k8s-proxyusing the hostname (e.g.https://your-host:30080), not the raw IP address. Add an/etc/hostsentry if needed.
6) Verify the deployment
# Check ArgoCD sees the app
kubectl get applications -n argocd
# Check HTTPProxy status
kubectl get httpproxy -A
# Should show status: valid
# Check k8s-proxy is running
kubectl get pods -n keploy
# Test connectivity through Contour
curl -sk https://<YOUR_INGRESS_HOST>:30080/healthz
# → {"status":"ok"}
✅ Open the Keploy UI → Clusters → your cluster should show as Connected. You can now record and replay traffic on any deployment.
7) Deploy your application with ArgoCD
Your application needs no changes for Keploy. Deploy it as you normally would with ArgoCD—either from Helm charts or raw K8s manifests:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/your-repo.git
targetRevision: main
path: k8s/
destination:
server: https://kubernetes.default.svc
namespace: staging
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Once deployed, your application appears in the Keploy UI under your cluster's Deployments tab. Click Record to start capturing live traffic.
Summary
To add Keploy to an existing ArgoCD setup, you need:
| What | File | Purpose |
|---|---|---|
| ArgoCD Application | keploy-k8s-proxy.yaml | Deploy k8s-proxy from Keploy's Helm chart |
| Contour HTTPProxy | k8s-proxy-httpproxy.yaml | Route HTTPS traffic via TLS passthrough |
| Kubernetes Secret | kubectl create secret (manual) | Access key for Keploy cloud authentication |
Your existing application code, manifests, and ArgoCD Applications remain completely untouched. Keploy works alongside your app—not inside it.