Skip to main content

VPN with Wireguard in Docker: Secure access to internal services without exposing ports

Rogelio Guerra Riverón
Author
Rogelio Guerra Riverón
Building my own web infrastructure from scratch. Here I document each step: servers, networks, containers and everything that comes along.

Why you need this
#

A few months ago I faced a common problem: I wanted to access my internal services (Jellyfin, Home Assistant, etc.) from outside my home, but I didn’t want to expose them directly on the internet. Opening ports is an unnecessary risk. The solution was to set up a VPN with Wireguard in Docker. It was the best decision I made for my home infrastructure.

Advantages of Wireguard
#

  • Lightweight: consumes fewer resources than OpenVPN
  • Fast: modern and efficient protocol
  • Easy to configure: compared to other alternatives
  • Secure: state-of-the-art cryptography
  • Docker-friendly: there are excellent official images

Preparation
#

You need:

  • A server with Docker installed
  • The docker-compose.yml file
  • A domain or public IP (to connect from outside)
  • Wireguard clients on your devices

Step-by-step installation
#

1. Create the configuration directory
#

mkdir -p ~/wireguard/config
cd ~/wireguard

2. Docker Compose
#

Create the docker-compose.yml file:

version: '3.8'

services:
  wireguard:
    image: linuxserver/wireguard:latest
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Madrid
      - SERVERURL=tu-dominio-o-ip-publica.com
      - SERVERPORT=51820
      - PEERS=telefono,laptop,tablet
      - PEERDNS=auto
    ports:
      - "51820:51820/udp"
    volumes:
      - ./config:/config
      - /lib/modules:/lib/modules:ro
    networks:
      - mi-red
    restart: unless-stopped

networks:
  mi-red:
    driver: bridge
    ipam:
      config:
        - subnet: 10.0.0.0/24

Replace:

  • tu-dominio-o-ip-publica.com with your actual address
  • The PEERS with the names of your devices
  • The timezone according to your location

3. Start the container
#

docker-compose up -d

Configuration files will be automatically generated in ./config. Wait a few seconds and verify:

ls -la config/peer_*/

4. Get the QR codes
#

To connect your devices:

docker exec wireguard cat /config/peer_telefono/peer_telefono.conf

Or directly the QR codes:

docker exec wireguard qrencode -t ansiutf8 < /config/peer_telefono/peer_telefono.conf

Scan with your Wireguard client on each device.

Connecting internal services
#

This is the important part. I want to access services on my internal network. To do this, I modify the docker-compose.yml and add routes:

environment:
  - ALLOWEDIPS=10.0.0.0/24,192.168.1.0/24

This allows you to access the 192.168.1.0/24 network (your local network) from the VPN.

On the server, enable forwarding:

echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Access from clients
#

Once connected to the VPN, you access your services using their internal IPs:

  • http://192.168.1.100:8096 for Jellyfin
  • http://192.168.1.50:8123 for Home Assistant
  • Whatever you need on your network

Maintenance
#

Renew certificates (approximately every 6 months):

docker exec wireguard /app/wireguard-tools/show-peer peer_nombre

Add a new device:

docker-compose down
# Edita PEERS en docker-compose.yml
docker-compose up -d

Final notes
#

  • Open only port 51820/UDP on your router
  • Use firewall on the server to block unnecessary access
  • Verify that IP forwarding is active
  • Monitor VPN traffic regularly

I’ve been running this setup for several months and it’s completely stable. I access my services from anywhere without security concerns. I definitely recommend this setup to anyone who wants to keep their home infrastructure private but accessible.


Recommended equipment#

Affiliate links. No extra cost for you.