# Public Home Server: Introducing and Resolving Issues

2025-02-16T00:00:00-08:00

As I have shared before, I have recently set up a server at home to run this website and web services like Mastodon, Gitea, Owncast, Miniflux, Linkding, and other great stuff. I decided to use Cloudron for simple server management, because I was struggling to get things up and running myself manually with package managers or compiling the software myself, or auto-magically using Docker, NixOS, etc. And I chose Cloudron over other similar services like YunoHost because I have used it before, it is quite stable, and does the thing it sets out to do well. The struggle with manually taking care of hosting issues came from long hours at work getting things set up and troubleshooting, and not having the energy in the evenings or weekends to get stuff set up and troubleshoot.

## Problem

This blog post isn’t a review of Cloudron though, instead I wanted to write down the solution to a weird issue I was having after I initially launched the server, which also took a somewhat embarrassing amount of time to fix. The issue was my website would not open in a web browser on my home computer after it went live, the browser would end the connection attempt with a timeout. I knew the website was up and live though, because I could open it from my phone connected to the cellular network. Tethering a laptop to my cell phone network and running `nmap 0x212.com` showed the domain name was resolving to my public IP, as well as the correct open ports for my server. Something was mis-configured on my local network.

My local network has two connected routers and three private VLANs. One of the VLANs is a DMZ between the public-facing and private-facing router, the private router drops all connection requests hitting the interface on that network. Port forwarding is enabled on the public router, so it sends all packets it receives from the internet to my Cloudron server that is also in the DMZ. The server is directly connected to the public-facing router.

## Troubleshoot

On my private local network, I could `ping` the public IP address and the private IP address of the server and all router gateways between, but I could not `ping 0x212.com`, indicating an issue with DNS. Yet, running `nslookup 0x212.com` showed correct name resolution, returning my public IP address. I am not running a private DNS server, so all DNS requests for my website were going out to a public DNS server. After checking and rechecking the router and server configurations, I started researching the issue online and learned that Network Address Translation requires loop-back to be enabled on the router for a web connection on the same IP address. But not all routers have that feature available, especially non-enterprise routers like my public facing router from AT&T (required for the fiber connection).

While I was researching the name resolution issue, a different but related issue came up. Like all good multi-taskers doing too much at one time, I was playing around with all the new toys I was installing on the server. Since I could connect to my website from the Internet, I just enabled a VPN connection with Mullvad to connect to my servers web services. But while connected to the VPN, I could not SSH into the local IP address for the server. This was necessary because I was needing to transfer files from my computer to the server, and I did not want to send that transfer across the internet. The Mullvad VPN client has a local network sharing setting that allows your computer to connect to other devices on the local network, but this setting will only apply to devices on the same local network as the computer.

## Possible Solutions

So fundamentally I wanted DNS requests to resolve my website’s domain to the server’s private IP address for my computer on my local network. The Cloudron server has an setting that dynamically updates DNS records using the APIs for various DNS registrars, which can be configured to the public or private IP address for the server. Mine is configured for the public IP address. I started thinking of different ways to resolve my issues, such as the following:

- Disable Cloudron’s dynamic DNS and pay for a public dynamic DNS service like No-IP. The server could be configured to accept all requests hitting the interface.
- Replace the public router with one that supports NAT loop-back, which is expensive and AT&T requires their fiber router.
- Move Cloudron from baremetal to a virtual machine in Proxmox or something similar, which could also run a virtual DNS server for local name resolution.

I probably should have installed Cloudron in a virtual machine and I may at some point, but that will be a later project and write-up. I do have another server running Proxmox, but I since I have one server running 24/7-ish, I was trying to reduce how often I am running other computers to reduce my electric bill carbon footprint. So I spent some time mulling over this silly little issue, considering how much time and money various solutions cost, and then in a moment of clarity after reading a post in a Mullvad support forum, I realized a simple, practical, and cheap solution for everything.

## Simple Solution

The Mullvad client will respect static routes configured on the machine. So running `ip route add $SECOND_VLAN via $GATEWAY via $INTERFACE` on my computer allowed me to connect to the private IP address for the server while connected to Mullvad’s VPN. With the static route configured, I added `$SERVER_PRIVATE_IP 0x212.com` to `/etc/hosts` to my computer. Now the 0x212.com domain resolves to the server’s private IP address for my computer, while still using public DNS servers for everything else. I felt like this was a simple solution that I should’ve realized sooner, but I got caught up considering more complicated, enterprise-grade solutions.

I’m probably will move Cloudron to a virtual machine and setup a private firewall and DNS server, but I don’t need to at this time and can focus on other fun things like updating my website and writing blog posts.