My Homelabbing Journey

April 15, 2026

This is a chronological log of my experience with setting up a personal home server on a Linux Mint Laptop (Acer ES1-132) on a campus network (IISER TVM), known for its heavy restrictions (Sophos firewalls, captive portals, subnets).

This blog documents what I tried, what worked, and what failed.

Phase 0: Initial Setup

Goal: Turn a crappy Linux Mint laptop into a basic home server.

I started with Ubuntu, but that had a lot of issues (that I don't even want to talk about), then installed a clean distro of Linux Mint. Why Mint? It is optimized for performance, and my laptop has a sum total of 4 GB of RAM.

What I Did:


Phase 1: The Minecraft Server

Goal: Host a legit Minecraft server locally. This was my first exposure to running long-lived processes and server configuration.

Java Setup:

I needed Java 21. I ran into a few errors while installing it, but got it fixed. Those errors I deem detrimental to a blog such as this, so we move.

Bash

sudo apt update
sudo apt install openjdk-21-jdk

Server Execution:

  1. Created mkdir ~/mcserver and grabbed the server jar via wget (specific version links can be found on Mojang's site).

  2. Ran it the first time: java -Xmx2G -Xms2G -jar server.jar nogui.

  3. Crashed because of the EULA. Opened nano eula.txt, changed eula=false to eula=true, and fired it up again.

  4. Success! My friends and I could join using <ip-address>:25565, but only within the exact same WiFi network. No remote access yet. Later experimented with a Modded Server using the Fabric Server Loader (which requires matching client-side mods).


Phase 2: Download Tools

Goal: Download media files efficiently onto the server.

Attempt 1: aria2c (CLI)

I tried using aria2c as a CLI torrent downloader. Massive headache.

The Fix: qBittorrent-nox

This is a web-version of qBittorrent that you can access via a web UI from anywhere using the server's IP.

Bash

sudo apt install qbittorrent-nox

If you just run qbittorrent-nox, it keeps the program trapped in your open SSH terminal. To avoid this, I ran it as a daemon instance:

Bash

qbittorrent-nox -d

Downloads worked reliably, peer discovery was automatic, and pointing the download directories to ~/Jellyfin/TV and ~/Jellyfin/Films was a breeze after I re-fixed folder permissions with chmod -R 775.


Phase 3: Plex (Failed Attempt)

Goal: Set up a mainstream media server.


Phase 4: Jellyfin (Major Success)

Goal: A completely local, restriction-free media server to completely replace Plex.

Bash

sudo apt install jellyfin
sudo systemctl enable --now jellyfin

I opened up http://<server-ip>:8096 in my browser, skipped the metadata options initially to keep things fast, and linked my ~/Jellyfin/Films and ~/Jellyfin/TV folders.

It scanned and detected everything automatically. I tested it on my phone using the iOS app Streamyfin via the local IP—playback worked flawlessly. No external accounts needed, clean UI, and highly reliable local streaming.


Phase 5: Networking Problems Begin

The Reality Check: The campus network is actively hostile to homelabs.

The Obstacles:


Phase 6: SSH Tunneling

Goal: Remotely access the campus login portal through the server.

I tried using SSH local port forwarding to bridge the gap:

Bash

ssh -L 8090:gateway.iisertvm.ac.in:8090 akwastaken@<server-ip>

Phase 7: VPN Setup (sshvpn)

Goal: Use the official campus VPN to bypass the captive portal altogether.

I grabbed the .ovpn file from the campus VPN portal, installed OpenVPN, and set up a credentials file (creds.txt) containing my username and password inside /etc/sshvpn/.

Automation via systemd:

Running it manually blocks the terminal, so I wrapped it into a systemd service (/etc/systemd/system/sshvpn.service):

Ini, TOML

[Unit]
Description=OpenVPN SSH VPN
After=network.target

[Service]
ExecStart=/usr/sbin/openvpn --config /etc/sshvpn/config.ovpn --auth-user-pass /etc/sshvpn/creds.txt
Restart=always
User=root

[Install]
WantedBy=multi-user.target

I then built a custom bash wrapper script named sshvpn and threw it into /usr/local/bin/ so I could manage the connection globally using simple commands like sshvpn startsshvpn stop, and sshvpn update <path-to-ovpn>.


Phase 8: Tailscale (Breakthrough)

Goal: Stable remote access from anywhere without dealing with local IPs, subnets, or port forwarding.

Bash

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

Phase 9: VPN vs. Tailscale Conflict

The Nightmare: OpenVPN and Tailscale absolutely hate sharing the same routing table.

When the campus VPN starts, it forces a global routing split:

Plaintext

0.0.0.0/1 via <vpn-gateway> dev tun0
128.0.0.0/1 via <vpn-gateway> dev tun0

This forces all internet traffic through tun0. Because the VPN overrides local routing, Tailscale's traffic gets sucked into the VPN tunnel, clashes with the Sophos firewall on the other end, and causes Tailscale to report as offline.

Failed Fixes:

  1. Manual Route Overrides: I tried running sudo ip route add 100.64.0.0/10 via <local-gateway> to force Tailscale outside the VPN. It was highly unstable and broke constantly.

  2. Split Tunneling: Trying to modify the campus VPN behavior to not route everything failed because the raw campus network just goes back to blocking Tailscale.

Key Insight:

There are only two stable modes here:

  1. Tailscale without VPN (Works only outside campus network restrictions).

  2. Tailscale inside VPN (Works because traffic is tunneled, but manual routing overrides are fragile and easily broken).

Phase 10: vpnbox (Per-App VPN - DOESN'T WORK)

Goal: Use Linux network namespaces to isolate the VPN traffic.

I wanted qBittorrent to route strictly through the campus VPN, while keeping the rest of the OS on the normal network so Tailscale wouldn't break.

The Execution:

The Failure:

It completely isolated the traffic, but it worked too well. Because qBittorrent was locked entirely inside the isolated vpnbox namespace, I couldn't access its Web UI from the outside network. It is permanently stuck inside the box. Back to the drawing board.

Phase 11: Dashboard!

Goal: Build a clean homelab dashboard to track everything.

I saw a YouTube video of someone vibe-coding a gorgeous homelab dashboard. I wanted to avoid using AI as much as possible, so I found an open-source project called Flame.

The Setup:

I spun up Docker, pulled the Flame container image, and deployed it.

Observation:

Flame is incredibly minimalistic, but honestly, I want something that gives me actual real-time system information and metrics at a glance. Flame is a bit too barebones for my taste, so I am planning to scrap it and switch to the Homepage dashboard next.