Self-hosting a static website on my old phone

· Amanda Ng

About seven months ago, I watched a video by Felix Kjellberg i.e. PewDiePie entitled “I’m DONE with Google” (dramatic title I know). Aside from seeding the realisation that I’m quite dependent on Google applications, I was surprised by how Kjellberg re-purposed his old Steamdeck for self-hosting applications. This surprise left a niggling thought at the back of my head on self-hosting: could I re-purpose an old mobile phone of mine for self-hosting too?

I have a Huawei Mate 20 from 2018 lying around as the “back-up phone in case things go south with my current phone”. It packs a Kirin 980 chip with 6 GB RAM and 128 GB storage capacity. Not too shabby for hardware I have lying around—sufficient for self-hosting my very own website.

That was how this website, this Digital Garden, came about.

Here’s what I learnt this side-quest. 🌸

TL;DR

I learnt to build a statistically generated site built with the Hugo framework styled with Tailwind CSS and daisyUI. The site tunnels to the public internet via Cloudflare tunnel and is served from an Android device running Termux.

If you’d like to self-host your own website similarly, I’ve made the GitHub repo ‘phone-hugo-blog’ that should help you along.

Table of contents

How do you build a website accessible by the public internet?

A website is a collection of data accessible from a URL. For example, this page you see is stored on a server (which is my old phone). When you type the URL for this page in your web browser, your web browser makes a request for this page from the server and the server responds by serving this page.

Not all websites are accessible by the public internet. The website could be accessible locally (on the same device the server is on) or connected to other devices through the internet or the intranet.

In other words, building a website accessible by the public internet can be seen as two main steps:

  1. Building a local website
  2. Connecting the website to the public internet

Building a local website

At this step, we’ve reached another fork in the road: do you want a static or dynamic website? Another way to look at this question is to ask: do you want to change the contents of your website via the web browser?

  • Static websites: The page is pre-built and served to you directly. You cannot change the contents of the website via the web browser.
  • Dynamic websites: The page is built based on the data you’ve requested for (e.g. from a database) or the data you’ve input via the browser.

For me, I’ve decided to go with a simpler set up — a static website. That’s why you can’t leave comments on these blog posts (that requires being able to change the contents of a website).

To build any website, we’ll need a site generator and styling tools, which is the tech stack underlying the local website. There are many tech stacks you can choose from when building a website. For me, it came down to what I had been exposed to:

While job hunting and casually googling around what people usually use for building their own blog website, Hugo tended to pop up. Hugo is a static website generator written in the Go language.

For styling the website, you could use Hugo’s default themes. I, however, had prior experience with Tailwind CSS and daisyUI from another side quest.

CSS stands for “Cascading Style Sheets”. To quote Wikipedia, CSS is “used for specifyng the presentation and styling of a document”. In other words, it controls how ugly or pretty your website is.

You can write in CSS directly or use frameworks like Tailwind CSS that have pre-written CSS utilities for easy use. Think of it as going from writing hundreds of lines of CSS to writing a handful of lines with Tailwind CSS to set your website’s background color. DaisyUI builds on top of Tailwind CSS, streamlining the lines of code behind the aesthetics of a website further. I also happen to like the selection of color themes from daisyUI which saves me a fair bit of time with color selection.

My resultant tech stack for building this website locally is, thus, Hugo + Tailwind CSS + daisyUI.

Tip 💡

Are there websites you enjoy the design of? Try inspecting the website (right click + inspect or whatever works for your browser). You’ll usually be able to find clues on the CSS library used. I’ve seen YUI (Yahoo! User Interface) and Boostrap for example.

Connecting a website to the public internet

So how can I connect my website to the public internet?

Connecting a website to the public internet requires two things:

  1. A public IP address
  2. Domain (Well, a domain is a “nice-to-have”.)

As aforementioned, when you search for a URL in your web browser, you’re making a request from a server for the webpage associated with that URL. This request is like a parcel being sent to your server. Using the mailing system as an analogy: to send this parcel, the address of your server is needed. Otherwise, the parcel would be lost in the mailing system. This address is the public IP address.

Thing is, most Internet Service Providers use what’s called Carrier-Grade Network Address Translation (CGNAT), which does not provide your device with a unique public IP address.

Rabbit hole 🐰

To be precise, Internet Service Providers (ISPs) do not provide your device a stable public IP address, which in part has to do with the dominant protocol used for IP addressing — the IPv4 protocol.

A CGNAT is like a gated complex of apartment buildings and your apartment in one of these apartment buildings. There are two lobbies between you and the outside world: the complex gatehouse and your building lobby. The complex gatehouse has a public address but the building lobby’s and your address aren’t publicly known; as such, the public internet can send the parcel to the complex gatehouse but the parcel cannot be passed on to your building lobby let alone you.

One solution is the Cloudflare tunnel. Since you don’t have a public address, you rent a PO box (Cloudflare’s network). Parcels from the public internet can be sent to the PO box and these parcels can be forwarded to you instantly (by having your device persistently connected to the PO box) without the public ever needing to know your real address.

Where does the domain come in then? IP addresses are a string of numbers like 203.0.113.42 that aren’t exactly snappy to remember. A domain is like a memorable nickname you can assign to an IP address like tangentialalmind.cc.

So when someone types tangentialalomd.cc into their browser, the following chain of events is triggered:

Visitor types "tangentialalmond.cc" in browser
DNS resolves it to Cloudflare's network
Cloudflare routes via Tunnel
Your device
Hugo serves the response (i.e. the web page)

Implementing the set up with Termux

Putting the theory altogether, Hugo builds the web pages which are styled by Tailwind CSS and daisyUI. This collection of web pages (a website) is connected to the public internet via Cloudflare Tunnel. That’s the set up.

To implement this set up on my phone, I installed Termux on my phone. Termux is a terminal emulator that allows you to run a Linux environment, which let’s you conveniently set up the design as you would on a laptop.

Viola! That’s what I learnt about self-hosting a website on my phone.

Reflection

I spent about 12 hours fiddling around with the set up to get the bare bones website up, which I’ve written as the GitHub repo ‘phone-hugo-blog’. If you’re planning to set up a similar website, the repo should speed up your progress quite significantly.

To address the elephant in the room, I did use Gemini and Claude for assistance in the form of:

  • entry points on how to self-host a website
  • writing and correcting my frontend .html and .md files (I found that both Gemini and Claude tend to write superfluous class attributes but perhaps that has to do with my prompting)

Overall, I found this side quest fun and a great entry point to understanding what goes on behind-the-scences for a website.