Time for a massive info dump.

Hotline is dated, and that complicates things as servers are very public. It was designed in a very different era of the internet. Hosting a server means exposing an IP. This isn't a huge deal, but I wanted to be able to host my files on my NAS without exposing said NAS to the internet. This is where a VPS comes in. The Mobius binary is happy on a small VPS, but storage costs money, and besides, I already have a Raspberry Pi 4 on a VLAN with my NAS as my data warehouse. The issue is I need to connect my VPS to my Raspberry Pi, which has limited access to NAS.

The trick: WireGuard stitches the two together, SSHFS mounts the Pi storage onto the VPS, and Mobius thinks everything is local. Trackers see the VPS IP, my LAN stays closed, and if the VPS dies, I can swap in a new one without touching the files, as the configuration lives on my home network. It's incredible how useful AI is when it comes to a project like this, as AI pretty much stepped me through setting up Wireguard and SSHFS.

My original plan was to use Cloudflare tunnels, as you get all the benefits of Cloudflare, and I could have skipped the VPS and hosted the server on my Raspberry Pi, but Hotline requires multiple TCP ports, which makes the tunneling more or less impossible unless you throw a lot of money at the problem. I'm not paying $10k a year to host a hotline server. But I am willing to pay $10 a year. That's where the VPS comes into play.

What this setup does

Time for the bullet points:

  • Public address like hotline.example.com:5500/5501.
  • All Mobius config, users, and files live on a Raspberry Pi at home.
  • VPS is only the front door; it reaches the Pi over WireGuard.
  • Mobius on the VPS reads/writes through an SSHFS mount.

Result: clients and trackers only see the VPS IP, while the Pi keeps the actual data tucked away on its own VLAN. For the remainder of these instructions, I'm going to skip the VLAN setup details as it's noise that doesn't matter for this guide. You can always add your own VLAN if you want. Also, to avoid over-complicating something that's already complicated, I'm writing the instructions as if you have an external HDD connected to your Pi.

1. High-level architecture

VPS: Ubuntu (I used 24.04) running Mobius, I found that CloudServer.net charged all of $10 a year for a tiny VPS (1 Core, a few gigs of RAM, 10 GB of storage)
Domain Name: I use Cloudflare to manage my DNS, but it doesn't matter who you use, though. You can find my server at Hotline.semihosted.xyz, it points to my VPS.
File Server: This is really up to you. I use a Raspberry Pi 4 with Raspberry Pi OS and have mounted my Synology NAS. My Raspberry Pi is on a VLAN, thus safer to expose it than my NAS itself.

2. WireGuard: connect VPS ↔ Pi

First, we need to set up WireGuard so the VPS and Pi can see each other on a private subnet. You'll need to SSH into both machines.

2.1 Install WireGuard

On the VPS:

sudo apt-get update
sudo apt-get install -y wireguard

On the Pi:

sudo apt-get update
sudo apt-get install -y wireguard

2.2 Generate keys

We need a public/private key pair for both the VPS and the Pi to make Wireguard work.

On the VPS:

sudo umask 077
sudo wg genkey | sudo tee /etc/wireguard/server.key | sudo wg pubkey > /etc/wireguard/server.pub

echo "SERVER PRIVATE:"
sudo cat /etc/wireguard/server.key
echo "SERVER PUBLIC:"
sudo cat /etc/wireguard/server.pub

On the Pi:

sudo umask 077
sudo wg genkey | sudo tee /etc/wireguard/pi.key | sudo wg pubkey > /etc/wireguard/pi.pub

echo "PI PRIVATE:"
sudo cat /etc/wireguard/pi.key
echo "PI PUBLIC:"
sudo cat /etc/wireguard/pi.pub

Keep these four values handy: SERVER_PRIVATE, SERVER_PUBLIC, PI_PRIVATE, PI_PUBLIC.

2.3 Configure VPS

Now it's time to configure WireGuard on our VPS.

Create /etc/wireguard/wg0.conf:

[Interface]
Address = 10.44.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE

# NAT traffic from the tunnel out via VPS NIC
PostUp   = iptables -t nat -A POSTROUTING -s 10.44.0.0/24 -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.44.0.0/24 -o eth0 -j MASQUERADE

[Peer]
PublicKey = PI_PUBLIC
AllowedIPs = 10.44.0.2/32, 192.168.1.0/24

Swap in your keys and LAN subnet. Then allow forwarding:

echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-ip-forward.conf
sudo sysctl --system

2.4 Configure Wirguard on the Pi

Create /etc/wireguard/wg0.conf:

[Interface]
Address = 10.44.0.2/24
PrivateKey = PI_PRIVATE
ListenPort = 45519

[Peer]
PublicKey = SERVER_PUBLIC
Endpoint = VPS_PUBLIC_IP:51820
AllowedIPs = 10.44.0.0/24
PersistentKeepalive = 25

Replace the keys and VPS IP. Optional but handy if you ever route more:

echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-ip-forward.conf
sudo sysctl --system

2.5 Bring the tunnel up

Time to stich the two together by turning the tunnel on.

On the VPS:

sudo systemctl enable --now wg-quick@wg0
sudo wg show

On the Pi:

sudo systemctl enable --now wg-quick@wg0
sudo wg show

From VPS, confirm both the tunnel and LAN reach the Pi:

ping -c 3 10.44.0.2
ping -c 3 PI_LAN_IP   # e.g. 192.168.1.50 

3. Prepare Mobius config on the Pi

3.1 Pick a storage spot

On the Pi, pick a spot for Mobius config and files. For this example, I'm using an external drive /mnt/storage/mobius-config. This could be entirely hosted on the Pi's intenral drive or an external NAS.

