Easy WireGuard VPN Server for Your Kubernetes Cluster

Easy WireGuard VPN Server for Your Kubernetes Cluster
Photo by Privecstasy / Unsplash

Want quick, secure VPN access to your cluster—without a dedicated VPS? This guide shows you how to install a WireGuard VPN server inside your Kubernetes cluster (great for accessing Pod IPs, Service IPs, and internal FQDN).

If you’re aiming for production-grade, it’s best to run WireGuard on a separate, dedicated VPS. But for internal or dev environments, this method is perfect.


We will be using the wg-easy helm template

Step 1: Generate a Password Hash

Before installing, generate a bcrypt hash for your WireGuard UI password.

Run this command locally (requires Docker):

docker run ghcr.io/wg-easy/wg-easy:14 wgpw secret        
PASSWORD_HASH='$2a$12$j.imiU1h7MBYJ3jVi09SYOpW9TNuPac0xIQ28sASV4KphAOU9n.YO'

Copy the PASSWORD_HASH value—you’ll need it soon.


Step 2: Get Your Node IP and Cluster DNS

You’ll need the external IP of your node (not an internal 10.x.x.x or 172.x.x.x address), and the cluster DNS IP.

Find them using:

kubectl get node -o wide

Next you'll need the DNS service provider of your cluster (mostly coredns, or kube-dns)

kubectl get svc -n kube-system
NAME             TYPE        CLUSTER-IP
kube-dns         ClusterIP   10.43.0.10

Note the EXTERNAL-IP (or INTERNAL-IP, if applicable) of your node.


Step 3: Add the Helm Repo and Create a Values File

Add the wg-easy Helm chart:

helm repo add wg-easy https://raw.githubusercontent.com/hansehe/wg-easy-helm/master/helm/charts
enabled: true
replicaCount: 1

environmentVariables:
  WG_HOST: <your-node-ip>
  PASSWORD_HASH: "<your-password-hash>"
  WG_DEFAULT_DNS: "<your-cluster-dns-ip>"

securityContext:
  capabilities:
    add:
      - NET_ADMIN
      - SYS_MODULE

service:
  type: NodePort
  port: 51820

resources:
  limits:
    cpu: 100m
    memory: 128Mi
  requests:
    cpu: 50m
    memory: 128Mi

volume:
  enabled: true
  size: 100m

wireguard.yaml


Step 4: Install WireGuard with Helm

Deploy into its own namespace:

helm upgrade --install --namespace wireguard --create-namespace wg-easy wg-easy/wg-easy --values ./wireguard.yaml

Step 5: Find Your Service Ports

WireGuard exposes two ports:

  • 51820/UDP – the VPN port
  • 51821/TCP – the UI port

List services to see which NodePorts were assigned:

kubectl get svc -n wireguard

Example output:

NAME      TYPE       CLUSTER-IP     PORT(S)
wg-easy   NodePort   x.x.x.x        51820:30222/UDP,51821:30223/TCP

Here, 30222 is the public VPN port, 30223 is the public UI port.


Step 6: (Optional) Use LoadBalancer Instead of NodePort

If you have multiple nodes, switch the service type to LoadBalancer in your wireguard.yaml, then redeploy:

service:
  type: LoadBalancer

After deployment, find your external IP with:

kubectl get svc -n wireguard

Update your WG_HOST in the values file to this IP, and re-run the helm upgrade command.

environmentVariables:
  WG_HOST: <ip-of-your-node>

Step 7: Connect!

  1. Open the WireGuard UI at http://<external-ip>:<ui-port>, log in with your password, and create a client.
  2. Download the generated .conf file.

Important:

Update the Endpoint in your client config with the correct public port mapped to 51820/UDP.

For example:

Endpoint = 31.12.282.192:30222

Step 8: Test Your VPN

After connecting, you should have full access to the cluster’s Pod IPs, Service IPs, and FQDN (e.g., http://wg-easy.wireguard.svc.cluster.local:51821/).

This address is the kubernetes FQDN which resolves services inside the cluster, cool right?


Step 9: Secure the UI

For security, restrict the WireGuard UI so it’s not exposed to the public Internet.

kubectl edit svc wg-easy

Find and delete the http-ui port entry:

ports:
  - name: udp-vpn
    nodePort: 30763
    port: 51820
    protocol: UDP
    targetPort: udp-vpn
  # Remove or comment out the following
  - name: http-ui
    nodePort: 30654
    port: 51821
    protocol: TCP
    targetPort: http-ui

Save and exit.


That’s it!

You now have secure VPN access into your Kubernetes cluster—no extra VPS required.

Enjoy full access to Pod and Service networking, cluster DNS, and more.

Questions or feedback? Leave a comment below!