---
title: "WireGuard VPN & Adblocking on Kubernetes | codingcoffee"
description: "Build a WireGuard VPN on Kubernetes with Kilo and AdGuard. Follow deployment, key generation and client configuration notes for secure browsing with adblocking."
canonical: "https://www.codingcoffee.dev/blog/wireguard-on-kubernetes-with-adblocking"
published: "2021-03-20"
tags: "blog"
---

# WireGuard on Kubernetes with Adblocking

By Ameya Shenoy · Published 2021-03-20

Build a WireGuard VPN on Kubernetes with Kilo and AdGuard. Follow deployment, key generation and client configuration notes for secure browsing with adblocking.

The Internet is simply unusable with all the ads floating around. While browser extensions like uBlock Origin work for tech-savvy users, most people lack ad protection. I wanted a DNS-level solution combined with VPN capabilities to serve my family.

## Why This Approach?

Three key use cases motivated this setup:

- Preventing ISP data collection on browsing patterns
- Circumventing internet censorship
- Remote access to home network

I evaluated mobile solutions like Blokada and DNS66 but found limitations. Android's VPN service restriction prevents simultaneous VPN connections, meaning custom VPN solutions expose browsing to ISPs. A publicly accessible DNS and VPN server resolves this constraint.

## Technology Selection

**AdGuard Home** was chosen over Pi-Hole because it offers:
- Native DNS-over-TLS support
- Single configuration file
- Golang implementation using fewer resources

**WireGuard** was selected for VPNs due to its speed, auditable codebase, cross-platform support, and Linux kernel integration. **Kilo**, a WireGuard-based network overlay for Kubernetes, enabled the complete setup while securing inter-pod communication and allowing cluster debugging.

## AdGuard Deployment

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: adguardhome
spec:
  selector:
    matchLabels:
      app: adguardhome
  replicas: 1
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 0
  template:
    metadata:
      labels:
        app: adguardhome
    spec:
      volumes:
      - name: tls-cert-secret
        secret:
          secretName: production-tls-cert
      - name: adguard-config
        hostPath:
          path: "/path/to/store/conf"
          type: DirectoryOrCreate
      - name: adguard-logs
        hostPath:
          path: "/path/to/store/work"
          type: DirectoryOrCreate
      containers:
      - name: adguardhome
        image: adguard/adguardhome:v0.102.0
        ports:
        - containerPort: 53
          hostPort: 53
          protocol: UDP
        - containerPort: 53
          hostPort: 53
          protocol: TCP
        - containerPort: 853
          hostPort: 853
          protocol: TCP
        volumeMounts:
        - name: tls-cert-secret
          mountPath: /certs
        - name: adguard-config
          mountPath: /opt/adguardhome/conf
        - name: adguard-logs
          mountPath: /opt/adguardhome/work
      terminationGracePeriodSeconds: 20
---
apiVersion: v1
kind: Service
metadata:
  name: adguardhome
  labels:
    app: adguardhome
spec:
  type: ClusterIP
  selector:
    app: adguardhome
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
```

The rolling update strategy intentionally terminates existing pods without waiting for new ones. This is necessary because `hostPort` binding to port 53 prevents concurrent pod scheduling.

Initial setup requires accessing the admin UI on port 3000. After configuration, revert the service `targetPort` to 80.

Optional enhancements include:
- DNSSEC for DNS response authenticity verification
- DNS-over-TLS using certificate paths `/certs/tls.crt` and `/certs/tls.key`

### Mobile DNS Configuration

Android Pie and later: Navigate to Settings > WiFi and Internet > Private DNS, select "Private DNS Hostname Provider," and enter your configured domain. Configure routers at the network level for device-wide protection.

## WireGuard Setup

### Prerequisites

Install WireGuard on both server (k3s cluster) and client machines. Install `kgctl` on the client:

```bash
go get github.com/squat/kilo/cmd/kgctl
```

### Kilo Installation

Download and modify the k3s manifest:

```bash
curl -LO https://raw.githubusercontent.com/squat/kilo/master/manifests/kilo-k3s.yaml
```

Add `--mesh-granularity=full` to the kilo container args in the DaemonSet:

```yaml
containers:
- name: kilo
  image: squat/kilo
  args:
  - --kubeconfig=/etc/kubernetes/kubeconfig
  - --hostname=$(NODE_NAME)
  - --mesh-granularity=full
  env:
  - name: NODE_NAME
    valueFrom:
      fieldRef:
        fieldPath: spec.nodeName
```

Apply the manifest:

```bash
kubectl apply -f kilo-k3s.yaml
```

### Client Key Generation

```bash
wg genkey | tee privatekey | wg pubkey > publickey
```

### Server-Side Peer Authorization

Create `archie.yaml`:

```yaml
apiVersion: kilo.squat.ai/v1alpha1
kind: Peer
metadata:
  name: archie
spec:
  allowedIPs:
  - 10.120.120.1/32
  publicKey: CLIENT_PUBLIC_KEY
  persistentKeepalive: 10
```

```bash
kubectl apply -f archie.yaml
```

### Generate Client Configuration

```bash
kgctl showconf peer archie
```

Output:

```
[Peer]
AllowedIPs = 10.42.0.0/24, 10.42.0.0/32, 10.4.0.1/32
Endpoint = YOUR_SERVER_IP:51820
PersistentKeepalive = 10
PublicKey = SERVER_PUBLIC_KEY
```

### Client Configuration

Create `/etc/wireguard/adguard.conf`:

```bash
[Interface]
Address = 10.120.120.1/32
PrivateKey = CLIENT_PRIVATE_KEY
DNS = YOUR_SERVER_IP

[Peer]
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = YOUR_SERVER_IP:51820
PersistentKeepalive = 10
PublicKey = SERVER_PUBLIC_KEY
```

The `0.0.0.0/0, ::/0` configuration routes all traffic through the VPN interface.

### Connection Management

```bash
wg-quick up adguard
```

Verify connectivity at https://ifconfig.io - your IP should match the server's IP.

```bash
wg-quick down adguard
```

### Mobile Integration

Generate a QR code for Android app scanning:

```bash
qrencode -t ansiutf8 < /etc/wireguard/adguard.conf
```

Install the WireGuard Android app from F-Droid and scan the code to import the configuration.

## Results

This setup provides:
- Complete ISP traffic isolation
- DNS-level ad filtering across all connected devices
- Network malware protection
- Cross-network device communication regardless of physical location
- Centralized infrastructure management via Kubernetes

---

Canonical page: https://www.codingcoffee.dev/blog/wireguard-on-kubernetes-with-adblocking

[Site guide](/llms.txt) · [Contact](/contact) · [Sitemap](/sitemap-index.xml)
