The blog that you are currently reading has a perfect PageSpeed score 100 / 100. At least at the moment of writing it 😄. It’s not a brag, quite the opposite. Turns out it’s not that hard to achieve it. Just host a static page with simple styles, and you’re done. Building a static page itself is quite simple. You plop an
index.html and send it through a wire. You can get more sophisticated and generate it using a framework, like I’m doing with Astro. But that’s not the point of this post.
The point is the hosting part of hosting a static page. And this page is hosted on my Raspberry Pi 4b at my house. Still doing great in terms of speed, costing close to nothing, and having endless possibilities for extending for free. In this blog post I’ll share with you how easy it was to set up. And how great of a dev experience I think it provides.
I’ve been using NextJS for a while and hosting the apps built with it on AWS with custom express servers. One day I’ve noticed that my servers are getting red-hot while doing almost nothing, and response times got huge. Long story short the library introduced a huge performance downgrade that was not caught by existing tests. Why so? Because benchmarks were using only Vercel’s (creators of NextJS) “Edge” infrastructure. And the bug was happening everywhere but not there. That’s when it struck me. We need alternative independent hosting to ensure that the community does not get stuck with a single provider. And that’s when I’ve decided to host my app on my own server.
So what do you need to host your own page? Well, a server, a way to deploy your page, and a domain.
I’ve already had an ok work from home setup:
In summary my dev setup is built in a way that it should allow me to work without interruption. What I was missing for a home server setup was well… the server.
Inspired by @JeffGeerling and his videos about creating a Pi Cluster I bought myself a second hand Raspberry Pi 4b 4GB for around 60$. There are of course alternatives to it, but I’ve had one of those running already for almost a year with literally 0 downtime. Not even once has it turned off or rebooted. I was using it as a Pi Hole. Turns out in 21st century you can even update it without downtime. 10 / 10. If you need a home server just get one.
Now that I had my server, how to set it up to work with my app? I’ve looked around how people usually do that and I quickly noticed that you need like 10 complicated time-consuming steps to run an app on metal. Nginx setup, Capistrano or similar tool for automating deployment (running new versions and shutting down old ones), SSL Certs (because no one uses http anymore), and if you want to Dockerize it, then Docker related stuff is required i.e. Kubernetes which itself is hyper-complicated. Soooooo I was screwed. I tried the kubernetes approach which was super uber complicated for a blog and I gave up. Similarly, the bare metal solution consisting of nginx with manual Let’s Encrypt cert setup was too much of a hassle. So I’ve dropped the idea. A few months later I’ve found Coolify while browsing reddit.
It was marketed as a simpler, more web focused version of CapRover, which itself is an Open Source alternative to Heroku. I come from a Ruby on Rails world so Heroku is GOAT for me (until it gets extremely costly). After I saw it I knew this is the way to do my home setup! Same evening I sat down to test it. It took around an hour to set everything up from the ground up:
rpi-imagerwith ssh and Wi-Fi config onto the SD card
After that I went to the Coolify dashboard and wow. It’s really like a quicker, simpler version of Heroku.
For a test project I’ve decided to try and set up my blog on it which at the time was running on Cloudflare Workers. I’ve picked the Static Page image, and with a few more clicks, plus a
git push my app was deployed and running on my Berry. It took like 5 minutes, and was probably easier than deploying it to Heroku. After the experiment I’ve decided to go further with the idea and expose the blog to the world.
Excited, I’ve bought a domain (
grifel.app) on Google Domains. I use it because they have all of the extensions like app and dev, don’t do much marketing BS, and provide a simple but fully featured admin panel.
So now it’s time to attach it to my local server and whoops. We’ve got a problem. When assigning the domain to IP address I remembered that I don’t have a static IP address. I’ve got a dynamic one like most households. (For those unfamiliar with the concept of dynamic external IPs, a modem assigns me a new IP address every time it reboots, or my net disconnects.)
Thankfully I’ve tackled this problem once already. In my childhood when I was hosting my own MU Online server I was lacking a static IP. And to get a server to the public I’ve used Hamachi! It works like this: Every X seconds when your server is connected to internet it sends information about the IP you currently have to a DDNS (Dynamic DNS). Worst case worst, your IP changes, X seconds pass, your server informs DDNS, and it navigates the traffic to the new IP. It turns out that Google Domains even has this feature built in! I’ve installed DDClient, which is the tool Google suggested in their docs, and configured it with my credentials. Whole process took around 10 minutes. I got info that it works by looking at the DDNS record in Google Domains admin panel. It was updated with my current IP.
I then went back to my Coolify panel and set the https://blog.grifel.app domain as FQDN in my app. Waited 30 seconds and voilà my blog is reachable at that address. With https working. It’s like magic. 10 years ago this was the thing that made Heroku so great. Now you can have it in your own setup with a few clicks.
PageSpeed score is still 100 / 100, so I guess my setup is fast enough and didn’t screw up my UX. My uptime is 100% for the last month which will obviously stop working at the worst point in time, and you’ll have to live without my great blog for an hour, but I hope you’ll survive. I’m hosting on a Raspberry Pi 4b 4GB, so if anyone wants to DDOS me then I’m probably not going to live through that. The server is located in Warsaw, so I’m not on the edge right next to your house, but I guess it’s not a problem. My packets will need to travel through the whole world to get to you, but light is fast enough. At any point in time I can use a CDN to battle all those struggles though.
But for the cost of all those problems I have my own Heroku’ish platform, automated deployment pipeline even feature branches are there. I can have a 100-person team working on this app, and not pay 5$ monthly for them to be able to access logs. I can directly contribute to it and extend it in any way I want. Would I host my future business on it? Probably not. I would still go with AWS or a similar solution just to avoid any problems that would screw it up in a way that I can’t even imagine, and they did. But honestly this experiment made me really think about it.
And if you’re interested in the operational cost of running this setup it is like 60$ for the Raspberry Pi (one time cost) + electricity (less than 1$ a month) + 10$ a year for domain (which I needed anyway). So not more than like 2$ a month if you already have internet in your home.
If you liked the post you might also want to read:
← How 3000 people won in my self-hosted game