sudo mkdir -p /mnt/storage/mobius-config
sudo chown -R $USER:$USER /mnt/storage
# or sudo chown -R piuser:piuser /mnt/storage

3.2 Download and init Mobius (ARM)

We are not going to run Mobius on the Pi, just use it for storage. However, we want all the configuration files that come with Mobius. You can copy between the two machines but I was lazy and found this to be easier.

mkdir -p ~/mobius
cd ~/mobius

curl -L https://github.com/jhalter/mobius/releases/download/v0.20.1/mobius_server_Linux_arm64.tar.gz -o mobius_server_Linux_arm64.tar.gz

tar xzf mobius_server_Linux_arm64.tar.gz
chmod +x mobius-hotline-server  # adjust if the binary name differs

./mobius-hotline-server -init -config /mnt/storage/mobius-config

You should now see Agreement.txt, config.yaml, Users/, Files/, etc. on the Pi’s storage. This is your Mobius configuration and data directory, aka where your files live.

4. SSH key auth from VPS → Pi

To make SSHFS work without a password prompt, we need to set up SSH key authentication from the VPS to the Pi. This is necessary so we can automatically connect to our Mobius storage on the Pi.

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -C "vps-to-pi"
ssh-copy-id -i ~/.ssh/id_ed25519.pub piuser@10.44.0.2
ssh piuser@10.44.0.2

Replace piuser with your actual user. If login works without a password, you are set for sshfs.

5. Mount the Pi's Mobius config on the VPS via SSHFS

Now the moment of truth: mount the Mobius config directory from the Pi onto the VPS using SSHFS.

sudo apt-get update
sudo apt-get install -y sshfs

sudo mkdir -p /mnt/mobius-config
sudo sshfs -o IdentityFile=/root/.ssh/id_ed25519,StrictHostKeyChecking=accept-new \
 piuser@10.44.0.2:/mnt/storage/mobius-config /mnt/mobius-config

ls -la /mnt/mobius-config

If you see config.yaml and friends, the mount worked. You can formalize this with systemd or /etc/fstab later.

6. Install Mobius on the VPS

Finally, we install Mobius on the VPS itself. This is where the server will run.

cd /opt
sudo mkdir -p /opt/mobius
sudo chown root:root /opt/mobius
cd /opt/mobius

curl -L https://github.com/jhalter/mobius/releases/download/v0.20.1/mobius_server_Linux_x86_64.tar.gz -o mobius_server_Linux_x86_64.tar.gz

tar xzf mobius_server_Linux_x86_64.tar.gz
chmod +x mobius-hotline-server  # adjust binary name if needed

./mobius-hotline-server --help

7. systemd unit on the VPS

Almost done, now we need to create a systemd unit to run Mobius as a service on the VPS. Systemd will manage starting, stopping, and restarting Mobius as needed.

Create /etc/systemd/system/mobius.service:

[Unit]
Description=Mobius Hotline Server (VPS using Pi storage via SSHFS)
After=network.target
After=wg-quick@wg0.service

[Service]
Type=simple
WorkingDirectory=/opt/mobius
ExecStart=/opt/mobius/mobius-hotline-server -config /mnt/mobius-config
Restart=on-failure

[Install]
WantedBy=multi-user.target

Reload and start:

sudo systemctl daemon-reload
sudo systemctl enable mobius
sudo systemctl start mobius
sudo systemctl status mobius --no-pager -n 20

8. Verify Hotline ports

sudo ss -tlnp | grep 550

You should see listeners on 5500 and 5501. From outside, test:

nc -vz -w 3 hotline.example.com 5500
nc -vz -w 3 hotline.example.com 5501

Watch logs as clients connect:

sudo journalctl -u mobius --no-pager -n 50

9. Configure trackers and metadata

Edit /mnt/storage/mobius-config/config.yaml (from the Pi or via the VPS mount):

server:
 name: "The Apple Media Archive by DMG"
 description: "A Hotline server filled with Apple events and commercials from the 80s to today."
 banner: "banner.jpg"
 messageBoard: "MessageBoard.txt"

tracker:
 enabled: true
 servers:
 - "hltracker.com:5499"
 - "tracker.preterhuman.net:5499"
 - "saddle.dyndns.org:5499"
 - "hotline.kicks-ass.net:5499"

Restart to apply changes:

sudo systemctl restart mobius

10. Optional: helper script for pushing new Mobius builds to the Pi

If you ever run Mobius directly on the Pi, a quick-update script helps:

#!/usr/bin/env bash
set -euo pipefail

MOBIUS_SRC="/home/piuser/Desktop/mobius-server-linux-arm64"
MOBIUS_DST="/opt/mobius/mobius-hotline-server"

echo "Stopping Mobius..."
sudo systemctl stop mobius || true

echo "Updating binary..."
sudo cp "$MOBIUS_SRC" "$MOBIUS_DST"
sudo chmod 755 "$MOBIUS_DST"

echo "Starting Mobius..."
sudo systemctl start mobius
sudo systemctl status mobius --no-pager -n 10

Make it executable: chmod +x ~/update-mobius.sh. Run it when you drop in a new build.

Wrap-up

I know that was quite a bit, but that's how you can host Mobius (Hotline server) on a VPS and have it SSH tunnel back to your home network for file storage and not expose your home network to the internet.

  • WireGuard links the VPS and Pi on a private subnet.
  • The Pi holds config and files on roomy storage.
  • SSHFS makes that storage feel local on the VPS.
  • Mobius runs on the VPS, shows the VPS IP to the world, and keeps your home network dark.

If the VPS gets nuked, you can rebuild it, remount the Pi, and be back on the Hotline trackers in minutes.