Hosting my own blog

October 08, 2025

I'm officially hosting my own blog!

Motivation

In the past, I'd leveraged Vercel to host my blog, but in light of recent events, I decided it was a good opportunity to host my blog on my own.

Another motivating factor of this decision was to learn. While I know enough Linux to be dangerous and I'm relatively comfortable building web applications, I generally rely on infrastructure providers for hosting purposes and I like my independence.

Tech Stack

At first, I was going to just use Pelican, but after some thought, I decided to roll my own. I'm pretty comfortable writing Python, I've written quite a few FastAPI applications, so I figured I could get something simple up and running with low effort.

My stack is pretty simple. It's really just

  • FastAPI + Uvicorn + Jinja
  • HTML
  • TailwindCSS (+ DaisyUI because I fancy it)
  • uv to manage dependencies ('cause, it's 2025 - I'm not gonna manually manage virtual environments)

That's it! No React. No Vite. No Tree Shaking. No Redux. No NextJS Pages Router vs. API Router. No Supabase.

Posting

I write an article in a file which gets rendered in a templitized HTML page. I admire the simplicity. And if I ever want something extra, I know all ~600 lines of code that make up my site (that wc includes this blog). No postgres or sqlite!

Hosting

I simply host this as a service on an Ubuntu VPS that I pay ~$5/month for. I wasn't really doing anything with it anyways, so serving this site is a pretty perfect fit.

The application is managed via systemctl. No docker. No k3s. No k8s. I have a config file in /etc/systemd/system which runs the following

ExecStart=/path/to/uvicorn main:app --proxy-headers --host 127.0.0.1 --port 8000 --workers 2

... of course there's some extra config to expose it to the internet.

For example, I navigated to my DNS provider and added a new A record that pointed the desired subdomain to my VPS IP address. In addition, I set up Caddy as a reverse proxy which points the subdomain to the app running on 127.0.0.1:8000. I did spend some cycles getting this set up but that's a story for another day. All that matters now is that we're here.

Deploying

Ok, so I rolled my own blog framework, but how does it get deployed? No k3s or k8s. No Vercel. So you're telling me that my Flux repo doesn't do any good here? That my ImagePolicy and ImageUpdateAutomation Resources won't get me anywhere? Big. Fat. Nope.

Instead, I went for the tried and true tar -czvf & scp method (I'm sure there will be some readers out there wishing they could smack me right now). No, it's not semantically versioned. No I don't have a docker image. I literally tarred up the entire repo, SCP'd it to my VPS from my laptop, untarred it and got to work.

I don't have any form of automation for deploying stuff (yet). I'll probably wrap those steps up into a bash script and put them behind a Github Action because knowing myself, I'll forget how to do all this by tomorrow. Computers have a better memory.

Tags: blog, writing, linux