How hard could it be to write and host a website without breaking the bank?
Well, let's just say that it isn't as easy as you may expect...
First thing first, let me explain why putting all the effort behind making a website in the first place: I had some free time and a spare Raspberry Pi Zero W laying around on my desk (which I was using as a pwnagotchi) and I thought to myself that I could get much more use out of that sweet ARM chip.
Little did I know that using a six years old processor would be so problematic.
The first step was to register a domain on the web -a text based lable with the only advantage of being easier to memorize than the website IP- possibly with my name on it.
The first service that came to mind was "Ngrok": a service that allows developers to expose local servers to the web by tunneling a connection from the localhost to a ngrok domain.
Issue is you don't get to choose (or associate) a custom domain without a "premium account" and your website is blocked off to first time visitors by a warning which disappears only if you have session cookies or a custom header in the client's request.
Now that we have a domain we just need some way to host our website.
Finally we can dwelve into the technical side of the project: programming the server and getting the package to run on my ancient Raspberry Pi Zero W.
At first I thought that the best way to run a server on a computer the size of half a credit card was to use baremetal rust but, since even the most basic crate that handles HTTP requests
does not have support for a no_std project (most are based on the mio crate which requires an OS for its I/O event queue as it makes frequent use of epoll calls), I had to install some lightweight linux distro.
Initially I intended on using Arch Linux as I am quite familiar with it and -despite not being official- there is a port for ARM processors.
Much to my disappointment, I soon discovered that the development of Arch for ARMv6 processor has been discontinued since February 2022 and I could not find a valid image file to flash on the SD card on any of the unofficial archives.
Not willing to spend any more time looking for answers on ancient forums, I decided to just use the lite version of the Raspberry OS.
While I was downloading the necessary files I rememberd that the computer I used to flash the SD card broke down months ago and my current one does not have any SD slot on the I/O panels.
Determined to finish what I started, I tore down the old PC and retrieved the reader which I connected to the motherboard using the USB headers and was ready to flash the OS on the chip.
If someone is trying to follow along, I advise using the Raspberry Pi imager as it allows you to set a SSID and password for your network and turn on SSH without having to mess with any of the system files.
Settings I used when flashing the image to my SD
Now that my Raspberry was ready I could start programming the web server...
Now the grand finale: writing the rust script to run the server.
Everything is pretty straight-forward if you have any experience with the tokio or hyper crate.
(up to date code can be found on my github profile)
The main loop only consists of creating a service from a generic function "serve_request"
pub async fn server() -> Result<(), Infallible>{
let make_svc = make_service_fn(move |conn: &AddrStream| {
let addr = conn.remote_addr();
let service = service_fn(move |req| {
serve_request( req ,addr)
});
async move {Ok::<_, Infallible>(service) }
});
[...]
match (req.method(), req.uri().path()) {
(&Method::GET, "/") => {
let body = fs::read_to_string("main.html").await.unwrap();
let body = body;
Ok(Response::builder()
.header("Content-Type", "text/html")
.body(Body::from(body))
.unwrap())
}
[...]
let addr = ([127, 0, 0, 1], 7878).into();
let server = Server::bind(&addr).serve(make_svc);
Finally we proved that it is possible to have a perfectly working website using some inexpensive components and lots of patience.
That said, I strongly advise to buy a newer chip if you are going to attempt this project. Compatibility issues are not fun to deal with, and a more performant device means not having to worry too much about the complexity of the program or the number of concurrent visitors.
I will try to improve the code by adding logging functionalities and changing the style of the site (the css is heavily inspired by another tech blog).
UwU