It’s almost 2024 and I’m trying out a new blogging setup. Instead of making a blog post about my custom made blog engine (and never blogging again), I’ve decided to go with Quartz & Obsidian for my setup instead. So I’ll test things out by talking about my self hosting setup.

Now, I won’t really talk much about why you should self-host, there are tons of answers to this question from various perspectives.

My Setup

The hardware

  • Asus G14 (2021) (Some distro, I hop).
  • A minisforum mini pc with Ryzen 7 (Ubuntu Server)
  • A cuddy wired router since my university has a firewall which means my devices cannot form a p2p connection over tailscale. A router solves that and I avoid DERP

The Software

  • Tailscale: Pretty much a must-have for me. I have heard good things about Cloudflare Tunnel too but I stuck with TS. I could figure out WireGuard myself but I didn’t want to deal with firewalls, NAT, University WiFi and securing it. Tailscale just works.
  • Caddy: One reverse proxy for each service, running on https://{service}.example.com (Yes, https with tailscale (not ts.net), here’s how, and why I did that)
  • Docker, nix: Most of my services are simple docker containers of open source projects, my own apps usually are minimal docker images built with nix. I also create my own images with docker as I serve everything on a Unix Domain Socket. (More on that below)

I want to confess that this is not a 100% self hosted solution 😔. I also run a VPS on Oracle’s generous free tier for some redundancy. I use Backblaze for important backups (encrypted with duplicati). I try to minimize this however.

The Services

  • AdGuardHome: I run 2 instances of this and sync them using AdGuardHome-sync. Both the machines have a Tailscale IP which I use as my DNS servers on my Tailscale console.
  • Immich: Might be a must have for future self host setups, the project moves fast and it’s got an amazing team. (Consider sponsoring them!). I also back these up using Duplicati.
  • NTOP: Network monitoring, making sure the traffic doesn’t look too crazy.
  • Picoshare: Tailscale file exists, but sometimes you want a url.
  • Tailscale Golink: neat URL shortner.
  • Tailscale Tclip: Private pastebin. A little slow IME, maybe I’m holding it wrong?
  • Journo: An end to end encrypted journaling app I made in the past, Self hosted it because..why not.
  • Piped: A private YouTube front-end. Another great community project. I built a custom image for it to use a single container. (I don’t really care for scalability for 2 - 3 users as this instance is private to my tailnet)
  • Transmission-openvpn: A torrent client for Linux ISOs only. (Running on the cloud machine, not locally)
  • Jellyfin: Browsing my Linux ISO collection.
  • CouchDB for Obsidian Self-hosted LiveSync: Free Obsidian Sync alternative.
  • S3FS Fuse: Fuse FS, a caddy server and a backblaze bucket that let’s me use it as a remote file system. On my phone the files get synced using foldersync. Convenient for documents.
  • Glances: HTOP over the web.
  • Ollama Web UI: Running popular llms locally for fun.
  • Reader: A dead simple project of mine that let’s you open read/https://some-news-article and shows it in a clean reader node interface.
  • Gitea: self hosted GitHub alternative. Currently using it as a mirror but slowly moving projects over completely.
  • Sterling PDF: PDF manipulation.
  • Metube: youtube-dl client

Why I build my Custom Images

For most of the projects above, I create a docker image on top of them that makes them serve content over a unix domain socket over a docker volume. My main caddy server would then reverse proxy service.example.com to that unix socket.

I do this because Docker actually modifies your iptables to let any service with a port mapping of say 3000:3000 be available on ALL interfaces (0.0.0.0). This is not a problem over a firewalled network but if I’m not under a firewall, all these services are available over the Internet. Read on: The Perils of docker run -p

You could specify the interface yourself: ( 127.0.0.1:3000:3000 OR {tailscale-ip}:3000:3000 ) or you could update UFW rules to cover docker as well. I simply avoid the issue of forgetting to do this by serving things over UDS. The Caddy server, which sits behind UFW (deny everything coming IN, allow everything going OUT) then serves all this and Tailscale handles the rest. Here’s a how-to for an image I converted recently.

My goal for 2024 is to self host more, add newer services and harden security even more. Let’s see how 2024s setup will look like.