# Hosting Your Own VPN on a £1 VPS

> Build your own VPN for privacy.

By Zsolt Bizderi · Published 2025-05-24
Canonical: https://ambientnode.uk/hosting-your-own-vpn-on-a-1-vps

I’ve long been a fan of self-hosted infrastructure, but until recently, my VPNs were always built [for internal access](/wireguard-vpn/). This time, I decided to go a step further, building my own personal VPN server for privacy and IP/location masking.

RackNerd recently dropped a £1/month VPS deal via [LowEndBox](https://lowendbox.com/blog/new-vps-specials-by-racknerd-kvm-vps-in-multiple-locations-from-10-96-year/) (not sponsored), and I couldn’t resist the temptation to spin something up.

## VPS Specs

Here’s what you get for just over a tenner per year:

* 1x vCPU Core
* 1GB RAM
* 20GB SSD Storage
* 2TB Bandwidth
* 1Gbps Port
* Dedicated IPv4
* Full Root Access
* KVM Virtualisation

This setup is more than enough to run a lean, secure WireGuard VPN.

---

## Quick Setup Guide

### 1. SSH In & Update

```
ssh root@your.server.ip
passwd  # change root password
apt-get update && apt-get upgrade -y
```

---

### 2. Install Docker & Docker Compose

```
apt-get install -y ca-certificates curl gnupg lsb-release

mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
  $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io

# Install Docker Compose
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

docker --version
docker-compose --version
```

---

### Set Up SSH Key Auth

On your local machine:

```
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
ssh-copy-id root@your.server.ip
```

Or do it manually if `ssh-copy-id` isn’t available.

Then disable password auth on the server:

```
nano /etc/ssh/sshd_config
```

Make sure these lines are set:

```
PermitRootLogin yes
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
```

Restart SSH:

```
systemctl restart ssh
```

Test your key login before closing your current session!

---

### Deploy WireGuard with `wg-easy`

First, generate a secure password hash:

```
docker run ghcr.io/wg-easy/wg-easy wgpw 'YOUR_PASSWORD'
```

Take note of the hash output, remember to double all dollar signs ($$) when pasting into `docker-compose.yml` as per below.

---

#### Sample `docker-compose.yml`

```
volumes:
  etc_wireguard:

services:
  wg-easy:
    image: ghcr.io/wg-easy/wg-easy
    container_name: wg-easy
    environment:
      - LANG=en
      - WG_HOST=YOUR_SERVER_IP
      - PASSWORD_HASH=$$2a$$12$$abc123...  # use your generated hash
      - WG_PORT=51820
      - WG_DEFAULT_ADDRESS=10.8.0.x
      - WG_DEFAULT_DNS=8.8.8.8,1.1.1.1
      - WG_MTU=1420
      - WG_ALLOWED_IPS=0.0.0.0/0
      - WG_PERSISTENT_KEEPALIVE=25
      - UI_TRAFFIC_STATS=true
      - UI_CHART_TYPE=2
    volumes:
      - etc_wireguard:/etc/wireguard
    ports:
      - "51820:51820/udp"
      - "51821:51821/tcp"
    restart: always
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv4.conf.all.src_valid_mark=1
```

Start the container:

```
docker-compose up -d
```

---

### Enable IP Forwarding

```
echo 1 > /proc/sys/net/ipv4/ip_forward
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
```

---

### Set Up NAT (Masquerading)

```
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
```

Persist iptables rules:

```
mkdir -p /etc/iptables
iptables-save > /etc/iptables/rules.v4

crontab -e
```

Add:

```
@reboot iptables-restore < /etc/iptables/rules.v4
```

---

## Result: Your Own Private VPN

At this point, you’ve got a fully functioning WireGuard VPN that routes all your internet traffic via your VPS and hides your IP and location.

Manage it via a web UI (`http://your.server.ip:51821`) to create clients as [described](/wireguard-vpn/) in my other post.

Minimal resources, maximum control.
