We want to be able to securely sync between the cloudbox and back on-prem (for a local plex server). As a result we'll configure a wireguard
VPN link between the two and then setup a rsync
daemon on the cloudbox.
See Wireguard vs OpenVPN on a local Gigabit Network for a performance comparison. I've gone with Wireguard over OpenVPN based on it being incorporated into the Linux Kernel and increased performance versus OpenVPN. In addition, there's a useful walkthrough on How to setup your own VPN server using WireGuard on Ubuntu that I leaned on during this process. It's not quite right though and had some errors in.
Install wireguard pre-reqs on both boxes
sudo apt-get -y install software-properties-common; \
sudo add-apt-repository -y ppa:wireguard/wireguard; \
sudo apt-get install -y wireguard; \
sudo modprobe wireguard # activate kernel module
Generate public/private keypair (on both boxes)
sudo -s # do this as root
cd /etc/wireguard; \
umask 077; \
wg genkey | sudo tee privatekey | wg pubkey | sudo tee publickey
exit # drop back to your user
We need to create a network interface now for the wireguard VPN. I'm going to set the cloudbox as the server
as it will always have a fixed IP address and will not need to store any reference to my home IP (it'll be a pull).
Common convention is to use wg0
as a name for this. In addition we also need to choose a subnet
for the VPN addresses. As I've got a 192.168.0.1/24
configuration at home I'll use 10.10.0.1/24
for the VPN.
Note the highlighted IP address we assign to each node here. It will need to be incremented for each to provide a unique address. In addition I'm dropping in the primary network interface based on the default routing but if this isn't what you want replace the inline code with your preferred network interface.
NB: mypublickeycontents
should be the contents of the public key you generated on your home server so that the seedbox can authenticate it.
sudo -s # run the below commands as root
export HOME_PUBLIC_KEY=mypublickeycontents
sudo tee /etc/wireguard/wg0.conf <<EOF
# file: /etc/wireguard/wg0.conf
# Server configuration (we allow peers to connect into us)
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o $(ip -4 route | grep default | awk '{print $5}') -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o $(ip -4 route | grep default | awk '{print $5}') -j MASQUERADE
PrivateKey = $(cat /etc/wireguard/privatekey)
[Peer]
PublicKey = $HOME_PUBLIC_KEY
AllowedIPs = 10.10.0.2/32
EOF
exit # drop back to your user
Enable forwarding of packets in the host kernel for cloudbox.
sudo tee /etc/sysctl.conf << EOF
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
EOF
sudo sysctl -p
Finally we can start the wg0
interface.
wg-quick up wg0
Hopefully you'll see something like the below output.
feederbox# wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.10.0.1/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o enp3s0 -j MASQUERADE
Configure a ufw profile for it to allow through the firewall.
sudo tee /etc/ufw/applications.d/wireguard <<EOF
# file: /etc/ufw/applications.d/wireguard
# Used to configure the ufw definition for wireguard vpn server
[wireguard]
title=Wireguard VPN Server
description=WireGuard is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography
ports=51820
EOF
sudo ufw app update wireguard
sudo ufw allow wireguard
Now setup the client connection on our homeserver.
NB: theseedboxpublickeycontents
should be the contents of the public key you generated on your seedbox so that the peer can authenticate it.
sudo -s # run the below commands as root
export SEEDBOX_PUBLIC_KEY=theseedboxpublickeycontents
sudo tee /etc/wireguard/wg0.conf <<EOF
# file: /etc/wireguard/wg0.conf
# Client configuration (we connect to the seedbox)
[Interface]
Address = 10.10.0.2/24
PrivateKey = $(cat /etc/wireguard/privatekey)
[Peer]
PublicKey = $SEEDBOX_PUBLIC_KEY
AllowedIPs = 10.10.0.0/24
Endpoint = feederbox.yarr.wtf:51820
PersistentKeepalive = 25
EOF
exit # drop back to your user
Assuming we can ping from one to another via the 10.0.0.1/24 subnet then enable the service on both boxes.
sudo systemctl daemon-reload
sudo systemctl enable wg-quick@wg0.service
To avoid the overhead of rsync over ssh we'll use a rsync daemon that listens on the wireguard interface only (and so traffic is encyrpted over that tunnel).
On the seedbox (as your user, not root) run:
sudo tee /etc/rsyncd.conf <<EOF
# /etc/rsyncd.conf
# rsync daemon file listening on our VPN interface
# address (10.10.0.1) only. Designed to allow quick
# sync of data back from cloud to on-prem storage-server
# (dealt with by our `media-sync` systemd timer).
#
# Use `read only` to prevent mistaken deletion of content.
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsync.log
address = 10.10.0.1
[media]
# hosts allow = 10.0.0.0/24
# hosts deny = *
gid = $(id -g)
uid = $(id -u)
path = /mnt/local/Media
comment = Completed Media Downloads
read only = true
timeout = 300
EOF
sudo systemctl enable --now rsync
And add this to the firewall
sudo ufw allow in on wg0 to any port 873
To check this works run a query from the on-prem box.
$ rsync -rdt rsync://10.10.0.1:873
media Completed Media Downloads
We can now enable our media-sync systemd scripts on the on-prem box to automate the pull down of completed media back home.
It might be useful to have additional clients capable of tunnelling via the seedbox. E.g. some private trackers want you to have consistent IP addresses and you might want that security as well when browsing.
To setup a peer for your mobile/laptop etc. you need to:
- Create a public/private keypair
- Decide on the routing you want to have for your client
- Forward all traffic through the VPN (
AllowedIPs = 0.0.0.0/0, ::0/0
) - Route just traffic which is for my private subnets such as Home LAN and other VPN peers (
AllowedIPs = 10.10.0.0/24,192.168.0.1/24
)
- Forward all traffic through the VPN (
Whilst the iOS client will take care of the first part for you if wanted (creation of a keypair) you'll still need to fill out the following details.
-
Server file
- Add your client as a
[Peer]
block with aPublicKey
= generated by the client as per beforeAllowedIPs
= which source IPs can I expect from that peer? Note that this setting is different on the server (essentially acting as an ACL) versus client (where it controls routing).
- Add your client as a
-
Peer file / mobile client
- Create an
[Interface]
block (this is shown differently in the mobile client). I needed to add:Addresses
: 10.10.0.3/24DNS servers
: whatever you want (mine is 1.1.1.1 but could use an internal PiHole etc.)
- Add your seedbox as a
[Peer]
block with aPublicKey
= generated alreadyAllowedIPs
= decide on the routing approachEndpoint
= seedbox fqdn/ip and port- (Opt)
PersistentKeepAlive
= how often to poll in order to keep the connection up if we're behind NAT
- Create an
If you're mounting shares from home then install apt-get install -y nfs-common
and then add the necessary fstab entries / modify the mergerfs service.