Hosting From Home
If you’ve flirted with the idea of running a server in your house, you’ve probably stumbled across services like Ngrok that let you, with a single command, get an HTTPs URL that connects to something on your local machine.
The idea is simple – someone accesses the URL, hits Ngrok’s servers, and is then routed to your computer on your home network.
While this is useful, and while there are plenty of tools that help build tunnels, we can build this ourselves, and easily host a website (or service, or anything really), using our own tunnel, built on Wireguard! And we can setup HTTPs too!
Who Is This For (and Who It Isn’t)
Before we get too far into this, I want to stress this is a niche setup. Serving something on the public internet from your house means you meet both of these criteria:
-
You have complex/unusual hosting needs
-
You want to share something with a large, public audience
Let’s take each of these one at a time.
If you just want to host a website there’s usually no reason to host it from your house. Your home internet’s upload speed will pale in comparison to any datacenter, and any time something happens to your home internet (power outage, someone else sucks up the bandwidth with a zoom call, etc), your website will suffer.
If you just want to put something online, there are some excellent (and inexpensive) website providers. If your website is static (like this one), Netlify, Github Pages, Cloudflare Pages, Vercel, and Surge are all excellent options, that will be cheaper (often free) and faster than what we’re discussing here. Even if you need more than just static files, there are plenty of providers that will give you anything from basic virtual machines (Linode, Digital Ocean) to fully managed websites (Squarespace, Wordpress, Wix, etc). This will probably be cheaper and cause less stress then running it out of your house.
But there are cases where that doesn’t make sense – where having your website on your local home network is a good idea. Maybe you’re setting up Nextcloud, and you want to have access to the existing mountain of data you already have on your NAS (and paying for extra storage from a cloud provider would be expensive). Or maybe you’re making some shiny public dashboard of all your smart home sensors you want to show off.
Or maybe you’re doing it for learning – maybe you want to setup a cluster of Raspberry Pis and expose them to the world for testing. That’s fine too!
That said, this setup only makes sense if you are making your website (or service, or whatever) available to the general public. If you just want to make your Plex server available on the go, or you want to make a chat server for you and a few friends, there’s a better solution:
In this model, we don’t need to pay for a VM, and it’s far more secure. Because all the services are behind Wireguard, even if there’s some vulnerability in Plex, even if your partner uses the same password for everything, it doesn’t matter, because to touch any service, you must go through Wireguard. It’s an easy, safe way to expose services from your house (it’s how I use my PiHole ad blocker, even when on mobile).
If you have an unusual internet setup (such as fixed wireless or satellite) and/or can’t have inbound ports, we can still use a VM as an entry point (as we’re doing in this article), and still place everything behind Wireguard (you would just connect to your VM over Wireguard instead of open HTTPs).
But, before we proceed, we need to make something clear: we’re discussing making something available to the entire internet. Again, there are cases where this makes sense (showing off a demo to someone before you tear it down, hosting NextCloud for a larger group, etc), but just remember: you’re connecting the public internet to a thing running on your home network. If someone breaks in, they’ll be inside your home network. While there are ways to mitigate this risk (VLANs), this isn’t optimal. Keep this in mind as you proceed!
Why a Tunnel?
You may have noticed in the previous section that one of the diagrams had people just connecting to your house directly. Why are we bothering with a tunnel and paying for a public VM?
Well, there are a couple of reasons for this. The first is safety – if you host a website directly from your home network, so that when people type in the address bar they are connect to your home IP address, people will know your home IP address. Which means they’ll know where you live (or at least the township). They’ll also be able to potentially unleash attacks on your home internet connection that aren’t otherwise possible.
Second, hosting HTTPs services at home can be tricky. A lot of residential ISPs block the ports used for normal inbound web traffic.
We are side-stepping both of these issues with using a Wireguard tunnel. The only IP address people see will be the one of the public VM in some datacenter (avoiding the privacy issues), and the connection into our house will flow through Wireguard (bypassing any ISP port blocks).
Getting Ready
To make this work, you’ll need a few things:
-
A virtual machine from some cloud provider (I’m partial to DigitalOcean, but any provider will do)
-
Note: You don’t need a machine with a lot of power or RAM – the $5/mo option on Digital Ocean works fine.
-
Be aware of bandwidth – if you’re hosting NextCloud and you’re going to be moving large files, you should check how your provider bills for ingress and egress!
-
-
Something on your home network where you’re going to host this new website (a raspberry pi works well here)
-
A domain name (while not technically required for hosting, we’ll need it to get a free SSL cert). If you’re just trying this out, you can grab a free domain from freenom, or use a free dynamic dns provider like DuckDNS.
To keep this article focused (and not longer than it already is), I’m going to assume both the virtual machine and the pi (or whatever your home server is) are already up and running and secured (this means you’ve setup unattended-upgrades on both of them to keep them updated, right?), and you have a DNS record pointing to your public virtual machine.
I’ll also assume you already have a web service running on your home machine that you want to share with the outside world. You should test this before getting started!
We’ll start by setting up Wireguard to connect the public and private machines together, then we’ll setup Caddy on the public virtual machines to automatically give us SSL certificates and to forward connections to the private machine!
Note: I’m using Ubuntu 20.04 on both machines, but these instructions should be mostly distro agnostic.
Setting Up Wireguard
Installing Wireguard, especially on Ubuntu, is pretty straightforward:
sudo apt install wireguard
And we’re done. Do this on both the client and server, and now we just need to configure everything.
Configuring the wireguard server (the public vm)
Once wireguard is installed, we have two tasks – to make the configuration, and to open up the firewall.
To start, let’s make public and private keys for both the private and public machines. You can do this on any machine.
wg genkey | tee server_prikey | wg pubkey > server_pubkey
wg genkey | tee client_prikey | wg pubkey > client_pubkey
You now have four files – a client public and private key, and a server public and private key. We’re going to copy paste these values in into our config files, and then delete them when done.
The configuration for our public vm (our server) is straightforward. I’m using the 192.168.201.0/24 subnet for our wireguard network, but feel free to use any private network of your choosing. In this setup, our public VM will have it’s wireguard interface set to 192.168.201.1, and our private system will be 192.168.201.2.
Write a file at /etc/wireguard/wg0.conf as root with the content:
[Interface]
Address = 192.168.201.1/24
PrivateKey = [contents of server_prikey]
ListenPort = 51830
[Peer]
AllowedIPs = 192.168.201.2/32
PublicKey = [contents of client pubkey]
And that’s it. We can enable this interface to be brought up at start by
running systemctl enable --now wg-quick@wg0
We now just need to open a firewall port for Wireguard. Assuming you’re
using ufw (which seems to be the preferred firewall for Ubuntu), you can
open a port with sudo ufw allow 51830/udp
.
And you now should be set on the server (at least for the Wireguard part). Let’s setup the client.
Configuring the Wireguard Client (the private machine)
A Note About Firewalls: I’m assuming the Raspberry Pi running on your local network does not have any firewall running on it. If it does, you’ll need to setup rules to allow inbound traffic from the Wireguard interface.
Just like we did on our server, create a client configuration at /etc/wireguard/wg0.conf:
[Interface]
Address = 192.168.201.2/24
PrivateKey = [contents of client_prikey]
[Peer]
Endpoint = [yourdomain.com]:[wireguard port]
PublicKey = [contents of server_pubkey]
AllowedIPs = 192.168.201.1/32
PersistentKeepalive = 25
Bring up the interface and set it to start on boot with systemctl enable --now wg-quick@wg0
.
You should now be able to ping the server (assuming it accepts pings) with ping 192.168.201.1 from the client, and you can ping the client with ping 192.168.201.2 from the server.
You can now delete your previously created key files!
We now have our encrypted tunnel! Great! Now we just need to setup HTTPs and our reverse proxy!
Setting Up Caddy
While nothing is stopping you from using another webserver, I’m using caddy in this tutorial because it’s easy to configure, and because it handles HTTPs certificates automatically.
Installing Caddy requires adding new package source on Ubuntu, but the process is straightforward and well documented on Caddy’s website.
Once caddy is installed, the configuration is dead easy. Write the following to /etc/caddy/Caddyfile:
yourdomain.com {
reverse_proxy 192.168.201.2:[port where your server is running on the pi]
}
You also might have to open up HTTP and HTTPs ports. Go ahead and run:
sudo ufw allow 80/tcp
sudo ufw allow 443/udp
And that’s it. Restart caddy with systemctl enable --now caddy
. And
you’re done. After a few seconds, you’ll be able to go to
https://yourdomain.com, and you’ll see whatever’s being served by the
Pi! Caddy is handling getting an SSL cert for us automatically, so
there’s nothing else to do!
Final Notes
As I said, this is a niche use. There’s plenty of times you might want to make a website on your local machine public, just for a little while, to show a friend. Having the ability to use a VM (that you may already have) and turn it into your own tunnel provider gives you options!
Though they’re options you should review and make sure that they make sense for you!