As promised in my previous post, here's what's happening with my self-hosting project.
Motivation
The idea of following things more closely in 2025 was most effective for my "media diet" tracking to begin the year. I created an app for that using Laravel, mostly as an excuse to stay up to date on what's happening in Laravel world since we don't use it at my mysterious day job.
Specifically, I wanted to try my hand at using InertiaJS since I'd previously spent some time with Livewire for a different project. I really like Inertia. I get to use a lot of the React things I do like without all the horrifying state handling code everywhere. It feels to me like the best of React with all the stuff to love about old school PHP where all the state was a server concern (I could write a whole other post about how client-side state management as we do it today feels like a mistake).
Originally, I'd started the project with a SQLite database (standard for new Laravel projects these days), but I wanted to deploy this app somewhere that I could use it besides my main computer. I considered several cloud DB offerings, but they all felt like overkill for what I need. When you're younger and scaffolding these projects out, the temptation is to overbuild your personal stuff, perhaps to show off or practice for big-time job you want. There's also an instinct to just use one of these "easy" offerings like Supabase, Render.com, fly.io, etc. Sometimes they are pretty easy, but there's also some lock-in baked in to these offerings that I'm just not a fan of anymore. I definitely did not want to stand up anything in AWS or GCP, because that seems like a ticket to cloud billing hell.
First Steps
My initial step was to try out the aforementioned fly.io to deploy my media diet app. Fly has a selling point of being scalable down to zero for everything (compute, DB, whatever you need), but, in practice, dealing with all of that for this project was a bad fit.
The base use case really wants you to use at least two "machines" in their parlance, which are not actual compute instances so much as two conceptual compute units that are distinct from each other. I also liked the idea that the closest region was two hours away from me in Atlanta. I immediately ran into a big problem. Since I was already using SQLite for my DB, Fly seemed like it would be an easy path to deploying everything.
In practice, Fly was not ideal. As I mentioned, Fly really wants you to use two machines, and as a result, you actually need two separate copies of your SQLite database, synchronized via some plumbing that Fly wrote in house to manage syncing what is essentially two files across those two machines. In addition to that, there was no good story for how I would manage using that syncing mechanism and my local copy for development. In the real world, sharing the production database for development is a terrible idea, but this was a more practical concern where I didn't want to manage two databases for what is a single user project. This data is just not that mission critical, and it's also easy to back up.
Having already ruled out the managed SQL offerings of various providers, I decided to return to my old friend, Digital Ocean. I had previously used a basic $5 low-end VPS mostly as a playground that I kept around even once I stopped using it regularly. When it was being used, it was mainly to run my own RSS server using Fever (which I eventually abandoned because Feedbin did the same thing but better for $5/mo and I didn't have to manage anything myself).
Build Out
The first choice was the easiest. I did not want to use a managed SQL offering, and I've got plenty of experience running MySQL on my own (and it's low maintenance anyway). I tend to avoid running things that need external volumes on Docker/Kubernetes if I can help it, so it made the most sense to just run it on the host machine instead.
Next, I needed somewhere to host my actual projects. Containerization was the obvious choice, so I spent some time removing all the Fly configuration (and its associated containerization) and built out my own Dockerfile for my media project. Once that was complete, I needed to figure out what my containerization strategy was. I'm pretty familiar with Kubernetes at work, but that felt like overkill for now. A simple docker compose file could have gone a long way, but that felt a little fiddly and frankly, I wanted something nice to look at and manage with. I ended up choosing Portainer. I set up Portainer manually on the host machine, and I was up and running. I did not realize this at the time, but because I'm keeping this pretty simple with a single host machine, I was also eligible to use the "Business Edition" of Portainer. That helped enable some of the "GitOps" style integration that would make everything even easier to deploy in the future.
Tearing Down The World For Fun
(apologies to Jughead's Revenge)
All this new infrastructure setup for the media diet application gave me the perfect excuse to consolidate the other random projects I had lying around on free services. Hobby tier stuff seems like a prime candidate to eventually be moved into a small rent-seeking $5/mo-ish plan for these providers, but truthfully, I just wanted all my stuff under one roof, so to speak.
I had about six to eight projects floating around, mainly on Netlify. I had a previous version of this site, but it was effectively just a resume built in Gatsby. The last deployment was May 2020, so it's not like this thing had been carefully curated. My first attempt at building it was met with immediate errors (most likely because all the dependencies were ancient). It did not seem like a reasonable use of time to attempt to get that app running again and update it, especially since I wasn't happy with it in the first place.
One of the remaining projects was an old demo I'd made for a previous employer. I almost wanted to keep it, just because it was a uncommon project for me. We used Vue for frontends at that job, so I had built this particular one with Gridsome, which is basically a Gatsby analogue for Vue. Overall, it was nothing too exciting though (and of course it was several years old at this point), so I just ended up deleting the deployment and moving on.
The remaining projects were all these little one-page sites I'd made for my wife during the worst of COVID. I was honestly too afraid of leaving the house for even small things, so I made virtual "cards" instead of shopping for them in the store. They were effectively just basic static HTML and CSS sites, but I had over-engineered them as Gatsby sites. I'm not entirely sure of my motivation at the time, but I would guess that the reasons were probably:
I wanted to use nested CSS, and that was not supported in-browser at the time.
I just liked writing React components and wanted to stay sharp since I was using Vue for work.
I just wanted to use Gatsby for projects and work was never the place for it.
Living here in The Future™️ in 2025, the cards were insanely over-engineered for what you can do these days. I ended up ripping out all of the JS plumbing and converting them into simple, modern static sites (with nothing to generate 🥳).
I mean, just look at this commit:
The end result was each repo had maybe four files total (excluding any media that I had on each site). I ended up also building an index page for these four sites, so I had a nice catalog of them.
In all, I was able to remove all of my existing sites from Netlify and subsequently delete my account (no sense in keeping it around if I'm not going to use it).
This Site
For someone in my profession, especially having been around as long as I have, the idea of not having a site at all felt ridiculous. I was not interested in rebuilding a resume site since:
LinkedIn exists
It's just not an interesting project.
Sure, this site is somewhat intended to showcase my skills, but it's not going to keep my attention in the long run if that's all it is. Time will tell if even this will actually keep my attention. I will monitor and report back (or not).
I could have gone a more DIY route for building out this site, and I considered it, but that ultimately felt like making work just to have work. I wanted a blog this time around. I briefly considered leveraging my media diet app as a CMS by adding some blogging functionality to it, but that felt like it didn't fit the concept of the existing app. The only other thing I was certain about is that I wanted to use Laravel again.
Statamic was a platform that I was ambiently aware of due to keeping one hand in the Laravel ecosystem despite almost never using it for my day job. Even the free product is absurdly more feature-rich than anything I could have done in six months of part-time evening and weekend work. It's got an amazing control panel already built out and a great templating system. It also still felt like a development project for me since it's all just Laravel code that I can still play around with.
So now, you (the theoretical person reading this blog) are reading a statically-generated blog thanks to Statamic. I'm keeping everything in code and flat files so there's no additional database to keep track of and support. Everything gets committed to Git and is automatically generated and deployed to my VPS using GitHub Actions.
Tying it all together with Caddy
Man, I love Caddy. I've spent time in the Apache and nginx mines (💎 ⛏️) in my day, and Caddy is such a breeze relatively. So much of nginx.conf
and Apache configs feels like you're dealing with the implementation details of the programs themselves. Proxying traffic to Docker or serving static files is basically a three-line affair per site, and adding HTTPS to that is just three more lines (and some of these lines are just closing brackets). I can not imagine using nginx or Apache these days for small projects unless you just hate yourself. ¯\_(ツ)_/¯
This site, plus the five card related static sites are all just served directly by Caddy. Portainer and the media diet app are reverse-proxied into Docker and that's it. I'm redirecting traffic to seven sites with about 30 lines in a Caddyfile. The future is amazing. Happy to live in it.
Miscellany
A quick aside about another reason I decided against SQLite.
It does not handle dates well, and that's half of what the data is in the media diet app. There's not an actual date type in SQLite, and it basically just operates on the data as a string. It expects a very specific format for the data and doesn't really handle it if you use something else. MySQL felt much more predictable in that sense, so it was an easy choice to return home to it.
What's Next?
My next big projects are probably:
Adding footnote support to this blog. There's some existing stuff out there for Statamic, but it's paid, and I'd honestly just like to try and implement it myself anyway.
Making sure I have a good backup strategy for this site, the media diet, and everything else I have. The media diet is the only real issue at this point because everything else lives in Git, which means it's replicated on my local machines, GitHub, and also Digital Ocean possibly, depending on which project it is.
Getting more serious about self-hosting overall. I'd like to do a few Homelab type things, and maybe use some of the self-hosted, open-source clones of popular apps like Figma, Google Photos, etc.
I have some more features I want to add to the media diet app, shoved into an Apple Note somewhere. This site also needs a few punch list things done (mainly number 1 on this list, plus a custom 404 page).
Man, that was a lot
Thanks for reading, hypothetical person!