Access remote/self-hosted applications securely with Wireguard

As a huge self-hosted aficionado I do love setting up new self-hosted applications in my home lab. Containerization truly pushed the envelope for homelabber/selfhoster community by drastically reducing LOE required to set things up ( and more importantly maintain things with low effort and low time expenditures).

Im sure any person who ever dabbled with self-hosting at one point or another will desire to access their applications remotely. As in – you know – away from home and thus away from comfortable “homelab” vicinity.

There are many ways of accomplishing that of course, however since the topic is wireguard – that’s what im going to talk about (coincidentally I do consider this to be the best way of doing it anyways – simple, easy, awesome).

While Ive gone through the ways of exposing every single service with SSL/TLS certificates in the past to the internet, but in the long run this turned out to be too much of a hustle. Well – not too “much much”, but enough for me to not want to do it anymore. Some apps support reverse proxies, some dont do it very well, some are well tested and some not. Some are fairly obscure I legitimately not confident in ever exposing them to the internet. Luckily – we dont have to do this (in conventional way).

Get a DDNS address

For starters – in most case you will need a DDNS. Most internet providers (at least here in US) are recycling their pool of ip addresses and chances are you do not have a static ip address and do not have a way of procuring it as a residential costomer. What this means is that you ip address will change after power outage or updating your cable modem or disconnecting you equipment for prolonged periods of time. And of course – this means if you use this ip address in some smartphone app configuration -> you will need to update that. And also in every other app you use. Every single time ip changes. Who wants to deal with that amIright? so just get it.

Im not going to go into this topic in details -there are plenty of tutorials. Just FYI – many many wireless routers do have this functionality built in so chances are you just need to tinker a little bit in router settings.

Launch wireguard service on your home server

You do have a home server right? (if not – get it – it’s totally worth it).

There are many ways of doing this, however Id argue docker/docker-compose are the most straightforward. Personally I very much love and always recommend containers packaged by awesome guys at linuxserver.

All you would need to do is save this docker-compose.yml on a linux server, edit it to your linking and execute docker compose command:

    docker-compose up -d

Example docker-compose.yml:

version: "3.5"

services:
  wireguard:
    image: ghcr.io/linuxserver/wireguard
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/New_York
      - SERVERURL=myddns.myddnsprovider.com
      - SERVERPORT=51820
      - PEERS=1
      - PEERDNS=192.168.10.103 # configure to use internal DNS server
      #- INTERNAL_SUBNET=192.168.10.0 #optional
      #- ALLOWEDIPS=0.0.0.0/0 #optional
    volumes:
      - ./config/config
      - ./modules:/lib/modules
    ports:
      - 51820:51820/udp
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    restart: unless-stopped

That’s it – wireguard VPN is running on you home server.

Find a generated wireguard configuration barcode

Now – we’ve specified number of PEERS above as 1. This means that server will generate just 1 config that we will be using. IN order to find this config you can just look at the logs:

docker-compose logs -f

You should see wireguard config as a scannable barcode, something like this:

