How I set up my homeserver
Note: unfinished
Last year I suddenly developed the urge to familiarize myself with servers and the web. What exactly got me crazy enough to dive into that world, I do not know, but at the time I was enjoying programming a lot and I wanted to take it to the next level.
Probably, if you want to dabble with a server, it is best to buy a cheap VPS from a nearby hosting provider. However, I wanted some actual computing power and I was not happy with the subscriptions I could find online. Furthermore, I wanted to customize not just the software, but the hardware too.
So I bought a bunch of components and built my own computer. Nothing fancy, but quite decent and with an integrated graphics card for convenience. I’d recommend getting something with lower power consumption, for the rest it shouldn’t really matter. Thankfully, a friend who is quite knowledgeable about servers and networking recommended me to install Proxmox. Proxmox is an operating system (built on top of Debian Linux) that allows you to manage large numbers of ‘virtual machines’ (VMs), which act like completely independent computers. Furthermore, they are fully isolated from the ‘host’ (the main operating system), providing strong security.
By assigning only a few tasks to each VM, you can tailor their environment for their needs. In this post, I want to document my experience setting up a home server, including my own authentication system and website. The reason I’m writing this now is because I finally figured out how to set up a system to connect to the server from outside my local network, so the basic infrastructure is complete.
Configuring your PVE host
With ‘PVE host’ I mean the main operating system running Proxmox VE, i.e. your physical computer. For enhanced security, I encrypted my installation. You can do this by first installing Debian with a standard encryption scheme and then installing Proxmox on top of it. However, you can also just install Proxmox directly.
The big downside to encryption is that you will have to enter your encryption key manually (i.e. you’ll have to physically plug in a monitor to your server) each time it restarts. Other than that it works great.
The main issue I encountered in this step was that my internet just would not work. It was probably caused by me installing ifupdown2
, resetting the configuration (this is a known bug with ifupdown versions before 0.8.35+pve1). You will be able to access your PVE host through an IP address given out by the computer (something like https://192.168.178.58:8006). This can only be done from your local network (i.e. the same network that your computer is on), but we will be able to remedy this later.
To get internet working for your VMs, you need some sort of networking setup, see this Proxmox guide. I have my VMs connected using a “Bridge”, set up as follows (this might be different from the default configuration, as I had some issues):
auto lo
iface lo inet loopback
iface eno1 inet manual
auto vmbr0
iface vmbr0 inet dhcp
bridge ports eno1
bridge stp off
bridge fd 0
I’m not an expert on this and don’t know what half of this means, this document is mostly just for documenting my own process. Note that enp3s0
is the main network interface and its name will differ from system to system. This bridge gives each VM its own IP address and allows them to behave basically as if they were each connected with their own ethernet cable.
From the web interface, you can easily create and remove virtual machines. I’ve mostly been using Ubuntu 20.04 VMs. One downside of using multiple VMs is that they are full operating systems with their own running kernel, meaning they can eat up quite a bit of memory. I’d recommend installing at least 16 GB (but 32 GB wouldn’t be bad either) on your computer and configure plenty of swap space.
Setting up a local web server
There’s a multitude of ways to set up a web server. We’ll be using a Docker container (specifically, tiauth v0.1.1). We’ll also deploy it using the accompanying deployment script. First, install Docker and Docker Compose V2.
Setting up a proxy VM
I use one VM as a proxy that manages incoming connections. This means I only have to port forward for that particular machine. Since we will be setting up web servers later, we want to port forward ports 80 and 443 for the IP address of the proxy VM (TCP protocol). We also want to forward some other port (e.g. 51820) for the UDP protocol, again for the same IP address. We will use this port for setting up a VPN.
VPN to your home network
You probably want to also manage your server when you’re not at home. Unfortunately, your computer will not be accessible from the internet. Of course, you could port forward whatever port you are using for SSH and manage your VMs directly that way, but this opens up your VMs to attacks.
For this reason I’d recommend setting up a private VPN to access your home network. I’ve used WireGuard for this purpose, as it is fast, secure and easy to set up for this particular use case.
First, make sure WireGuard is installed on your VM (i.e. by running sudo apt install wireguard
). If it is not already there, create a file called wg0.conf
in /etc/wireguard/
. I have the following configuration:
[Interface]
Address = 10.0.0.1/24, fd86:ea04:1115::1/64
PrivateKey = <YOUR PRIVATE KEY HERE>
ListenPort = 51820
DNS = 1.1.1.1
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -j MASQUERADE
The Address
option does not really matter as long as it does not interfere with your local subnet (so don’t use something like 192.168.xxx.xx). As such, any random (but valid) address should work. For the server, I recommend using the /24 and /64 subnet masks, as this can ease configuration with many peers, but using /32 and /128 (which mean just a single IP address and not a wider mask) should work just find.
You can generate a private key using wg genkey > privatekey
(which you can then read using cat private
), which you should put as the PrivateKey option above. Be sure to derive a public key as well (wg pubkey < privatekey > publickey
), which you will need to later access the server.
ListenPort should correspond to the port you forwarded earlier. The PostUp and PostDown options will make sure that you can connect to all IP addresses that the server can access, i.e. the other VMs on your PVE host’s local network.
Next you have to generate a private key and public key for your client. Once you have done this, add a peer to the configuration, as follows:
[Peer]
PublicKey = <CLIENT PUBLIC KEY>
AllowedIPs = 10.0.0.2/32, fd86:ea04:1115::2/128
PersistentKeepalive = 25
After setting WireGuard to start and always run on boot (sudo systemctl enable wg-quick@wg0
), you are done on the server-side. Now install WireGuard on your client machine and configure it as follows:
[Interface]
PrivateKey = <CLIENT PRIVATE KEY>
Address = 10.0.0.2/32, fd86:ea04:1115::2/128
[Peer]
PublicKey = <SERVER PUBLIC KEY>
AllowedIPs = 192.168.178.0/24
Endpoint = <SEVER PUBLIC IP ADDRESS>:<SERVER LISTENPORT>
PersistentKeepalive = 25
Here allowed IPs should correspond to the IP range of your VMs, this can vary from network to network. You also need to find your server’s public IP address, which is usually set by your ISP and can be found online. The port should correspond to the ListenPort you configured before.
Now you should be able to connect to the web UI remotely!