Access a remote server from a mobile phone via WireGuard #
Introduction #
I self-host a few apps on my home network, using a small single-board computer as my server.
Until recently, I was only able to access my self-hosted apps at home on my home network. That limitation caused me a few problems.
For example, one of the apps I self-host is Actual, an open-source budgeting app that totally changed the way I manage my personal finances. I love Actual, and I love the idea of keeping my financial data on my home network away from prying eyes. However, my inability to access Actual remotely meant I couldn’t update my budget or add transactions without being at home. Annoying!
My solution? Use WireGuard to create a secure VPN tunnel to my home server, allowing me to access my self-hosted apps from anywhere.
Requirements #
This article describes how to create a bare-bones WireGuard setup that satisfies my basic requirements:
- I need access to resources on a single server. I don’t need to access anything else on my home network or on the internet through the tunnel.
- I must be able to use my phone as the “client” to access the server.
My server is running Ubuntu 20.04.6 LTS on the ARMv7 architecture.
A note on terminology
In this article, I use the terms server and client to describe the two endpoints of a WireGuard tunnel. I also use the WireGuard term peer to refer to these endpoints in the abstract.
Instructions #
Install WireGuard #
Install WireGuard on the server using the installation method of your choice. I’m on Ubuntu, so I use the apt
package manager:
$ sudo apt install wireguard
Test that WireGuard installed successfully by running the wg
command. No output means the installation was successful.
Generate keys #
WireGuard relies on encrypted keys for authentication between peers. Each peer needs to have a private key and an associated public key that’s derived from the private key.
-
Create a private and public key for the server with the following command:
$ wg genkey | tee privatekey | wg pubkey > publickey
wg genkey
: Generates a private keytee privatekey
: Saves the private key in a file calledprivatekey
and writes the private key to stdout.wg pubkey > publickey
: Generates a public key from the private key and saves the public key in a file calledpublickey
-
Generate another set of private and public keys, this time for the client. Give the key files a unique name. For example, prepend
mobile
to indicate the keys are for a mobile phone.$ wg genkey | tee mobileprivatekey | wg pubkey > mobilepublickey
With the private and public keys ready, you’re ready to configure the WireGuard tunnel. To do so, you’ll create two configuration files, one for the server and one for the client.
Configure the server #
-
On the server, create a config file for an interface called
wg0
at/etc/wireguard/wg0.conf
. Add the following configuration:[Interface] Address = 192.168.2.1/32 ListenPort = 51820 PrivateKey = serverprivatekey
Address
: An IP address and subnet for the server’s interface on WireGuard’s virtual network. It shouldn’t overlap with any subnet in use on the server’s LAN. In this basic use case with only two peers, the interface’s subnet consists of a single IP address.ListenPort
: The port the interface is listening on.PrivateKey
: The server private key you generated in Generate the server and client keys.
-
Restrict the permissions of
wg0.conf
:$ chmod 600 /etc/wireguard/wg0.conf
Configure the client #
-
Create another config file at
/etc/wireguard/mobile.conf
for the client configuration.[Interface] Address = 192.168.2.2/32 PrivateKey = mobileprivatekey [Peer] PublicKey = serverpublickey Endpoint = mydomain.duckdns.org:51820 AllowedIPs = 192.168.2.1/32, 192.168.86.99/32
The
[Interface]
section defines the client interface.Address
: An IP address and subnet for the client’s interface on WireGuard’s virtual network. Like in the server interface configuration, the subnet here is just a single IP address.PrivateKey
: The client private key you generated in Generate server and client keys.
The
[Peer]
section tells the client interface how to connect to the server interface.PublicKey
: The server’s public key.Endpoint
: A publicly accessible domain name or IP address1 for the server, plus theListenPort
specified in the server interface configuration2.AllowedIPs
: IP addresses that the client should accept traffic from over its WireGuard interface. To connect to resources on my home server, I entered two IP addresses:- The IP address of the server’s WireGuard interface defined in
wg0.conf
- The IP address of the server on my LAN at home
- The IP address of the server’s WireGuard interface defined in
1 The IP address assigned by my ISP is dynamic, so I use a DuckDNS domain name that always points to my public IP, even when it changes.
2 You’ll need to set up port forwarding on the server’s network gateway to forward traffic on this port to the
ListenPort
defined in the server’s interface configuration. -
Restrict the permissions of
mobile.conf
:$ chmod 600 /etc/wireguard/mobile.conf
-
Go back to the server configuration in
wg0.conf
and create aPeer
section with information about the client.[Peer] PublicKey = mobilepublickey AllowedIPs = 192.168.2.2/32
PublicKey
: The client’s public keyAllowedIPs
: IP addresses that the server interface should be able to send packets to. In this case, there’s only one: the IP address of the client’s WireGuard interface defined inmobile.conf
.
At this point it might be helpful to review the contents of the two configuration files side-by-side:
/etc/wireguard/wg0.conf
[Interface]
Address = 192.168.2.1/32
ListenPort = 51820
PrivateKey = serverprivatekey
[Peer]
PublicKey = mobilepublickey
AllowedIPs = 192.168.2.2/32
/etc/wireguard/mobile.conf
[Interface]
Address = 192.168.2.2/32
PrivateKey = mobileprivatekey
[Peer]
PublicKey = serverpublickey
Endpoint = mydomain.duckdns.org:51820
AllowedIPs = 192.168.2.1/32, 192.168.86.99/32
In the server configuration, the peer’s AllowedIPs
value is the same as the client interface’s Address
. Likewise, in the client configuration, one of the peer’s AllowedIPs
is the server interface’s Address
.
Set up the client #
At this point, you’ve created the server and client configuration and have the server interface running. Now you need to get the client configuration onto your phone.
-
On the server, download
qrencode
:$ sudo apt install qrencode
-
Use
qrencode
to generate a QR code frommobile.conf
. My server has no desktop environment, so I used theansiutf8
option to specify that the QR code should be in a plain text format.$ qrencode -t ansiutf8 < /etc/wireguard/mobile.conf
-
Open the QR code. If you have a plain text QR code, you can use
cat
or a text editor likenano
to display it.$ cat /etc/wireguard/mobile.conf
-
On your phone, download the WireGuard mobile app.
-
In the WireGuard mobile app, add a new tunnel and select Create from QR code.
-
Use your phone to scan the QR code and save the settings.
Start the interfaces and connect #
- On the server, add the WireGuard service to
systemd
so thewg0
interface starts automatically when the server boots up:$ sudo systemctl enable wg-quick@wg0.service $ sudo systemctl daemon-reload
- Start the WireGuard service:
$ sudo systemctl start wg-quick@wg0.service
- On your phone, use the WireGuard mobile app to activate the client interface.
You should now have an active, encrypted WireGuard tunnel between your server and phone. Enjoy accessing your server from anywhere!