
π Secure Kubernetes Access with Teleport: No More Port-Forwarding Pain
I run oursi.net on a self-hosted Kubernetes cluster, and I manage everything through ArgoCD. But like many of you, I was getting tired of doing this every time I wanted to check my deployments:
1kubectl port-forward svc/argocd-server -n argocd 8080:8080
And then navigating to https://localhost:8080
. Meh.
So I decided to deploy Teleport.
π§ What is Teleport?
Teleport is a secure access platform β like a modern Bastion host on steroids. It gives you:
- a web interface
- CLI access
- and zero trust authentication across SSH, Kubernetes, databases, and web apps
β¦ all from a single login (including passkeys or OTP).
In my case, I wanted to use Teleport to securely expose internal services (like ArgoCD and Argo Workflows) without making them public.
π οΈ Installing Teleport via Helm + ArgoCD
I use GitOps, so everything goes through ArgoCD. The first step is to deploy the main teleport cluster.
1apiVersion: argoproj.io/v1alpha1 2kind: Application 3metadata: 4 name: teleport 5 namespace: argocd 6spec: 7 project: default 8 source: 9 repoURL: https://charts.releases.teleport.dev 10 chart: teleport-cluster 11 targetRevision: 17.5.1 12 helm: 13 values: | 14 clusterName: "teleport.oursi.net" 15 service: 16 type: ClusterIP 17 ingress: 18 enabled: false 19 proxyListenerMode: multiplex 20 acme: false 21 tls: 22 existingSecretName: teleport-tls-cert 23 operator: 24 enabled: true 25 persistence: 26 enabled: true 27 storageClassName: "local-path" 28 size: 10Gi 29 log: 30 level: INFO 31 resources: 32 limits: 33 cpu: 500m 34 memory: 512Mi 35 requests: 36 cpu: 250m 37 memory: 256Mi 38 destination: 39 server: https://kubernetes.default.svc 40 namespace: teleport-cluster 41 syncPolicy: 42 automated: 43 prune: true 44 selfHeal: true 45 syncOptions: 46 - CreateNamespace=true
π TLS with cert-manager
I created a TLS certificate using cert-manager and Let's Encrypt:
1apiVersion: cert-manager.io/v1 2kind: Certificate 3metadata: 4 name: teleport-tls-cert 5 namespace: teleport-cluster 6spec: 7 secretName: teleport-tls-cert 8 dnsNames: 9 - teleport.oursi.net 10 - "*.teleport.oursi.net" 11 issuerRef: 12 name: letsencrypt-issuer 13 kind: ClusterIssuer 14 group: cert-manager.io
This is the secret referenced in the Teleport cluster Helm chart.
π Exposing Teleport with Traefik (IngressRouteTCP)
Teleport speaks native TLS over TCP. Regular Ingress didnβt work well, so I used IngressRouteTCP
from Traefik:
1apiVersion: traefik.io/v1alpha1 2kind: IngressRouteTCP 3metadata: 4 name: teleport-tcp 5 namespace: teleport-cluster 6spec: 7 entryPoints: 8 - websecure 9 routes: 10 - match: HostSNI(`teleport.oursi.net`) 11 services: 12 - name: teleport 13 port: 443 14 nativeLB: true 15 - match: HostSNI(`argocd.teleport.oursi.net`) 16 services: 17 - name: teleport 18 port: 443 19 nativeLB: true 20 - match: HostSNI(`argowf.teleport.oursi.net`) 21 services: 22 - name: teleport 23 port: 443 24 nativeLB: true 25 tls: 26 passthrough: true
The only downside is that I must reference each new application's hostname here as well.
π€ Creating a User with Teleport CRD
To create my teleport user, with admin access, I use this yaml:
1apiVersion: resources.teleport.dev/v2 2kind: TeleportUser 3metadata: 4 name: benoit 5 namespace: teleport-cluster 6spec: 7 roles: 8 - access 9 - editor
It will create the user, but you still need to set up a password for it. To do so, generate a password reset link:
1kubectl -n teleport-cluster exec -ti deployment/teleport-auth -- tctl users reset benoit
Follow the link and boom, you're in β¨
π Installing the Kube Agent
Now to expose ArgoCD and Argo Workflows, I deployed the teleport-kube-agent
.
First, create a join token:
1apiVersion: resources.teleport.dev/v2 2kind: TeleportProvisionToken 3metadata: 4 name: kubernetes-app-token 5 namespace: teleport-cluster 6spec: 7 roles: [App] 8 join_method: kubernetes 9 kubernetes: 10 type: in_cluster 11 allow: 12 - service_account: "teleport-cluster:teleport-agent"
Then install the Helm chart via ArgoCD:
1apiVersion: argoproj.io/v1alpha1 2kind: Application 3metadata: 4 name: teleport-agent 5 namespace: argocd 6spec: 7 project: default 8 source: 9 repoURL: https://charts.releases.teleport.dev 10 chart: teleport-kube-agent 11 targetRevision: 17.5.1 12 helm: 13 values: | 14 proxyAddr: "teleport.oursi.net:443" 15 roles: app 16 joinParams: 17 method: "kubernetes" 18 tokenName: "kubernetes-app-token" 19 apps: 20 - name: argocd 21 uri: "https://argocd-server.argocd.svc.cluster.local" 22 public_addr: argocd.teleport.oursi.net 23 insecure_skip_verify: true 24 rewrite: 25 redirect: 26 - argocd-server.argocd.svc.cluster.local 27 - name: argowf 28 uri: "https://argo-server.argo.svc.cluster.local:2746" 29 public_addr: argowf.teleport.oursi.net 30 insecure_skip_verify: true 31 rewrite: 32 redirect: 33 - argo-server.argo.svc.cluster.local 34 destination: 35 server: https://kubernetes.default.svc 36 namespace: teleport-cluster 37 syncPolicy: 38 automated: 39 prune: true 40 selfHeal: true 41 syncOptions: 42 - CreateNamespace=true
π Result
Now, I can go to:
https://argocd.teleport.oursi.net
https://argowf.teleport.oursi.net
β¦ log in with passkeys, and enjoy secure access from anywhere π
Teleport abstracts the pain of port forwarding, secure tunneling, and multi-cluster auth into a slick interface. Highly recommend for anyone doing GitOps or running internal tools!