Kubernetes
Securely exposing Kubernetes services with Twingate
This article walks you through how to securely expose Kubernetes services using Twingate without relying on VPNs, public IPs, or complex Ingress setups.
Jubril Oyetunji
May 27, 2025
Published on
May 27, 2025
Read More
Divine Odazie
19 Jan, 2025
This article walks you through how to securely expose Kubernetes services using Twingate without relying on VPNs, public IPs, or complex Ingress setups.

Kubernetes offers several ways to expose your applications, with one of them being to use Ingress.

Load balancers are great if you are running in a production environment, and you can create so many in the cloud before your bill starts to run up. For local/development environments, Nodeports work, but now you have exposed that node to the entire network or public internet.

And then, of course, we have the tried-and-true kubectl proxy, which forwards all requests to your local machine. This is great, but it can leave numerous terminal windows open with kubectl proxy running. Moreover, all these methods operate under the assumption that you want this service exposed to the internet in the first place.

You can argue that this is the exact case for a VPN, and you will be right. At the same time, VPNs also introduce a new class of problems, particularly with regard to identity. In this post, we will look at a neat solution from Twingate that allows you to securely access your Kubernetes services without a VPN or exposing them to the public internet.

The problem with identity-based access

Before going further, there are a few things to understand about why identity-based access, especially through traditional VPNs, starts to become painful as your infrastructure grows.

VPNs were designed for a world where you had a single perimeter, and everything inside it could more or less trust each other. The assumption is that if you can connect to the network, you're allowed to be there. That might have worked fine when access was limited to a small group of users or when apps lived in a static data center, but it doesn’t hold up in a world where you have developers in different time zones with services spread across clusters.

This is where the shift to zero trust starts to make sense. Cloudflare has been championing this for years, but the idea is simple: don’t trust anyone by default, not even someone on your network. Instead, enforce access controls at the application level, based on who the user is, what they’re trying to access, and whether they meet certain conditions (like device trust or time of day). Every request is verified, not just the initial login.

How does Twingate fits in?

Twingate is a tool that helps make the zero trust model practical.

Instead of dropping a VPN gateway in the middle of your cluster, it creates secure, peer-to-peer connections between your device and the services you’ve been granted access to. No public IPs, no Ingress, no NodePorts, just direct access over a secure tunnel that’s authorized by your identity and enforced client-side.

This is especially useful for Kubernetes clusters where you want to expose internal tools like dashboards, APIs, or internal services without making them internet-facing or adding extra authentication layers.

Prerequisites

This tutorial assumes some familiarity with Kubernetes. Additionally, you will need the following in order to follow along:

  • A Twingate account:  If you do not have one already, you can create a free account here.
  • Twingate client: To connect to the private tunnel Twingate creates, you will need the desktop client for your operating system.
  • A Kubernetes cluster: Minikube was used in this tutorial; however, any recent release of Kubernetes will suffice.

Connectors: How Twingate can reach your private network

Because there is no central VPN, Twingate uses connectors to provide you with access to your services without exposing them to the public internet, as tempting as it is to think of this as a “VPN”, connectors are different in that they:

  • Always reside behind a firewall, within a private network where protected resources are connected.
  • Only allow individual network connections to proceed to the resources that users are authorised to access.

Creating a Twingate connector

To create a connector for your cluster, begin by heading to your Twingate dashboard and following the steps in the GIF below, for this demonstration you will need to select the helm connector as it is the most stright forward way to install it on your Kubernetes cluster.

https://www.dropbox.com/scl/fi/igw1ubbv15zmntpcpmxd3/Screen-Recording-2025-05-07-at-11.37.19-AM.mov?rlkey=bfbdgzpdtu4fag9ndqklbs7uz&dl=0

Deploying a connector prompts you to create a new Remote Network. Remote networks in Twingate are logical containers that group resources together.  

Additionally, you will need to generate tokens for your connector - as shown in the GIF above,  to authenticate your cluster.

 

Deploying the Twingate connector

With a connector and tokens generated, the next step is to use the Twingate Helm chart to install the connector on your cluster.

Add the Twingate Helm repo:

helm repo add twingate https://twingate.github.io/helm-charts

Install the chart:

helm upgrade --install twingate-connector twingate/connector -n default \
    --set connector.network=[network] \
    --set connector.accessToken=[accessToken] \
    --set connector.refreshToken=[refreshToken]

Verify the installation:

kubectl get pods

The output is similar to:

Similarly, the connector section of your Twingate dashboard should now look like this:

Deploy a sample application

To test the connector, you will need an application. In practice, this could be a development build of your app or an internal service. But for this demonstration, you will use the whoami service from Traefik Labs.

Head back to your terminal and apply the following manifest:

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: traefik/whoami
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: whoami
  namespace: default
spec:
  selector:
    app: whoami
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
EOF

The output is similar to:

Twingate resources; the demo application

Resources in Twingate represent an application you’d like to access; for this demonstration, that will be the whoami application.  

Begin by obtaining the IP of the whoami service. This is required for Twingate to route requests appropriately.

kubectl get svc/whoami

The output will be similar to:

Copy the cluster IP of the service, head over to the remote networks section of your Twingate dashboard, and follow the steps below to create a new resource

https://www.dropbox.com/scl/fi/sbver8iy45vs5xxf8b5aa/Screen-Recording-2025-05-07-at-12.54.16-PM.mov?rlkey=t1he33ctdnx1yw21nmy0qrmpy&dl=0

When creating a new resource, you will paste in the internal IP of the Kubernetes service you created earlier. Additionally, you set up an alias, which is a custom domain name you can use to reach the application.

Finally, you will be prompted to select who has access to the new resource. For this demonstration, you can select everyone. However, Twingate has more fine-grained access controls, which you should check out for production deployments.

Accessing your resource

Once a resource has been created, you can reach it via the alias created earlier (whoami.world). For this to work, you need to be signed in and be connected through the Twingate client. For Mac OS users, you can verify your connection by clicking on the Twingate icon in your menubar. Similar steps apply to other operating systems.

https://www.dropbox.com/scl/fi/rt0ryfgjw390r9kmc3j79/Screen-Recording-2025-05-07-at-1.02.51-PM.mov?rlkey=6ez5qtumeg1y3kk9p61hbo8tw&dl=0

Notice the Twingate client also populates the menubar with the resource you just added.

In your browser, head over to the address you copied from the menu bar, and you should be greeted with a page similar to this:

And there you go!

You have successfully exposed your internal app on your machine without exposing it to the public internet or battling an ingress controller. This also allows you to share this resource with other users within your Twingate organisation.

Is it time to ditch your VPN?

Securely exposing your applications can be quite the challenge especially as your organization starts to scale and develop more services, which is why Twingate is an interesting solution for exposing applications that do not necessarily need to be internet-facing.

In this post, we covered how to use the Twingate connector for Kubernetes to expose an application. However, Twingate supports more services which are worth checking out.

Stay ahead with the latest updates, exclusive insights, and tailored solutions by joining our newsletter.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
What is your email addres?
Featured posts
Getting Started with Kubernetes Ingress
This is some text inside of a div block.
This is some text inside of a div block.

Stay ahead with the latest updates, exclusive insights, and tailored solutions by joining our newsletter.

We care about your data in our privacy policy.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
ABOUT THE AUTHOR