Attaching to wireguard
wireguard    | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
wireguard    | [s6-init] ensuring user provided files have correct perms...exited 0.
wireguard    | [fix-attrs.d] applying ownership & permissions fixes...
wireguard    | [fix-attrs.d] done.
wireguard    | [cont-init.d] executing container initialization scripts...
wireguard    | [cont-init.d] 01-envfile: executing... 
wireguard    | [cont-init.d] 01-envfile: exited 0.
wireguard    | [cont-init.d] 10-adduser: executing... 
wireguard    | -------------------------------------
wireguard    |           _         ()
wireguard    |          | |  ___   _    __
wireguard    |          | | / __| | |  /  \ 
wireguard    |          | | \__ \ | | | () |
wireguard    |          |_| |___/ |_|  \__/
wireguard    | Brought to you by linuxserver.io
wireguard    | -------------------------------------
wireguard    | To support the app dev(s) visit:
wireguard    | WireGuard: https://www.wireguard.com/donations/
wireguard    | To support LSIO projects visit:
wireguard    | https://www.linuxserver.io/donate/
wireguard    | -------------------------------------
wireguard    | GID/UID
wireguard    | -------------------------------------
wireguard    | User uid:    1000
wireguard    | User gid:    1000
wireguard    | -------------------------------------
wireguard    | [cont-init.d] 10-adduser: exited 0.
wireguard    | [cont-init.d] 30-config: executing... 
wireguard    | Uname info: Linux 599282cb298c 5.9.16-100.fc32.x86_64 #1 SMP Mon Dec 21 14:10:00 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
wireguard    | **** It seems the wireguard module is already active. Skipping kernel header install and module compilation. ****
wireguard    | **** Server mode is selected ****
wireguard    | **** External server address is set to myddns.myddnsprovider.com ****
wireguard    | **** External server port is set to 51820. Make sure that port is properly forwarded to port 51820 inside this container ****
wireguard    | **** Internal subnet is set to 10.13.13.0 ****
wireguard    | **** AllowedIPs for peers 0.0.0.0/0, ::/0 ****
wireguard    | **** Peer DNS servers will be set to 192.168.10.103 ****
wireguard    | **** No wg0.conf found (maybe an initial install), generating 1 server and 1 peer/client confs ****
wireguard    | grep: /config/peer*/*.conf: No such file or directory
wireguard    | PEER 1 QR code:
wireguard    | █████████████████████████████████████████████████████████████████
wireguard    | █████████████████████████████████████████████████████████████████
wireguard    | ████ ▄▄▄▄▄ █▀▀▄  ▄▀█▀ ▀▀▀▄█▄▄███▀▀▄▄██▀ █▄▀▄▀▄▄▀█▄▄ ██ ▄▄▄▄▄ ████
wireguard    | ████ █   █ █▀ █   █▀█▄ ▀ ███ ▀█▄█ ▀ ▄▄▄  ▄▄██▀  ▄▀▄ ██ █   █ ████
wireguard    | ████ █▄▄▄█ █▀ █▀▀█▄ ██▄█▄ ▀▄▀  ▄▄▄ ▄█▄██ █ ▀█▄█▄▄▄▀▄██ █▄▄▄█ ████
wireguard    | ████▄▄▄▄▄▄▄█▄▀ ▀ ▀▄▀ ▀ █▄█▄█▄█ █▄█ ▀ ▀▄█▄█ █ █▄█▄█▄▀▄█▄▄▄▄▄▄▄████
wireguard    | ████   ▄ ▀▄▄ ▄ ▄▀▀ ▄▀██▀▀▄█  █▄ ▄▄▄▀▄▄▀▄▀▄▀ ▄▄▄ ▄█▀▀▀▄█ ▀▄█▄█████
wireguard    | ████▄█▀▄██▄▄▄▄█ █▄ ▀██ █▀ █  ██▀▀ █▀█ █▄ ██▄▄▄▀▀█  ▀▄ ▄▀▀ ▀█▄████
wireguard    | ████▄▀▀▀ ▄▄ ▀▀█▄▀▄▄ ▄█▀▄█▄ ▄▄  ▄█ ▄▀█▀▄▄▀██▄▄▄▀ ▄▄▄█ ▄▀▀▀▀ ▀█████
wireguard    | █████▄▀ ▀█▄█▄█▀█  ▄ ▀▀ ▀▀▀▄ █▀▄ ▄   ▀ █▄█▄  ▄▀▀▀█▄▀ ▄██▄█ ▀▀▄████
wireguard    | ████▀▀█▄██▄▀█ ▀▄██ █▄ ▄▀███▄▀ ▀██▀ ▀█▄▄▄  █▀▀▀▀ ▀▀█▄█▄▀▄▄   ▀████
wireguard    | ██████ ▄ ▀▄█▄▄▄▄▄▀█▄▀█▄▀█▀▄▀▄▄▀▀▀██▄▀█ █    ▄█  ▀█▄▄▄ ███ ▄▄▀████
wireguard    | ████▀▀▄▄▄▀▄█ ▀▄ ▄▀█ ▄ ▀▀▀▄ ▄█▀▀▄██ ▄▀███ ▄███▄  ██▀█▀▀▄█▄█ ▀█████
wireguard    | █████ █ ▀▀▄▄▄█   ▄  █▄▀▀▀█▄█ █▀ ▄ ▀ ▀  ▄  ▀▀█ ▄▄█▄▄ ▄█  █▀▄ █████
wireguard    | ████▀▄ ▄▄▀▄   ▄█▄██▀▀ ██▄ ███▀▀▀▀ ▄▀▄▄▀▄▀▄▀█▄ ▄ ▄▀▀▀  █▀█▄█ █████
wireguard    | ████▀▀▄▀ ▄▄▄  █▀ ▀ ▀▀█  ▀ ▄  ▀ ▄▄▄ █▀ ▀▄ ▄▄██▄ ▄ ▀█  ▄▄▄    ▄████
wireguard    | ████▄█▀▄ █▄█ █  ▀▀  ▄▄██▀▀▄▄ █ █▄█  █▄▄▄▀▀▀▄██  ████ █▄█ █▀▀▄████
wireguard    | ████▄▄▀▄  ▄ ▄▄▄ ▄▀▄ ▀▄  ▀▄▀█ ▄▄  ▄▄  ██ ▀█▄ █ █▀█ ▄▄▄ ▄    ▀▄████
wireguard    | ████▀ ▀█ ▄▄ ██ █▀█▄▄▄  ▀▄▀▀▀▀▄▀█▄ ▀██ █▄▄ ▄▄█ ▀▄▀ ███▀▄█▄▄▄▀█████
wireguard    | █████ ▄ █▀▄█▄██▄  ██▄█ ▄██ █  ███▀▀▀▀▄▄▄█  █▄█ █▀█▄▀▀▀ ██  ▄█████
wireguard    | ████▄  ▄▀ ▄▀█▄▄▄  █▄▀ ▀▄ ▀▀▀▄▀  ▄   █▀▀█  █▄ ▀▄▄▀ ▀▄▄▀█▄  ▀▀▄████
wireguard    | ████▄ ▀█ ▀▄▄ ▀  █▄▀▄▀▄ ██▄▄█ ▄█▀█▄ ▀ ▀▄   ▀██▄▄██ █▄ ▀ ███▄██████
wireguard    | ████▀ ▄ ▄ ▄▄  ▀█▀█ ▀ █▄▄█▀▄█▀▀█ ▄█▄▀▄ █▄▀▄▀▄▄▄▄ ▄▀▀▄█▀█▄█▀▄▀▀████
wireguard    | ████ ▄   █▄  ▀▄█▄▄▄███▀ ▀ █▄ ▄ █▀▀▄▄█ ▄█▀  ▄█▀██▄██▀▄▄▀▀▀▀▀▀▄████
wireguard    | ████▄▀ █▄ ▄ ▄▀▄█▀▀  ▄▄█ ▀▄ █▀██ █▀ ▀▄▄█▄▀▀█▄▄▄ █▄▄█▀▄ ▀▄▄ ▀▄█████
wireguard    | ████ ▀ ▀▀▄▄█▀▀ ▄▀   ▄▀ █▄█▀ ▄▄▄ █▄ ▄ ▀▄▄█▀▄▄▀▀▀▄▀▄▄▀▄▀▀▀▀   █████
wireguard    | ██████████▄▄ █  ▀▄▄▄▄▄ ▀▄█▀  █ ▄▄▄ ▀█ █  ▀█ █▄▀▄▀█▄▀ ▄▄▄ ▀▀ ▄████
wireguard    | ████ ▄▄▄▄▄ █▄█ ▄█▄▀█▀█ ▀▄▄▀ ██ █▄█ ▄ █▄▄ █▄██ ▀▀▀▀▄▄ █▄█ █  █████
wireguard    | ████ █   █ █ ▀▀ ▀▀█▀ █ ▀▀ ▀█▄▀     ▄▀██▄█ ▀ █ ▄▄█▄▀█ ▄▄  █▀▄█████
wireguard    | ████ █▄▄▄█ █ ▄▀   ▄ ▀▀▀█▀██▀ ▀██▀▄▄██ ▀█▄ █▄█▀  ▀▀▄ ▀▄▀▀█▄▄██████
wireguard    | ████▄▄▄▄▄▄▄█▄▄███▄▄███▄█▄▄███▄▄▄▄▄▄████▄███▄▄▄▄█▄█████▄██▄█▄█████
wireguard    | █████████████████████████████████████████████████████████████████
wireguard    | █████████████████████████████████████████████████████████████████
wireguard    | [cont-init.d] 30-config: exited 0.
wireguard    | [cont-init.d] 99-custom-scripts: executing... 
wireguard    | [custom-init] no custom files found exiting...
wireguard    | [cont-init.d] 99-custom-scripts: exited 0.
wireguard    | [cont-init.d] done.
wireguard    | [services.d] starting services
wireguard    | [services.d] done.
wireguard    | [#] ip link add wg0 type wireguard
wireguard    | [#] wg setconf wg0 /dev/fd/63
wireguard    | .:53
wireguard    | CoreDNS-1.8.1
wireguard    | linux/amd64, go1.15.7, 95622f4
wireguard    | [#] ip -4 address add 10.13.13.1 dev wg0
wireguard    | [#] ip link set mtu 1420 up dev wg0
wireguard    | [#] ip -4 route add 10.13.13.2/32 dev wg0
wireguard    | [#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

See better screenshot below:

Import into wireguard client

Here im just using android wireguard client, there is also an ios wireguard client as well available.

One installed you can just scan above generated barcode configuration in order to import config. You can also of course just import config manually – but where is the fun in that?

Above barcode will generate a config like so in android app:

All you have to do now is trigger the slider to enable wireguard VPN – and you can now access all your homelab apps as if you were on the local network.

Setup port forwarding

Most likely you will need to tinker with your router once more to allow traffic from the internet to pass from port 51820 to your home server port 51820 (ir whatever port you use).

Port forwarding is trivial and I wont go into details here.

That’s it – enjoy your remote/selfhosted services wherever life takes you 🙂

Leave a Comment