Self-hosting shenanigans update
For a while, I’ve been hosting a number of personal-use-only services on a few Oracle Cloud Ampere instances. Annoyingly, though, Oracle recently halved their “always free” limits — and also got a lot more aggressive about reclaiming instances it thought were sitting idle. Which, you know, my instances mostly were, since I was the only user.
Since I had some free time this weekend, I decided to “repatriate” my cloud-hosted services back to on-prem — where “on-prem” is the DGX Spark sitting in my office.
And that seemed to call for an update to my old post on self-hosting.
Overall, my self-hosting rationale from the old post is still true. I self-host a service if:
- Self-hosting is going to add a capability that’s difficult to find in a SaaS alternative. That might be privacy, or extra compute, or just an extra degree of customization that I want.
- I find it interesting or amusing to self-host it! I have been a professional sysadmin, and ran production web services for over a decade. So I enjoy messing around with servers, and can have a fair amount of fun with this.
From an infrastructure perspective, my current self-hosting platform is an NVIDIA DGX Spark that I use as a development workstation. I mostly treat it as a headless server and access it over SSH or HTTP; while I think there might be a connection between the Spark and my desktop KVM switch, I haven’t actually used a keyboard or monitor with it directly in many months.
(Do I worry about reliability for this? Not terribly. If anything, my local setup has been more reliable than Oracle in recent experience…)
Tailscale continues to be a load-bearing part of my setup, even more than it was before I started moving things locally. At this point, I don’t think I actually have any personal-use services with endpoints on the public Internet. Instead, I access them entirely via Tailscale from my own devices or my family’s.
As for what I’m hosting right now, the major self-hosted open-source services running on the Spark are:
- FreshRSS, a self-hosted RSS feed aggregator
- One of the things I like about FreshRSS is that it’s API-compatible with Reeder, which is my feed app of choice on phone and desktop
- Gitea is a lightweight Git forge, and my hosted instance is where I keep the “source of truth” for most of my hobby projects
- Open WebUI, which gives me a chat interface to a few different LLMs that run directly on the DGX Spark’s GPU. Right now I’m getting a lot of use out of the Gemma models.
I also have a few smaller, more personal services running here:
- daily-news-rss is a tiny feed generator that gives me an aggregated daily news update. It scans a specified list of sources — weather.gov, AP News, the Denver Post, and others — and assembles a short news brief. That news brief goes into an RSS feed that I read via the FreshRSS setup described above. The whole thing runs as a daily cron job.
- Incidentally, this generator takes advantage of the local GPU on the Spark to extract headlines from the news source web pages and pick the “top 5” I might be interested in. Right now this is gemma4:12b, running via ollama.
- personal-feed-generator is similar in spirit, but more geared towards finding research papers and industry news. Instead of a daily report, it scans my list of upstream sources each day and tries to identify anything I find relevant — again, using a local LLM to score relevance. If it finds an interesting item, it adds it to the RSS feed as a standalone item, including a short explanation for why it’s relevant.
- Right now relevance is decided by gemma4:e4b, as I find the smaller model is less likely to try and find… speculative… connections between my list of interests and whatever it’s reading.
- chess-openings-trainer is a tiny webapp for playing with and visualizing chess openings. At the moment it’s pretty procedural, though at some point I’d like to extend it to use Stockfish for game analysis…
I also frequently run smaller, more “throw-away” webapps here to solve short-term problems or curiosities. For example, since I joined a quantum computing company, I have a janky webapp for visualizing the Bloch sphere which helped with some early learning. These sorts of apps generally get built in an afternoon, I play with them for a few days or weeks, and then thrown away. One of the handy things about a good self-hosting setup is that the activation energy for these experiments is low!
Let’s see, what’s left for implementation details?
- Except when I actually want to share the code for something, everything ends up in a big private monorepo named
play, with history stretching back… Dear Lord, over 15 years at this point. - Many of these services run in Docker containers, set up with docker-compose with files tracked in the repo.
- Kubernetes is a great tool, but it does not entertain me to self-host at single-node scale.
- Trivial apps — especially those that are HTML+JS only — just run directly from
/var/www/htmlwith an nginx webserver. - The DGX Spark also gets used for general development and playing around, either by hand or using OpenCode with qwen3-coder-30B.
- The whole thing gets backed up to S3 using restic, so that I have some hope of recovery if the host dies.
A few services got dropped in the transition, including a Fediverse instance, an IRC bouncer, and a Matrix server. Some of those may get resurrected at some point (e.g., the IRC bouncer), but none of them were in anything like regular use so I wasn’t sad to sunset them.
