From 09e410b21358e1475261499ccf6a75fac2da12d4 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Mon, 5 Jan 2026 21:15:44 +0200 Subject: Refactor and colocate assets --- content/posts/atk16-my-homegrown-computer.md | 17 --- .../atk16-text-mode.png | Bin 0 -> 427840 bytes content/posts/atk16-my-homegrown-computer/index.md | 17 +++ content/posts/cassettes.md | 28 ----- content/posts/cassettes/cassette_player.jpeg | Bin 0 -> 3747638 bytes content/posts/cassettes/index.md | 28 +++++ content/posts/deploying-the-garden.md | 38 ------ content/posts/deploying-the-garden/index.md | 38 ++++++ content/posts/deploying-the-garden/repo_langs.png | Bin 0 -> 25064 bytes content/posts/diddle-event-scheduler.md | 20 ---- .../diddle-event-scheduler/diddle_screenshot.png | Bin 0 -> 100453 bytes content/posts/diddle-event-scheduler/index.md | 20 ++++ content/posts/eurobsdcon-2025-conf-notes.md | 89 -------------- .../eurobsdcon_2025_binders.jpeg | Bin 0 -> 3375983 bytes .../eurobsdcon_2025_cevapi.jpeg | Bin 0 -> 3111850 bytes .../eurobsdcon_2025_group.jpeg | Bin 0 -> 621216 bytes .../eurobsdcon_2025_hallway.jpeg | Bin 0 -> 4168772 bytes content/posts/eurobsdcon-2025-conf-notes/index.md | 89 ++++++++++++++ content/posts/home-server-part-1.md | 78 ------------- .../posts/home-server-part-1/3-2-1-Backup-Rule.png | Bin 0 -> 34158 bytes .../posts/home-server-part-1/aliexpress_minipc.png | Bin 0 -> 793558 bytes .../posts/home-server-part-1/do-june-billing.png | Bin 0 -> 133566 bytes content/posts/home-server-part-1/index.md | 78 +++++++++++++ .../home-server-part-1/old-man-yells-at-cloud.png | Bin 0 -> 1059057 bytes content/posts/home-server-part-2.md | 91 --------------- .../posts/home-server-part-2/aliexpress_minipc.png | Bin 0 -> 793558 bytes .../aliexpress_minipc_results.png | Bin 0 -> 1360509 bytes content/posts/home-server-part-2/index.md | 91 +++++++++++++++ content/posts/home-server-part-3.md | 77 ------------ content/posts/home-server-part-3/index.md | 77 ++++++++++++ .../home-server-part-3/pursotin_fastfetch.png | Bin 0 -> 285448 bytes .../posts/home-server-part-3/pursotin_raidz.svg | 1 + content/posts/home-server-part-4.md | 124 -------------------- content/posts/home-server-part-4/index.md | 124 ++++++++++++++++++++ .../posts/home-server-part-4/pursotin_network.svg | 1 + content/posts/it-doesnt-mean-that.md | 42 ------- content/posts/it-doesnt-mean-that/index.md | 40 +++++++ .../posts/it-doesnt-mean-that/wikimedia_monad.svg | 1 + content/posts/now-2024-fall.md | 88 -------------- content/posts/now-2024-fall/diffuser_1.jpg | Bin 0 -> 3447758 bytes content/posts/now-2024-fall/diffuser_2.jpg | Bin 0 -> 3239064 bytes content/posts/now-2024-fall/diffuser_3.jpg | Bin 0 -> 3723759 bytes content/posts/now-2024-fall/index.md | 88 ++++++++++++++ content/posts/now-2024-spring.md | 87 -------------- content/posts/now-2024-spring/index.md | 87 ++++++++++++++ content/posts/now-2024-spring/jojo-in-snow.webm | Bin 0 -> 1508041 bytes content/posts/now-2024-summer.md | 56 --------- content/posts/now-2024-summer/2024-wines.jpg | Bin 0 -> 3095038 bytes content/posts/now-2024-summer/aws-exam-drink.jpeg | Bin 0 -> 2606811 bytes content/posts/now-2024-summer/index.md | 56 +++++++++ content/posts/now-2025-fall.md | 90 -------------- content/posts/now-2025-fall/index.md | 90 ++++++++++++++ content/posts/now-2025-fall/valokate_1.jpg | Bin 0 -> 3726158 bytes content/posts/now-2025-fall/valokate_2.jpg | Bin 0 -> 1931666 bytes content/posts/now-2025-fall/villa.jpeg | Bin 0 -> 2572301 bytes content/posts/now-2025-summer.md | 114 ------------------ content/posts/now-2025-summer/index.md | 114 ++++++++++++++++++ content/posts/now-2025-summer/kenrokuen.jpg | Bin 0 -> 8081996 bytes content/posts/now-2025-summer/samurai_garden.jpeg | Bin 0 -> 6622434 bytes content/posts/now-2025-summer/wagyu_grill.jpeg | Bin 0 -> 3270292 bytes content/posts/now-2025-winter.md | 129 --------------------- .../posts/now-2025-winter/2025_wrapped_genres.jpeg | Bin 0 -> 173496 bytes .../now-2025-winter/backdoor_feature_done.jpeg | Bin 0 -> 3525718 bytes .../now-2025-winter/backdoor_feature_wip.jpeg | Bin 0 -> 3340312 bytes content/posts/now-2025-winter/dopamine_office.jpeg | Bin 0 -> 3272619 bytes content/posts/now-2025-winter/index.md | 129 +++++++++++++++++++++ content/posts/now-2025-winter/muumimusiikkia.jpeg | Bin 0 -> 2951215 bytes content/posts/now-2025-winter/taulu_koira.jpeg | Bin 0 -> 2778093 bytes content/posts/qcon-london-2024-takeaways.md | 112 ------------------ .../fish-and-chips-duke-of-argyll.jpg | Bin 0 -> 2997683 bytes content/posts/qcon-london-2024-takeaways/index.md | 112 ++++++++++++++++++ .../london-from-above.jpg | Bin 0 -> 3041148 bytes content/posts/subjective-review-miru.md | 73 ------------ .../hinokodo-static-abyss.png | Bin 0 -> 2457949 bytes content/posts/subjective-review-miru/index.md | 73 ++++++++++++ .../subjective-review-miru/miru_gameplay.jpeg | Bin 0 -> 2317180 bytes .../miru_time_to_kill_triple.jpg | Bin 0 -> 1559052 bytes content/posts/theres-an-rss-feed-now.md | 10 -- content/posts/theres-an-rss-feed-now/index.md | 10 ++ .../posts/theres-an-rss-feed-now/internet_surf.png | Bin 0 -> 394047 bytes content/posts/unfold.md | 42 ------- content/posts/unfold/index.md | 42 +++++++ content/posts/unfold/indieweb_presentation.png | Bin 0 -> 333070 bytes content/posts/unfold/reveal-js-logo.png | Bin 0 -> 85023 bytes 84 files changed, 1406 insertions(+), 1405 deletions(-) delete mode 100644 content/posts/atk16-my-homegrown-computer.md create mode 100644 content/posts/atk16-my-homegrown-computer/atk16-text-mode.png create mode 100644 content/posts/atk16-my-homegrown-computer/index.md delete mode 100644 content/posts/cassettes.md create mode 100644 content/posts/cassettes/cassette_player.jpeg create mode 100644 content/posts/cassettes/index.md delete mode 100644 content/posts/deploying-the-garden.md create mode 100644 content/posts/deploying-the-garden/index.md create mode 100644 content/posts/deploying-the-garden/repo_langs.png delete mode 100644 content/posts/diddle-event-scheduler.md create mode 100644 content/posts/diddle-event-scheduler/diddle_screenshot.png create mode 100644 content/posts/diddle-event-scheduler/index.md delete mode 100644 content/posts/eurobsdcon-2025-conf-notes.md create mode 100644 content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_binders.jpeg create mode 100644 content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_cevapi.jpeg create mode 100644 content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_group.jpeg create mode 100644 content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_hallway.jpeg create mode 100644 content/posts/eurobsdcon-2025-conf-notes/index.md delete mode 100644 content/posts/home-server-part-1.md create mode 100644 content/posts/home-server-part-1/3-2-1-Backup-Rule.png create mode 100644 content/posts/home-server-part-1/aliexpress_minipc.png create mode 100644 content/posts/home-server-part-1/do-june-billing.png create mode 100644 content/posts/home-server-part-1/index.md create mode 100644 content/posts/home-server-part-1/old-man-yells-at-cloud.png delete mode 100644 content/posts/home-server-part-2.md create mode 100644 content/posts/home-server-part-2/aliexpress_minipc.png create mode 100644 content/posts/home-server-part-2/aliexpress_minipc_results.png create mode 100644 content/posts/home-server-part-2/index.md delete mode 100644 content/posts/home-server-part-3.md create mode 100644 content/posts/home-server-part-3/index.md create mode 100644 content/posts/home-server-part-3/pursotin_fastfetch.png create mode 100644 content/posts/home-server-part-3/pursotin_raidz.svg delete mode 100644 content/posts/home-server-part-4.md create mode 100644 content/posts/home-server-part-4/index.md create mode 100644 content/posts/home-server-part-4/pursotin_network.svg delete mode 100644 content/posts/it-doesnt-mean-that.md create mode 100644 content/posts/it-doesnt-mean-that/index.md create mode 100644 content/posts/it-doesnt-mean-that/wikimedia_monad.svg delete mode 100644 content/posts/now-2024-fall.md create mode 100644 content/posts/now-2024-fall/diffuser_1.jpg create mode 100644 content/posts/now-2024-fall/diffuser_2.jpg create mode 100644 content/posts/now-2024-fall/diffuser_3.jpg create mode 100644 content/posts/now-2024-fall/index.md delete mode 100644 content/posts/now-2024-spring.md create mode 100644 content/posts/now-2024-spring/index.md create mode 100644 content/posts/now-2024-spring/jojo-in-snow.webm delete mode 100644 content/posts/now-2024-summer.md create mode 100644 content/posts/now-2024-summer/2024-wines.jpg create mode 100644 content/posts/now-2024-summer/aws-exam-drink.jpeg create mode 100644 content/posts/now-2024-summer/index.md delete mode 100644 content/posts/now-2025-fall.md create mode 100644 content/posts/now-2025-fall/index.md create mode 100644 content/posts/now-2025-fall/valokate_1.jpg create mode 100644 content/posts/now-2025-fall/valokate_2.jpg create mode 100644 content/posts/now-2025-fall/villa.jpeg delete mode 100644 content/posts/now-2025-summer.md create mode 100644 content/posts/now-2025-summer/index.md create mode 100644 content/posts/now-2025-summer/kenrokuen.jpg create mode 100644 content/posts/now-2025-summer/samurai_garden.jpeg create mode 100644 content/posts/now-2025-summer/wagyu_grill.jpeg delete mode 100644 content/posts/now-2025-winter.md create mode 100644 content/posts/now-2025-winter/2025_wrapped_genres.jpeg create mode 100644 content/posts/now-2025-winter/backdoor_feature_done.jpeg create mode 100644 content/posts/now-2025-winter/backdoor_feature_wip.jpeg create mode 100644 content/posts/now-2025-winter/dopamine_office.jpeg create mode 100644 content/posts/now-2025-winter/index.md create mode 100644 content/posts/now-2025-winter/muumimusiikkia.jpeg create mode 100644 content/posts/now-2025-winter/taulu_koira.jpeg delete mode 100644 content/posts/qcon-london-2024-takeaways.md create mode 100644 content/posts/qcon-london-2024-takeaways/fish-and-chips-duke-of-argyll.jpg create mode 100644 content/posts/qcon-london-2024-takeaways/index.md create mode 100644 content/posts/qcon-london-2024-takeaways/london-from-above.jpg delete mode 100644 content/posts/subjective-review-miru.md create mode 100644 content/posts/subjective-review-miru/hinokodo-static-abyss.png create mode 100644 content/posts/subjective-review-miru/index.md create mode 100644 content/posts/subjective-review-miru/miru_gameplay.jpeg create mode 100644 content/posts/subjective-review-miru/miru_time_to_kill_triple.jpg delete mode 100644 content/posts/theres-an-rss-feed-now.md create mode 100644 content/posts/theres-an-rss-feed-now/index.md create mode 100644 content/posts/theres-an-rss-feed-now/internet_surf.png delete mode 100644 content/posts/unfold.md create mode 100644 content/posts/unfold/index.md create mode 100644 content/posts/unfold/indieweb_presentation.png create mode 100644 content/posts/unfold/reveal-js-logo.png (limited to 'content/posts') diff --git a/content/posts/atk16-my-homegrown-computer.md b/content/posts/atk16-my-homegrown-computer.md deleted file mode 100644 index 6b9f583..0000000 --- a/content/posts/atk16-my-homegrown-computer.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: ATK16 – My homegrown computer -date: 2024-05-01 -extra: - kind: project ---- - -![A screenshot of a text mode program displaying a work-in-progress hardware monitor](/files/atk16-text-mode.png) - -**ATK16** is a learning project I've been working on for some time. It started off as a 16-bit, reduced instruction set computer (RISC) CPU design but evolved into an entire computer with peripherals and software. - -Instead of repeating myself, I'm going to direct you to the [ATK16 project page](/projects/atk16). It's not complete by any means, but I've written a bunch about the project and my motivations already! [¹](#footnote) - ---- - -
-1. There's actually more text in there than in my bachelor's thesis. diff --git a/content/posts/atk16-my-homegrown-computer/atk16-text-mode.png b/content/posts/atk16-my-homegrown-computer/atk16-text-mode.png new file mode 100644 index 0000000..93c2752 Binary files /dev/null and b/content/posts/atk16-my-homegrown-computer/atk16-text-mode.png differ diff --git a/content/posts/atk16-my-homegrown-computer/index.md b/content/posts/atk16-my-homegrown-computer/index.md new file mode 100644 index 0000000..ba8bf84 --- /dev/null +++ b/content/posts/atk16-my-homegrown-computer/index.md @@ -0,0 +1,17 @@ +--- +title: ATK16 – My homegrown computer +date: 2024-05-01 +extra: + kind: project +--- + +![A screenshot of a text mode program displaying a work-in-progress hardware monitor](atk16-text-mode.png) + +**ATK16** is a learning project I've been working on for some time. It started off as a 16-bit, reduced instruction set computer (RISC) CPU design but evolved into an entire computer with peripherals and software. + +Instead of repeating myself, I'm going to direct you to the [ATK16 project page](/projects/atk16). It's not complete by any means, but I've written a bunch about the project and my motivations already! [¹](#footnote) + +--- + +
+1. There's actually more text in there than in my bachelor's thesis. diff --git a/content/posts/cassettes.md b/content/posts/cassettes.md deleted file mode 100644 index 5b8f6b6..0000000 --- a/content/posts/cassettes.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: Cassettes -date: 2024-03-27 -extra: - kind: note ---- - -I like the idea of cassettes. They are cheap and analog, and there’s a culture of sharing and trading them. I like the sound of tape saturation and hysteresis. - -They feel much more approachable than vinyls. I dislike snobbery. - -## So I bought a cassette player - -{{ fig(src="/files/cassette_player.jpeg", alt="A Sony cassette recorder next to a pile of cassettes") }} - -It’s a Sony TCM-459V and it’s only a bit noisy and wobbly. It can record too. - -After listening to all of my tapes (not very many, see picture), A side and B side, I can safely say that I like cassettes. - -## Maintenance - -The manual says that the innards need cleaning (rubbing alcohol + q-tip) after every 10 hours of operation. I don’t think this unit has ever been cleaned. - -The belts might also need changing since they apparently go bad after a while. - -## Tapes catch on fire - -I read on the internet that peoples’ tapes have spontaneously combusted. This is a thing to avoid. diff --git a/content/posts/cassettes/cassette_player.jpeg b/content/posts/cassettes/cassette_player.jpeg new file mode 100644 index 0000000..6591cc4 Binary files /dev/null and b/content/posts/cassettes/cassette_player.jpeg differ diff --git a/content/posts/cassettes/index.md b/content/posts/cassettes/index.md new file mode 100644 index 0000000..92d3887 --- /dev/null +++ b/content/posts/cassettes/index.md @@ -0,0 +1,28 @@ +--- +title: Cassettes +date: 2024-03-27 +extra: + kind: note +--- + +I like the idea of cassettes. They are cheap and analog, and there’s a culture of sharing and trading them. I like the sound of tape saturation and hysteresis. + +They feel much more approachable than vinyls. I dislike snobbery. + +## So I bought a cassette player + +{{ fig(src="cassette_player.jpeg", alt="A Sony cassette recorder next to a pile of cassettes") }} + +It’s a Sony TCM-459V and it’s only a bit noisy and wobbly. It can record too. + +After listening to all of my tapes (not very many, see picture), A side and B side, I can safely say that I like cassettes. + +## Maintenance + +The manual says that the innards need cleaning (rubbing alcohol + q-tip) after every 10 hours of operation. I don’t think this unit has ever been cleaned. + +The belts might also need changing since they apparently go bad after a while. + +## Tapes catch on fire + +I read on the internet that peoples’ tapes have spontaneously combusted. This is a thing to avoid. diff --git a/content/posts/deploying-the-garden.md b/content/posts/deploying-the-garden.md deleted file mode 100644 index 105bfb7..0000000 --- a/content/posts/deploying-the-garden.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: Deploying the garden -date: 2024-03-26 -extra: - kind: note ---- - -Every respectable tech blog must contain two posts: - -- ”This site now has RSS” -- ”This is how this site is deployed” - -Other content is optional. - -## Writing on the go - -Content updates go like this: - -1. I write Markdown in a special directory in my Obsidian Vault -2. The change is synced to my Digital Ocean server via Obsidian Sync (I run an Obsidian process on my server) -3. A file system monitor script picks it up and runs a build script -4. Built HTML files are served with Nginx - -This process gives me full control over the content wherever I have access to Obsidian. Making writing as easy as possible is the principle behind this design. - -[This is considered a good idea in the frog community.](https://www.todepond.com/wikiblogarden/art/never-stop-writing/on-your-phone) - -Making changes to the build process itself, or the HTML template, requires a computer, however. - -## Parentheses - -Most of the heavy lifting is done by `pandoc`. The glue parts use an obscure and ancient language with many curved sigils. Give it a try. - -{{ fig(src="/files/repo_langs.png", alt="A GitHub repository language breakdown showing that most of the code is written in Scheme.") }} - -## Hosting - -My small Digital Ocean server also moonlights as a container image registry. I build the scripts into an OCI image, push it on the server and run it with `docker-compose`. Don’t over-engineer when you want things _done_. diff --git a/content/posts/deploying-the-garden/index.md b/content/posts/deploying-the-garden/index.md new file mode 100644 index 0000000..cdb5caf --- /dev/null +++ b/content/posts/deploying-the-garden/index.md @@ -0,0 +1,38 @@ +--- +title: Deploying the garden +date: 2024-03-26 +extra: + kind: note +--- + +Every respectable tech blog must contain two posts: + +- ”This site now has RSS” +- ”This is how this site is deployed” + +Other content is optional. + +## Writing on the go + +Content updates go like this: + +1. I write Markdown in a special directory in my Obsidian Vault +2. The change is synced to my Digital Ocean server via Obsidian Sync (I run an Obsidian process on my server) +3. A file system monitor script picks it up and runs a build script +4. Built HTML files are served with Nginx + +This process gives me full control over the content wherever I have access to Obsidian. Making writing as easy as possible is the principle behind this design. + +[This is considered a good idea in the frog community.](https://www.todepond.com/wikiblogarden/art/never-stop-writing/on-your-phone) + +Making changes to the build process itself, or the HTML template, requires a computer, however. + +## Parentheses + +Most of the heavy lifting is done by `pandoc`. The glue parts use an obscure and ancient language with many curved sigils. Give it a try. + +{{ fig(src="repo_langs.png", alt="A GitHub repository language breakdown showing that most of the code is written in Scheme.") }} + +## Hosting + +My small Digital Ocean server also moonlights as a container image registry. I build the scripts into an OCI image, push it on the server and run it with `docker-compose`. Don’t over-engineer when you want things _done_. diff --git a/content/posts/deploying-the-garden/repo_langs.png b/content/posts/deploying-the-garden/repo_langs.png new file mode 100644 index 0000000..9c85b3b Binary files /dev/null and b/content/posts/deploying-the-garden/repo_langs.png differ diff --git a/content/posts/diddle-event-scheduler.md b/content/posts/diddle-event-scheduler.md deleted file mode 100644 index 701e252..0000000 --- a/content/posts/diddle-event-scheduler.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Diddle, a minimalist event scheduler -date: 2024-03-12 -extra: - kind: project ---- - -I don't like Doodle. It pushes ads and its premium subscription relentlessly while simultaneously feeling like a clumsy, lumbering beast. There is also a lot to be desired in terms of accessibility and mobile-friendliness. - -There are alternatives, like [dudle](https://dud-poll.inf.tu-dresden.de/) or [framadate](https://framadate.org/abc/en/). I could probably make do with those. However, to me this felt like an opportunity to spin up a quick MVP. This MVP turned into _diddle_. - -Diddle ([live instance](https://diddle.jan.systems/), [Github](https://github.com/jantuomi/diddle)) is a minimalist tool that focuses on fast load times, accessibility and pragmatism. The feature set is based on my own personal requirements. It works great for quickly filling out a poll on mobile. - -**Note**: The instance hosted on my domain might go down any second. Use it at your own discretion. - -{{ fig(src="/files/diddle_screenshot.png", alt="Diddle screenshot showing an answerable poll") }} - -The first 80% of the project was done in two evenings. The last 80% was done during the next week. The tech stack is the _get-shit-done_ stack: **Python** + **Flask** + **PostgreSQL**. There is no required client side javascript: all client side logic is strictly for [progressive enhancement](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement). You can use "dumb" browsers like w3m or lynx to enjoy Diddle just fine. - -Check out the README on Github for more info. diff --git a/content/posts/diddle-event-scheduler/diddle_screenshot.png b/content/posts/diddle-event-scheduler/diddle_screenshot.png new file mode 100644 index 0000000..437567e Binary files /dev/null and b/content/posts/diddle-event-scheduler/diddle_screenshot.png differ diff --git a/content/posts/diddle-event-scheduler/index.md b/content/posts/diddle-event-scheduler/index.md new file mode 100644 index 0000000..033a352 --- /dev/null +++ b/content/posts/diddle-event-scheduler/index.md @@ -0,0 +1,20 @@ +--- +title: Diddle, a minimalist event scheduler +date: 2024-03-12 +extra: + kind: project +--- + +I don't like Doodle. It pushes ads and its premium subscription relentlessly while simultaneously feeling like a clumsy, lumbering beast. There is also a lot to be desired in terms of accessibility and mobile-friendliness. + +There are alternatives, like [dudle](https://dud-poll.inf.tu-dresden.de/) or [framadate](https://framadate.org/abc/en/). I could probably make do with those. However, to me this felt like an opportunity to spin up a quick MVP. This MVP turned into _diddle_. + +Diddle ([live instance](https://diddle.jan.systems/), [Github](https://github.com/jantuomi/diddle)) is a minimalist tool that focuses on fast load times, accessibility and pragmatism. The feature set is based on my own personal requirements. It works great for quickly filling out a poll on mobile. + +**Note**: The instance hosted on my domain might go down any second. Use it at your own discretion. + +{{ fig(src="diddle_screenshot.png", alt="Diddle screenshot showing an answerable poll") }} + +The first 80% of the project was done in two evenings. The last 80% was done during the next week. The tech stack is the _get-shit-done_ stack: **Python** + **Flask** + **PostgreSQL**. There is no required client side javascript: all client side logic is strictly for [progressive enhancement](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement). You can use "dumb" browsers like w3m or lynx to enjoy Diddle just fine. + +Check out the README on Github for more info. diff --git a/content/posts/eurobsdcon-2025-conf-notes.md b/content/posts/eurobsdcon-2025-conf-notes.md deleted file mode 100644 index f10c781..0000000 --- a/content/posts/eurobsdcon-2025-conf-notes.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: "EuroBSDCon 2025: conference notes" -date: 2025-10-17 -extra: - kind: note ---- - -EuroBSDCon is one of the events organized under the BSD community umbrella, focusing on all things related to and descending from 4.4 Berkeley Software Distribution. This year's event was held between September 25th and 28th in Zagreb, Croatia, but the city and country change every year. - -My event experience consisted of two days of "trainings", sometimes also referred to as labs, and two days of conference proper. In addition to these, there were also dev summits and smaller "conference-in-a-conference" kind of deals related to some BSD subsystems like `bhyve`, but those were not relevant to me so I skipped them outright. - -The event was held at the Faculty of Electrical Engineering and Computing (University of Zagreb). The venue was nostalgic in a way since it reminded me a lot of the building where I started my studies in Aalto University. Functional. - -{{ fig(src="/files/eurobsdcon_2025_hallway.jpeg", alt="A photo of a stairway in the conference venue") }} - -Recordings from the presentation rooms can be found on [Youtube](https://www.youtube.com/playlist?list=PLskKNopggjc6bnhXOX5MQbaPKEvohzjYH). You might have to check the talk schedule to find the timestamp of a given talk. - -## Kernel deep-dive - -I attended a two day lab by Prof. Kirk McKusick, who is a well known figure in the BSD world, having worked on core operating system components in the formative years of the BSD lineage. I really enjoyed his relaxed but still intensive teaching style. The lab, or maybe _interactive lecture_ would be more fitting, was an introduction to the FreeBSD kernel subsystems, explaining how things like I/O, scheduling, filesystems and networking work in the kernel. - -> Note that the FreeBSD kernel is not the same as the Linux kernel, or the other \*BSD kernels either for that matter. It is FreeBSD exclusive, but it shares history with other systems that descend from 4.4BSD, which is the common ancestor for many Unix-like OSs. - -You see, I'm not a huge kernel guy (at least not yet) so I was a bit worried that the lab content would go over my head. What happened though surprised me: I understood something like 90% of the material. Apparently I had the necessary prerequisite knowledge after all, or maybe Kirk was just so good at teaching. Maybe both. - -{{ fig(src="/files/eurobsdcon_2025_binders.jpeg", alt="Two spiral notebooks of lecture notes, one for each day") }} - -## Favorite talks - -There was a healthy range of themes in the talk schedule. Some were straightforward demos of recent development efforts, some were about history (mostly 1970–80s, the childhood years of the BSD project). Some war stories as well, explaining how the speaker et al. dealt with some hindrance. There were also some, I would say _not so BSD-related_, talks about things like data and identity ownership, federated social media, freedom. There is a bunch of overlap between BSD enthusiasts and digital freedom enthusiasts so it was only fitting. - -Here's my top 3, based on overall vibes. - -### _Lessons learned Open Sourcing the UK's Covid Tracing App_, by Terence Eden - -Terence was the third in line in the Saturday's opening keynote schedule. Terence was one of the key engineers behind the open source Covid tracing app that the UK developed and used. The keynote handled themes of public relations, talking about software licenses to lawyers, protecting privacy of developers from the wrath of the public, successful platform launches and shutdowns... a lot of stuff delivered with great pacing and enthusiasm. - -Timestamped link to this talk: [Youtube](https://www.youtube.com/live/qdEMmM5g27M?t=1221) - -### _Enhancing Unix Education through Chaos Engineering and Gamification using FreeBSD_, by Benedict Reuschling, Andreas Kirschner - -Benedict and Andreas had noticed that their students at Hochschule Darmstadt were not very proficient when it came to administering a UNIX system and debugging issues on it. They devised a platform where their students use exercise environments (with root access) and solve problems like DNS problems against the clock. The fastest student teams get winning points on a leaderboard. - -The talk format was a mix of a war story and tech demo: they explained their pedagogical conundrum and walked the viewers through their solution, which was based on FreeBSD and liberal use of jails. - -Timestamped link to this talk: [Youtube](https://www.youtube.com/live/FgtTVzYFEF0?t=23860) - -### _AI slop attacks on the curl project_, by Daniel Stenberg - -Daniel is the main developer in the `curl` project. In his Sunday keynote he explained how the project is being pestered by AI generated, low effort security issue reports that take up a lot of contributor time to review. Why not just block those people outright? Daniel argues that they take all reports indicating a critical vulnerability seriously; they can not allow to mistakenly disregard a valid report. - -Daniel is an entertaining speaker with big responsibility in the open source world. - -Sadly, the talk seems to not be recorded on Youtube. - -## Community - -I was curious to see what the people are like. I knew that BSD is a pretty niche thing so I was afraid the community might be hard to get into, but I was happy to notice that everyone that I talked to seemed very welcoming and excited to share. - -I noticed that there was very little "hierarchy" at the event. Speakers, sponsors and attendees were all mingling together at lunches and at social events. I didn't really see signs of cliques or circles that didn't accommodate newcomers. - -Since the event, I have familiarised myself with BSD community channels such as the [FreeBSD IRC channels](https://wiki.freebsd.org/IRC/Channels) on Libera.Chat and the various forums of [BSD Cafe](https://wiki.bsd.cafe/), hosted by Stefano Marinelli, who was also speaking at the conference. - -{{ fig(src="/files/eurobsdcon_2025_group.jpeg", alt="A group photo was taken on the final day") }} - -## There and back again, and the touristy bits - -There were no direct flights from Helsinki to Zagreb, so I had to layover in Germany both on the way there and on the way back. Leaving Finland, the departure time was gnarly: around five in the morning. Good thing I can sleep in economy. I had plenty of time to change planes, and got to the destination without a hitch. - -I stayed in B&B Boutique Casablanca, which was a nice bed & breakfast place with friendly staff. - -Traditional & local foods were my primary target when looking for restaurants. My top picks: - -- **ćevapi** at _Plac_ ([Tripadvisor](https://www.tripadvisor.com/Restaurant_Review-g294454-d7075337-Reviews-Plac-Zagreb_Central_Croatia.html)), pictured below -- **štrukli** at _La Štruk_ ([Website](https://www.lastruk.com/)) - -{{ fig(src="/files/eurobsdcon_2025_cevapi.jpeg", alt="A serving of ćevapi with cream cheese and paprika spread") }} - -The return trip was more eventful. The plane didn't start boarding until it was more than an hour late. We were never told the reason. That delay caused me to miss my connecting flight 😑 - -I was rerouted via Frankfurt which turned my nice "get home for dinner" schedule into a gruesome "you're home sometime between midnight and 2 AM" trek. Luckily I got a seat on both of the rerouted flights (that was not a given). I was home after 1 AM. - -I have then learned that there would have been a very nice direct route from Finland to Ljubljana, which lies just across the Croatian border, accompanied by a bus route that would have taken me from city to city in a couple of hours. Now I know. - -## The next event - -...will be held in Brussels, Belgium. It's closer to Finland (👍) but I've heard that it's kind of a dull city to visit. Whether that's true or not, I don't know really, never been there before. But I'd prefer going a bit farther away from my home to escape the weather 😅 - -[EuroBSDCon 2026 website](https://2026.eurobsdcon.org/) diff --git a/content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_binders.jpeg b/content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_binders.jpeg new file mode 100644 index 0000000..ee02077 Binary files /dev/null and b/content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_binders.jpeg differ diff --git a/content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_cevapi.jpeg b/content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_cevapi.jpeg new file mode 100644 index 0000000..67595b4 Binary files /dev/null and b/content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_cevapi.jpeg differ diff --git a/content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_group.jpeg b/content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_group.jpeg new file mode 100644 index 0000000..b94c739 Binary files /dev/null and b/content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_group.jpeg differ diff --git a/content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_hallway.jpeg b/content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_hallway.jpeg new file mode 100644 index 0000000..f15217a Binary files /dev/null and b/content/posts/eurobsdcon-2025-conf-notes/eurobsdcon_2025_hallway.jpeg differ diff --git a/content/posts/eurobsdcon-2025-conf-notes/index.md b/content/posts/eurobsdcon-2025-conf-notes/index.md new file mode 100644 index 0000000..33a0f7d --- /dev/null +++ b/content/posts/eurobsdcon-2025-conf-notes/index.md @@ -0,0 +1,89 @@ +--- +title: "EuroBSDCon 2025: conference notes" +date: 2025-10-17 +extra: + kind: note +--- + +EuroBSDCon is one of the events organized under the BSD community umbrella, focusing on all things related to and descending from 4.4 Berkeley Software Distribution. This year's event was held between September 25th and 28th in Zagreb, Croatia, but the city and country change every year. + +My event experience consisted of two days of "trainings", sometimes also referred to as labs, and two days of conference proper. In addition to these, there were also dev summits and smaller "conference-in-a-conference" kind of deals related to some BSD subsystems like `bhyve`, but those were not relevant to me so I skipped them outright. + +The event was held at the Faculty of Electrical Engineering and Computing (University of Zagreb). The venue was nostalgic in a way since it reminded me a lot of the building where I started my studies in Aalto University. Functional. + +{{ fig(src="eurobsdcon_2025_hallway.jpeg", alt="A photo of a stairway in the conference venue") }} + +Recordings from the presentation rooms can be found on [Youtube](https://www.youtube.com/playlist?list=PLskKNopggjc6bnhXOX5MQbaPKEvohzjYH). You might have to check the talk schedule to find the timestamp of a given talk. + +## Kernel deep-dive + +I attended a two day lab by Prof. Kirk McKusick, who is a well known figure in the BSD world, having worked on core operating system components in the formative years of the BSD lineage. I really enjoyed his relaxed but still intensive teaching style. The lab, or maybe _interactive lecture_ would be more fitting, was an introduction to the FreeBSD kernel subsystems, explaining how things like I/O, scheduling, filesystems and networking work in the kernel. + +> Note that the FreeBSD kernel is not the same as the Linux kernel, or the other \*BSD kernels either for that matter. It is FreeBSD exclusive, but it shares history with other systems that descend from 4.4BSD, which is the common ancestor for many Unix-like OSs. + +You see, I'm not a huge kernel guy (at least not yet) so I was a bit worried that the lab content would go over my head. What happened though surprised me: I understood something like 90% of the material. Apparently I had the necessary prerequisite knowledge after all, or maybe Kirk was just so good at teaching. Maybe both. + +{{ fig(src="eurobsdcon_2025_binders.jpeg", alt="Two spiral notebooks of lecture notes, one for each day") }} + +## Favorite talks + +There was a healthy range of themes in the talk schedule. Some were straightforward demos of recent development efforts, some were about history (mostly 1970–80s, the childhood years of the BSD project). Some war stories as well, explaining how the speaker et al. dealt with some hindrance. There were also some, I would say _not so BSD-related_, talks about things like data and identity ownership, federated social media, freedom. There is a bunch of overlap between BSD enthusiasts and digital freedom enthusiasts so it was only fitting. + +Here's my top 3, based on overall vibes. + +### _Lessons learned Open Sourcing the UK's Covid Tracing App_, by Terence Eden + +Terence was the third in line in the Saturday's opening keynote schedule. Terence was one of the key engineers behind the open source Covid tracing app that the UK developed and used. The keynote handled themes of public relations, talking about software licenses to lawyers, protecting privacy of developers from the wrath of the public, successful platform launches and shutdowns... a lot of stuff delivered with great pacing and enthusiasm. + +Timestamped link to this talk: [Youtube](https://www.youtube.com/live/qdEMmM5g27M?t=1221) + +### _Enhancing Unix Education through Chaos Engineering and Gamification using FreeBSD_, by Benedict Reuschling, Andreas Kirschner + +Benedict and Andreas had noticed that their students at Hochschule Darmstadt were not very proficient when it came to administering a UNIX system and debugging issues on it. They devised a platform where their students use exercise environments (with root access) and solve problems like DNS problems against the clock. The fastest student teams get winning points on a leaderboard. + +The talk format was a mix of a war story and tech demo: they explained their pedagogical conundrum and walked the viewers through their solution, which was based on FreeBSD and liberal use of jails. + +Timestamped link to this talk: [Youtube](https://www.youtube.com/live/FgtTVzYFEF0?t=23860) + +### _AI slop attacks on the curl project_, by Daniel Stenberg + +Daniel is the main developer in the `curl` project. In his Sunday keynote he explained how the project is being pestered by AI generated, low effort security issue reports that take up a lot of contributor time to review. Why not just block those people outright? Daniel argues that they take all reports indicating a critical vulnerability seriously; they can not allow to mistakenly disregard a valid report. + +Daniel is an entertaining speaker with big responsibility in the open source world. + +Sadly, the talk seems to not be recorded on Youtube. + +## Community + +I was curious to see what the people are like. I knew that BSD is a pretty niche thing so I was afraid the community might be hard to get into, but I was happy to notice that everyone that I talked to seemed very welcoming and excited to share. + +I noticed that there was very little "hierarchy" at the event. Speakers, sponsors and attendees were all mingling together at lunches and at social events. I didn't really see signs of cliques or circles that didn't accommodate newcomers. + +Since the event, I have familiarised myself with BSD community channels such as the [FreeBSD IRC channels](https://wiki.freebsd.org/IRC/Channels) on Libera.Chat and the various forums of [BSD Cafe](https://wiki.bsd.cafe/), hosted by Stefano Marinelli, who was also speaking at the conference. + +{{ fig(src="eurobsdcon_2025_group.jpeg", alt="A group photo was taken on the final day") }} + +## There and back again, and the touristy bits + +There were no direct flights from Helsinki to Zagreb, so I had to layover in Germany both on the way there and on the way back. Leaving Finland, the departure time was gnarly: around five in the morning. Good thing I can sleep in economy. I had plenty of time to change planes, and got to the destination without a hitch. + +I stayed in B&B Boutique Casablanca, which was a nice bed & breakfast place with friendly staff. + +Traditional & local foods were my primary target when looking for restaurants. My top picks: + +- **ćevapi** at _Plac_ ([Tripadvisor](https://www.tripadvisor.com/Restaurant_Review-g294454-d7075337-Reviews-Plac-Zagreb_Central_Croatia.html)), pictured below +- **štrukli** at _La Štruk_ ([Website](https://www.lastruk.com/)) + +{{ fig(src="eurobsdcon_2025_cevapi.jpeg", alt="A serving of ćevapi with cream cheese and paprika spread") }} + +The return trip was more eventful. The plane didn't start boarding until it was more than an hour late. We were never told the reason. That delay caused me to miss my connecting flight 😑 + +I was rerouted via Frankfurt which turned my nice "get home for dinner" schedule into a gruesome "you're home sometime between midnight and 2 AM" trek. Luckily I got a seat on both of the rerouted flights (that was not a given). I was home after 1 AM. + +I have then learned that there would have been a very nice direct route from Finland to Ljubljana, which lies just across the Croatian border, accompanied by a bus route that would have taken me from city to city in a couple of hours. Now I know. + +## The next event + +...will be held in Brussels, Belgium. It's closer to Finland (👍) but I've heard that it's kind of a dull city to visit. Whether that's true or not, I don't know really, never been there before. But I'd prefer going a bit farther away from my home to escape the weather 😅 + +[EuroBSDCon 2026 website](https://2026.eurobsdcon.org/) diff --git a/content/posts/home-server-part-1.md b/content/posts/home-server-part-1.md deleted file mode 100644 index 28bfbb4..0000000 --- a/content/posts/home-server-part-1.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: "A home server journey, part 1: Motivation" -date: 2025-06-30 -description: | - This is the first post in a blog series chronicling my progress with designing and setting up a new, physical FreeBSD home server. -extra: - kind: note ---- - -This is the first post in a blog series chronicling my progress with designing and setting up a new, physical FreeBSD home server. I'm guessing this will become at least a three-parter, but that depends on how things actually go, and how in-depth I happen to write. This first part is about my motivations and requirements, whereas the latter ones will be more technical-deepdive-like. - -{{ toc() }} - -{{ fig(src="/files/aliexpress_minipc.png", alt="A promotional image portraying the mini-PC I ended up getting") }} - -## I need a place to run code and store files - -I have pretty simple requirements for a server. I need to run a bunch of services, most of which are Node.js or Python apps, and serve some static websites and files. These are primarily personal applications: tracking finances, or keeping track of house chores, but also hobby projects that I host and expose to the world. - -I also need to store files somewhere, like everyone that partakes in the modern digital society. There isn't that much data to store, really. I don't take that many photos or videos, which tend to be the main driver for purchasing more cloud storage, but I have some Ableton project files (music production) that take up some space. Currently all my project files fit in a couple dozen gigabytes. I store them alongside my documents in Google Drive, using a real-time Drive sync app. This does not include the audio samples and recordings in my projects: I would have to buy a restrictively expensive plan to store those in Drive. - -I have a trusty Ubuntu server, chugging away in some rack in a DigitalOcean datacenter in Amsterdam. Even though DigitalOcean pricing is pretty reasonable for individuals in general, my monthly price tag is around ~35€, after taxes. That sum is based on the cost of running a medium sized x86-64 instance and storing some backup snapshots from that machine. Times twelve, that comes to around 420€ per year. To me, that is a sizeable amount of money. - -{{ fig(src="/files/do-june-billing.png", alt="DigitalOcean is charging $36.14 this month") }} - -> 🤔 I would like to run a smaller instance, but I needed a certain level of RAM to reliably run Obsidian Sync. For whatever reason, less memory would have the app crash intermittently. - -Having upgraded to instance to the current size, it is hard to downscale back to a smaller machine. It is possible, of course. But instead of doing that, I started to consider an alternative: maybe I could save some coins and get some hardware of my own, like in the prehistoric times, before cloud services became the de-facto way to run anything. With one year's cloud costs, I could surely get a capable small machine. - -{{ fig(src="/files/old-man-yells-at-cloud.png", alt="Old man yells at Cloud (FFVII)") }} - -## Ownership and control - -Money is not the only motivator. I dislike the idea of having the continuity of my digital presence rely on American / multinational corporations that have no real responsibility when it comes to ensuring my files stay intact, containers running and website up. Google could ban my account without batting an eyelid, which would directly make me lose access to my collection of personal photos, important documents, and various other files I prefer not lose. DigitalOcean could flag my server for suspicious activity. - -All this isn't very likely, but it still happens. And even if it didn't, I don't like having a soulless, corporate entity being the arbitrator on whether I can access my own digital life or not. I would prefer to have the probability of an account-frozen catastrophe be exactly zero instead of 0.1%. - -> 🤔 In terms of cloud provider trustworthiness, I think DigitalOcean is pretty high up in the rankings. I haven't seen much ire against them.🤔 - -I could provide these capabilities to myself, by managing my own hardware and networking. I could set up a NAS (network attached storage) box for the files, and run the services locally on either the same machine or some other hardware. It would have to be publicly accessible (Internet), just like my DigitalOcean VPS. It would have to provide _at least_ the same guarantees as the status quo: periodic restorable backups, redundant storage and at-rest encryption for stored files. - -> As an alternative, I could move my stuff to a European, maybe even Finnish, company. There are some [shared hosting](https://en.wikipedia.org/wiki/Shared_web_hosting_service) providers that exist. I don't really consider this to be that good of an option. I feel that if I'm moving out of the public cloud, I might as well go all the way. - -To replace something as generally trusted and widely used as Google Drive requires some proper thinking. I haven't previously set up any redundant disk storage. My systems have never followed the [3-2-1 backup rule](https://en.wikipedia.org/wiki/Backup#3-2-1_Backup_Rule). - -{{ fig(src="/files/3-2-1-Backup-Rule.png", alt="Maintain at least 3 copies of your data, keep 2 copies stored at separate locations, store at least 1 copy at an off-site location. Source: msp360.com") }} - -Reaching for full ownership and control is not solely an objective aim. It is in part psychological, an attempt to get back control in a world of weakening privacy and walled content gardens. It is driven by emotion. And this is completely fine: humans are allowed to be motivated by emotion, especially when it comes to personal, hobby-adjacent things. To claim otherwise would be dishonest. - -## Physical electronics are fun, tinkering is fun - -There is an inherent value in physical things. People collect music on CDs, cassette tapes, and vinyls. Playing games on real hardware is seen differently from emulation. A computer running in my home is "more real" than a resource-sharing virtual machine in some datacenter. - -It is nice to own, instead of rent. It is nice to not be bound by a contract, or a service agreement. Having fewer dependencies, legal or technical, is often favorable. - -I can pick out the components and design the infrastructure for my system. I know the moving parts, I know that if something fails, one of the cogs in the machine has stopped turning. I then replace the cog. There is no mystery, at least in an [unknown-unknowns](https://en.wikipedia.org/wiki/There_are_unknown_unknowns) kind of way. - -As long as things are not that serious, maintaining and administrating physical systems can be pretty fun. - -## Simplicity begets reliability - -Physical components are one thing, software is another. I have been running Ubuntu on the VPS for a long time, but I can think of multiple reasons to reconsider that choice. - -When I picked Ubuntu years ago, I didn't know what kind of programs I would be running on the machine. I opted for a Linux distribution that is well supported and offers relatively recent versions of software. I was also uncertain about whether or not I would need to run graphical software. Ubuntu ships with `snap` and `flatpak` , both of which are used to run desktop apps. It is now clear to me that I don't need any of this; stable server software is all I need. - -I am inspired by simplicity. I feel that systems are often improved by removing, not adding. - -I don't understand what is going on in a Ubuntu installation. There are so many components that interact, it's hard to make sense of what affects what. There are sediment layers of Linux history in there, with some Canonical-added goodness in between. To be fair, I don't think I understand the inner workings of any Linux distribution, for that matter. - -A friend had recently set up a bunch of machines using FreeBSD. The elegance of simplicity lures me in. FreeBSD is well respected when it comes to running stable server software. The system boots up with just a couple of processes running in `top`. The fantastic [FreeBSD handbook](https://docs.freebsd.org/en/books/handbook/) and supplementary reading by [Michael W. Lucas](https://mwl.io/nonfiction/os) directly teach what each file under `/etc/` does. - -I did some more reading as well as some experimentation with a FreeBSD virtual machine. It quickly became clear that this should be the way forward. I am excited to try out new, but at the same time respected and old, technology. - -FreeBSD is different. A familiar, but still strange system is fascinating. I have only worked with Linux systems before, so many things are as I expect them to be, while similarly many surprise me. - -## To be continued - -In the next part we'll dive into technical good stuff: setting up the machine and installing FreeBSD. diff --git a/content/posts/home-server-part-1/3-2-1-Backup-Rule.png b/content/posts/home-server-part-1/3-2-1-Backup-Rule.png new file mode 100644 index 0000000..ed6b675 Binary files /dev/null and b/content/posts/home-server-part-1/3-2-1-Backup-Rule.png differ diff --git a/content/posts/home-server-part-1/aliexpress_minipc.png b/content/posts/home-server-part-1/aliexpress_minipc.png new file mode 100644 index 0000000..0cb57a4 Binary files /dev/null and b/content/posts/home-server-part-1/aliexpress_minipc.png differ diff --git a/content/posts/home-server-part-1/do-june-billing.png b/content/posts/home-server-part-1/do-june-billing.png new file mode 100644 index 0000000..a38f71c Binary files /dev/null and b/content/posts/home-server-part-1/do-june-billing.png differ diff --git a/content/posts/home-server-part-1/index.md b/content/posts/home-server-part-1/index.md new file mode 100644 index 0000000..6d859cc --- /dev/null +++ b/content/posts/home-server-part-1/index.md @@ -0,0 +1,78 @@ +--- +title: "A home server journey, part 1: Motivation" +date: 2025-06-30 +description: | + This is the first post in a blog series chronicling my progress with designing and setting up a new, physical FreeBSD home server. +extra: + kind: note +--- + +This is the first post in a blog series chronicling my progress with designing and setting up a new, physical FreeBSD home server. I'm guessing this will become at least a three-parter, but that depends on how things actually go, and how in-depth I happen to write. This first part is about my motivations and requirements, whereas the latter ones will be more technical-deepdive-like. + +{{ toc() }} + +{{ fig(src="aliexpress_minipc.png", alt="A promotional image portraying the mini-PC I ended up getting") }} + +## I need a place to run code and store files + +I have pretty simple requirements for a server. I need to run a bunch of services, most of which are Node.js or Python apps, and serve some static websites and files. These are primarily personal applications: tracking finances, or keeping track of house chores, but also hobby projects that I host and expose to the world. + +I also need to store files somewhere, like everyone that partakes in the modern digital society. There isn't that much data to store, really. I don't take that many photos or videos, which tend to be the main driver for purchasing more cloud storage, but I have some Ableton project files (music production) that take up some space. Currently all my project files fit in a couple dozen gigabytes. I store them alongside my documents in Google Drive, using a real-time Drive sync app. This does not include the audio samples and recordings in my projects: I would have to buy a restrictively expensive plan to store those in Drive. + +I have a trusty Ubuntu server, chugging away in some rack in a DigitalOcean datacenter in Amsterdam. Even though DigitalOcean pricing is pretty reasonable for individuals in general, my monthly price tag is around ~35€, after taxes. That sum is based on the cost of running a medium sized x86-64 instance and storing some backup snapshots from that machine. Times twelve, that comes to around 420€ per year. To me, that is a sizeable amount of money. + +{{ fig(src="do-june-billing.png", alt="DigitalOcean is charging $36.14 this month") }} + +> 🤔 I would like to run a smaller instance, but I needed a certain level of RAM to reliably run Obsidian Sync. For whatever reason, less memory would have the app crash intermittently. + +Having upgraded to instance to the current size, it is hard to downscale back to a smaller machine. It is possible, of course. But instead of doing that, I started to consider an alternative: maybe I could save some coins and get some hardware of my own, like in the prehistoric times, before cloud services became the de-facto way to run anything. With one year's cloud costs, I could surely get a capable small machine. + +{{ fig(src="old-man-yells-at-cloud.png", alt="Old man yells at Cloud (FFVII)") }} + +## Ownership and control + +Money is not the only motivator. I dislike the idea of having the continuity of my digital presence rely on American / multinational corporations that have no real responsibility when it comes to ensuring my files stay intact, containers running and website up. Google could ban my account without batting an eyelid, which would directly make me lose access to my collection of personal photos, important documents, and various other files I prefer not lose. DigitalOcean could flag my server for suspicious activity. + +All this isn't very likely, but it still happens. And even if it didn't, I don't like having a soulless, corporate entity being the arbitrator on whether I can access my own digital life or not. I would prefer to have the probability of an account-frozen catastrophe be exactly zero instead of 0.1%. + +> 🤔 In terms of cloud provider trustworthiness, I think DigitalOcean is pretty high up in the rankings. I haven't seen much ire against them.🤔 + +I could provide these capabilities to myself, by managing my own hardware and networking. I could set up a NAS (network attached storage) box for the files, and run the services locally on either the same machine or some other hardware. It would have to be publicly accessible (Internet), just like my DigitalOcean VPS. It would have to provide _at least_ the same guarantees as the status quo: periodic restorable backups, redundant storage and at-rest encryption for stored files. + +> As an alternative, I could move my stuff to a European, maybe even Finnish, company. There are some [shared hosting](https://en.wikipedia.org/wiki/Shared_web_hosting_service) providers that exist. I don't really consider this to be that good of an option. I feel that if I'm moving out of the public cloud, I might as well go all the way. + +To replace something as generally trusted and widely used as Google Drive requires some proper thinking. I haven't previously set up any redundant disk storage. My systems have never followed the [3-2-1 backup rule](https://en.wikipedia.org/wiki/Backup#3-2-1_Backup_Rule). + +{{ fig(src="3-2-1-Backup-Rule.png", alt="Maintain at least 3 copies of your data, keep 2 copies stored at separate locations, store at least 1 copy at an off-site location. Source: msp360.com") }} + +Reaching for full ownership and control is not solely an objective aim. It is in part psychological, an attempt to get back control in a world of weakening privacy and walled content gardens. It is driven by emotion. And this is completely fine: humans are allowed to be motivated by emotion, especially when it comes to personal, hobby-adjacent things. To claim otherwise would be dishonest. + +## Physical electronics are fun, tinkering is fun + +There is an inherent value in physical things. People collect music on CDs, cassette tapes, and vinyls. Playing games on real hardware is seen differently from emulation. A computer running in my home is "more real" than a resource-sharing virtual machine in some datacenter. + +It is nice to own, instead of rent. It is nice to not be bound by a contract, or a service agreement. Having fewer dependencies, legal or technical, is often favorable. + +I can pick out the components and design the infrastructure for my system. I know the moving parts, I know that if something fails, one of the cogs in the machine has stopped turning. I then replace the cog. There is no mystery, at least in an [unknown-unknowns](https://en.wikipedia.org/wiki/There_are_unknown_unknowns) kind of way. + +As long as things are not that serious, maintaining and administrating physical systems can be pretty fun. + +## Simplicity begets reliability + +Physical components are one thing, software is another. I have been running Ubuntu on the VPS for a long time, but I can think of multiple reasons to reconsider that choice. + +When I picked Ubuntu years ago, I didn't know what kind of programs I would be running on the machine. I opted for a Linux distribution that is well supported and offers relatively recent versions of software. I was also uncertain about whether or not I would need to run graphical software. Ubuntu ships with `snap` and `flatpak` , both of which are used to run desktop apps. It is now clear to me that I don't need any of this; stable server software is all I need. + +I am inspired by simplicity. I feel that systems are often improved by removing, not adding. + +I don't understand what is going on in a Ubuntu installation. There are so many components that interact, it's hard to make sense of what affects what. There are sediment layers of Linux history in there, with some Canonical-added goodness in between. To be fair, I don't think I understand the inner workings of any Linux distribution, for that matter. + +A friend had recently set up a bunch of machines using FreeBSD. The elegance of simplicity lures me in. FreeBSD is well respected when it comes to running stable server software. The system boots up with just a couple of processes running in `top`. The fantastic [FreeBSD handbook](https://docs.freebsd.org/en/books/handbook/) and supplementary reading by [Michael W. Lucas](https://mwl.io/nonfiction/os) directly teach what each file under `/etc/` does. + +I did some more reading as well as some experimentation with a FreeBSD virtual machine. It quickly became clear that this should be the way forward. I am excited to try out new, but at the same time respected and old, technology. + +FreeBSD is different. A familiar, but still strange system is fascinating. I have only worked with Linux systems before, so many things are as I expect them to be, while similarly many surprise me. + +## To be continued + +In the next part we'll dive into technical good stuff: setting up the machine and installing FreeBSD. diff --git a/content/posts/home-server-part-1/old-man-yells-at-cloud.png b/content/posts/home-server-part-1/old-man-yells-at-cloud.png new file mode 100644 index 0000000..bf6a0f3 Binary files /dev/null and b/content/posts/home-server-part-1/old-man-yells-at-cloud.png differ diff --git a/content/posts/home-server-part-2.md b/content/posts/home-server-part-2.md deleted file mode 100644 index 3030d62..0000000 --- a/content/posts/home-server-part-2.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: "A home server journey, part 2: Hardware" -date: 2025-10-04 -description: | - This is the second post in a blog series chronicling my progress with designing and setting up a new, physical FreeBSD home server. -extra: - kind: note ---- - -
“My first impulse, when presented with any spanking-new piece of computer hardware, is to imagine how it will look in ten years’ time, gathering dust under a card table in a thrift shop.” -― William Gibson, Distrust That Particular Flavor -
-
- -This is the second post in a blog series chronicling my progress with designing and setting up a new, physical FreeBSD home server. Last time we went over my motivations, and this time we're looking at the physical hardware. - -Check out episode [1](/posts/home-server-part-1). - -{{ toc() }} - -## Budget specs - -My yearly cost in the public cloud is around 420€. It feels reasonable for a project of this caliber that a year’s expenses could buy a capable minicomputer. - -What is a capable minicomputer then, you may ask. Well, my needs are pretty straightforward: - - - - - - - - - - - - - -
Qualitative requirements
UsefulnessCan run a range of small to medium load web services without a hitch
TrustworthinessData is durable, disk failures are not catastrophic, I can sleep at night
ExpandabilityCan add more terabytes in the future
Quantitative requirements
CPULow power, economical, can run FreeBSD.
MemoryWon’t OOM swap in day-to-day operation, ZFS is happy
Disk I/OI don’t really care, no high-throughput required. As long as it’s not especially bad (i.e. HDD-level bad).
Disk spaceSlots for multiple SSDs (RAID). Enough space to hold important files and some media with redundancy. No need for data hoarding.
Network2 interfaces (private and public networks), Gigabit ethernet. No need for wireless.
AnnoyanceLow noise, low temps, sleek form factor
- -With this list of requirements, I handwaved some models and numbers: - -- CPU: Intel N series ⭐️ -- Memory: 16GB -- Disk space: 2TB (usable) - -> ⭐️ Intel N series processors, formally known as [Alder Lake-N](https://en.wikipedia.org/wiki/Alder_Lake#Alder_Lake-N) and [Twin Lake-N](https://en.wikipedia.org/wiki/Alder_Lake#Twin_lake-N), are affordable processors designed to be primarily used in mobile devices, lower end laptops (think Chromebooks) and small workstations. Some models, such as the N100, N150, N200 and N250, have thermal power ratings as low as 6W, making them popular in the passively-cooled, quasi-embedded design space: routers, NAS's, and the like. - -I got the idea for an Intel N series chip from a friend who has succesfully set up computing cluster from a bunch of small machines with those chips. They seemed to be just what I was looking for. - -With these, I sail off towards the east (AliExpress). - -By the way, I also looked at ARM and RISC-V chips for this. I figured that if Apple Silicon can work as well as it does while being based on ARM, what's stopping me from reaping the same benefits, at least in part? ARM has T1 support from FreeBSD. - -Turns out that there simply aren't any reasonably priced machines based on chips comparable to e.g. the Intel N150. Everything's either designed for mobile devices or just prohibitively expensive. Maybe there is no market yet for small non-x64 computers? - -## Sourcing the silicon - -AliExpress, an online retailer based in China, is nice since they have a huge variety of devices at prices that would never be profitable if sold in a western shop. I would prefer to buy European in this current political atmosphere, but I'm working off a budget, and limiting my options to reputable and ethical vendors would force me to relax my requirements a lot or stop the project in its tracks altogether. - -{{ fig(src="/files/aliexpress_minipc_results.png", alt='Some of the results of a "mini pc" search query') }} - -I'm happy to notice that there is a varied selection of devices at the ~200€ price point. Some are designed to be network devices, with a bunch of physical interfaces and limited storage options, while some are clearly NAS oriented, with SATA 3.5" drive bays capable of housing two or four disks, most commonly. - -I'm looking for something in the middle ground: I need two physical interfaces (a property of router-likes) but I also need storage, preferably of the solid state variety (a property of NAS-likes). - -**Conclusion**: I'm going with this one (possibly stale link warning): [Topton Pocket Mini PC](https://www.aliexpress.com/item/1005007905020917.html). With some mystery promotions applied, I had to only pay 162.27€, with free shipping. I also purchased 16GB of RAM (Crucial DDR5 SODIMM 4800MHz) separately, also from AliExpress. - -> AliExpress tends to have multiple layers of ‼️ LIMITED SALE ‼️ and 🤑 TOP DEAL COUPON 🤑 going on at the same time. In the mobile app they also have a bunch of connect-four-type games that can score you big AliExpress Coins©. Please continue consuming. - -{{ fig(src="/files/aliexpress_minipc.png", alt="A promotional image of the mini PC I picked, hosted here in case the product page goes poof. Please enjoy the broken English.") }} - -Regarding disks, I think I want to buy them locally, just in case there are issues with them. It's way less stressful to handle returns and such with a local vendor than with an overseas megacorp. I feel that stuff like RAM is pretty often OK even if bought from less reputable sources, but with disks I don't want to test my luck. - -**Conclusion**: I'm going to get 4 x 1 TB (double the required usable space because of mirroring) of basic NVMe drives from a computer parts shop (Gigantti) nearby. - -## Setting up hardware - -The box arrives after a bit of a wait (par for the course for the cheapest delivery option, China Airmail). Everything seems to be in order content-wise, but there is no installation manual whatsoever included. I would like one, since I need to figure out how to install the RAM stick. It seems to somehow go below the NVMe sticks, but there is no obvious mechanism for detaching the NVMe bay. - -However, with a bit of trial and error I find the correct screw to remove. The top layer comes off, revealing the RAM stick slot underneath. Very carefully I slot in the memory and push down the clamp that fixes it in place. - -With similar care I put the drive bay back in, and connect the four NVMe drives and stick on their respective thermal material stickers that conduct heat for the drives to the heatsink on top of the machine. I screw everything in place with the tiny screws that came with the machine. A magnetic screwdriver would be a godsend now! - -After a bit, everything's put together. After connecting the power cable, the machine powers on without me even touching the power switch, which is a bit surprising, but ok. I hear the POST beep. - -Success! - -## To be continued - -In the next part(s) we will be looking at installing FreeBSD for the first (and second) time, and networking. I had some – let's say curious – issues with DHCP leases from the ISP. We might also take a look at my jail setup. diff --git a/content/posts/home-server-part-2/aliexpress_minipc.png b/content/posts/home-server-part-2/aliexpress_minipc.png new file mode 100644 index 0000000..0cb57a4 Binary files /dev/null and b/content/posts/home-server-part-2/aliexpress_minipc.png differ diff --git a/content/posts/home-server-part-2/aliexpress_minipc_results.png b/content/posts/home-server-part-2/aliexpress_minipc_results.png new file mode 100644 index 0000000..9242e3e Binary files /dev/null and b/content/posts/home-server-part-2/aliexpress_minipc_results.png differ diff --git a/content/posts/home-server-part-2/index.md b/content/posts/home-server-part-2/index.md new file mode 100644 index 0000000..7cd5300 --- /dev/null +++ b/content/posts/home-server-part-2/index.md @@ -0,0 +1,91 @@ +--- +title: "A home server journey, part 2: Hardware" +date: 2025-10-04 +description: | + This is the second post in a blog series chronicling my progress with designing and setting up a new, physical FreeBSD home server. +extra: + kind: note +--- + +
“My first impulse, when presented with any spanking-new piece of computer hardware, is to imagine how it will look in ten years’ time, gathering dust under a card table in a thrift shop.” +― William Gibson, Distrust That Particular Flavor +
+
+ +This is the second post in a blog series chronicling my progress with designing and setting up a new, physical FreeBSD home server. Last time we went over my motivations, and this time we're looking at the physical hardware. + +Check out episode [1](/posts/home-server-part-1). + +{{ toc() }} + +## Budget specs + +My yearly cost in the public cloud is around 420€. It feels reasonable for a project of this caliber that a year’s expenses could buy a capable minicomputer. + +What is a capable minicomputer then, you may ask. Well, my needs are pretty straightforward: + + + + + + + + + + + + + +
Qualitative requirements
UsefulnessCan run a range of small to medium load web services without a hitch
TrustworthinessData is durable, disk failures are not catastrophic, I can sleep at night
ExpandabilityCan add more terabytes in the future
Quantitative requirements
CPULow power, economical, can run FreeBSD.
MemoryWon’t OOM swap in day-to-day operation, ZFS is happy
Disk I/OI don’t really care, no high-throughput required. As long as it’s not especially bad (i.e. HDD-level bad).
Disk spaceSlots for multiple SSDs (RAID). Enough space to hold important files and some media with redundancy. No need for data hoarding.
Network2 interfaces (private and public networks), Gigabit ethernet. No need for wireless.
AnnoyanceLow noise, low temps, sleek form factor
+ +With this list of requirements, I handwaved some models and numbers: + +- CPU: Intel N series ⭐️ +- Memory: 16GB +- Disk space: 2TB (usable) + +> ⭐️ Intel N series processors, formally known as [Alder Lake-N](https://en.wikipedia.org/wiki/Alder_Lake#Alder_Lake-N) and [Twin Lake-N](https://en.wikipedia.org/wiki/Alder_Lake#Twin_lake-N), are affordable processors designed to be primarily used in mobile devices, lower end laptops (think Chromebooks) and small workstations. Some models, such as the N100, N150, N200 and N250, have thermal power ratings as low as 6W, making them popular in the passively-cooled, quasi-embedded design space: routers, NAS's, and the like. + +I got the idea for an Intel N series chip from a friend who has succesfully set up computing cluster from a bunch of small machines with those chips. They seemed to be just what I was looking for. + +With these, I sail off towards the east (AliExpress). + +By the way, I also looked at ARM and RISC-V chips for this. I figured that if Apple Silicon can work as well as it does while being based on ARM, what's stopping me from reaping the same benefits, at least in part? ARM has T1 support from FreeBSD. + +Turns out that there simply aren't any reasonably priced machines based on chips comparable to e.g. the Intel N150. Everything's either designed for mobile devices or just prohibitively expensive. Maybe there is no market yet for small non-x64 computers? + +## Sourcing the silicon + +AliExpress, an online retailer based in China, is nice since they have a huge variety of devices at prices that would never be profitable if sold in a western shop. I would prefer to buy European in this current political atmosphere, but I'm working off a budget, and limiting my options to reputable and ethical vendors would force me to relax my requirements a lot or stop the project in its tracks altogether. + +{{ fig(src="aliexpress_minipc_results.png", alt='Some of the results of a "mini pc" search query') }} + +I'm happy to notice that there is a varied selection of devices at the ~200€ price point. Some are designed to be network devices, with a bunch of physical interfaces and limited storage options, while some are clearly NAS oriented, with SATA 3.5" drive bays capable of housing two or four disks, most commonly. + +I'm looking for something in the middle ground: I need two physical interfaces (a property of router-likes) but I also need storage, preferably of the solid state variety (a property of NAS-likes). + +**Conclusion**: I'm going with this one (possibly stale link warning): [Topton Pocket Mini PC](https://www.aliexpress.com/item/1005007905020917.html). With some mystery promotions applied, I had to only pay 162.27€, with free shipping. I also purchased 16GB of RAM (Crucial DDR5 SODIMM 4800MHz) separately, also from AliExpress. + +> AliExpress tends to have multiple layers of ‼️ LIMITED SALE ‼️ and 🤑 TOP DEAL COUPON 🤑 going on at the same time. In the mobile app they also have a bunch of connect-four-type games that can score you big AliExpress Coins©. Please continue consuming. + +{{ fig(src="aliexpress_minipc.png", alt="A promotional image of the mini PC I picked, hosted here in case the product page goes poof. Please enjoy the broken English.") }} + +Regarding disks, I think I want to buy them locally, just in case there are issues with them. It's way less stressful to handle returns and such with a local vendor than with an overseas megacorp. I feel that stuff like RAM is pretty often OK even if bought from less reputable sources, but with disks I don't want to test my luck. + +**Conclusion**: I'm going to get 4 x 1 TB (double the required usable space because of mirroring) of basic NVMe drives from a computer parts shop (Gigantti) nearby. + +## Setting up hardware + +The box arrives after a bit of a wait (par for the course for the cheapest delivery option, China Airmail). Everything seems to be in order content-wise, but there is no installation manual whatsoever included. I would like one, since I need to figure out how to install the RAM stick. It seems to somehow go below the NVMe sticks, but there is no obvious mechanism for detaching the NVMe bay. + +However, with a bit of trial and error I find the correct screw to remove. The top layer comes off, revealing the RAM stick slot underneath. Very carefully I slot in the memory and push down the clamp that fixes it in place. + +With similar care I put the drive bay back in, and connect the four NVMe drives and stick on their respective thermal material stickers that conduct heat for the drives to the heatsink on top of the machine. I screw everything in place with the tiny screws that came with the machine. A magnetic screwdriver would be a godsend now! + +After a bit, everything's put together. After connecting the power cable, the machine powers on without me even touching the power switch, which is a bit surprising, but ok. I hear the POST beep. + +Success! + +## To be continued + +In the next part(s) we will be looking at installing FreeBSD for the first (and second) time, and networking. I had some – let's say curious – issues with DHCP leases from the ISP. We might also take a look at my jail setup. diff --git a/content/posts/home-server-part-3.md b/content/posts/home-server-part-3.md deleted file mode 100644 index 456ee2a..0000000 --- a/content/posts/home-server-part-3.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "A home server journey, part 3: Installation" -date: 2025-12-23 -description: | - This is the third episode in a series where I set up a FreeBSD home server, explaining all the steps, problems and solutions along the way. This time we're installing the OS for the first time. -extra: - kind: note ---- - -This is the third episode in a series where I set up a FreeBSD home server, explaining all the steps, problems and solutions along the way. This time we're installing the OS for the first time. - -Check out episodes [1](/posts/home-server-part-1) and [2](/posts/home-server-part-2). - -{{ toc() }} - -## Installing FreeBSD - -Installation should be pretty straightforward. I'm going to go with the latest stable release installer (`14.3-RELEASE`) in the `amd64` + `memstick.iso` variety. Let's burn the installer onto a memory stick, plug it in, and was enter the install wizard. - -> Note from the future! `15.0-RELEASE` is already out, and I have recently updated to it. This post is already outdated! - -The initial idea is this: - -- ZFS, for all the automatic durability gains and easy-to-setup RAID1+0 (stripe of mirrors) -- encrypted ZFS datasets (kinda similar to partitions) for **jails**, which would contain all the actual services -- unencrypted root, so that I can reboot the machine remotely, physically unattended - -> [Jails](https://docs.freebsd.org/en/books/handbook/jails/) are a lightweight way to containerize applications. They can get a separate process space, network stack, file system, root user, among others. They use the same kernel as the host, so they are more similar to LXC or OCI containers (think Docker, but more mature and flexible) than to virtual machines, which in FreeBSD are managed with [bhyve](https://docs.freebsd.org/en/books/handbook/virtualization/#virtualization-host-bhyve). -> -> Teaser: we will be installing `bhyve` later too. - -Using the install wizard, I set up the system following my rough plan. And here we go, all up and running: - -{{ fig(src="/files/pursotin_fastfetch.png", alt="Fastfetch output showing the machine specs. Disregard the uptime (I took the screenshot way later)") }} - -### RAIDZ - -You might notice that I bought 4 x 1 TB of NVMe disks, but `fastfetch` is only showing ~2TB. That's because I set up the disks into a "RAID 1+0" configuration: - -{{ fig(src="/files/pursotin_raidz.svg", alt='A "RAID 1+0" configuration') }} - -RAID 1+0 is a combination of two RAID levels. RAID 1, or _mirror_, consumes two disks to produce one virtual disk that has the capacity of only one physical disk but can withstand the loss of either one. ZFS can automatically heal missing data in a member of a mirror by copying it over from the healthy member. RAID 0, or _stripe_, consumes two disks to produce a disk that has the capacity of the sum of its member capacities as well as double I/O speed, but fails if either member disk fails. The combination of these is a useful way to get increased speed and increased durability at the price of half your raw capacity. - -## Threat profile and encryption - -To figure out what level and what kind of at-rest encryption I need, I need to stop and think about the threat model. - -Scenario A, _online intruder_. An attacker that gains shell access can exfiltrate any data that the user has access to, since the decryption key has been activated at boot. At-rest encryption won't help here. - -Scenario B, _burglar_. An intruder grabs the machine and brings it to a place where they can inspect the disks, possibly with sophisticated recovery tools. - -- In a non-encrypted-root install, everything outside the encrypted jails is instantly accessible. Stored API keys and similar secrets leak. The administrator must take great care not to keep _anything_ of value on the unencrypted partition(s), and store everything in encrypted datasets. -- An encrypted root would be safe from this attack, assuming the cryptography used in the encryption is bulletproof. - -Scenario C, _evil maid attack_. A friend, spouse or similar tampers with the unattended physical system. Illegitimate access is blocked by requiring login and keeping the credentials in my personal vault. If the whole disk is encrypted, the worst thing the attacker can do is cause temporary harm and possibly data loss by powering off the system. If not, the attacker can do all kinds of nasty things, like booting a live environment and copying the disk contents, replacing the kernel/bootloader, installing malware etc. - -## Conclusion - -It makes sense to encrypt the whole thing. - -⚠️ But wait a minute! This is against my initial idea: - -> unencrypted root, so that I can reboot the machine remotely, physically unattended - -Encrypting the whole disk loses the ability to do unattended reboots. A bit inconvenient, but it is what it is. I'll just make sure to only reboot when I'm physically near the machine, which should be often, considering I work from home and the server is, uh, right there. - -Because of this architectural change, I ended up installing FreeBSD for a second time, now with full disk encryption. - -## System disk? - -Sometimes a separate small system disk is used in addition to a redundant array of "data disks". I decided to not pursue this setup, since then the system would not benefit from the RAIDZ redundancy and self-healing capabilities. In fact, I'd imagine that the ability to repair the OS and packages is even more important to me than repairing bulk data. - -I decided to keep the system next to the data on the disks (a "traditional" install). - -## To be continued - -In the next part(s) we will be looking at networking. I had some – let's say curious – issues with DHCP leases from the ISP. We'll also take a look at my jail setup. diff --git a/content/posts/home-server-part-3/index.md b/content/posts/home-server-part-3/index.md new file mode 100644 index 0000000..0b553ba --- /dev/null +++ b/content/posts/home-server-part-3/index.md @@ -0,0 +1,77 @@ +--- +title: "A home server journey, part 3: Installation" +date: 2025-12-23 +description: | + This is the third episode in a series where I set up a FreeBSD home server, explaining all the steps, problems and solutions along the way. This time we're installing the OS for the first time. +extra: + kind: note +--- + +This is the third episode in a series where I set up a FreeBSD home server, explaining all the steps, problems and solutions along the way. This time we're installing the OS for the first time. + +Check out episodes [1](/posts/home-server-part-1) and [2](/posts/home-server-part-2). + +{{ toc() }} + +## Installing FreeBSD + +Installation should be pretty straightforward. I'm going to go with the latest stable release installer (`14.3-RELEASE`) in the `amd64` + `memstick.iso` variety. Let's burn the installer onto a memory stick, plug it in, and was enter the install wizard. + +> Note from the future! `15.0-RELEASE` is already out, and I have recently updated to it. This post is already outdated! + +The initial idea is this: + +- ZFS, for all the automatic durability gains and easy-to-setup RAID1+0 (stripe of mirrors) +- encrypted ZFS datasets (kinda similar to partitions) for **jails**, which would contain all the actual services +- unencrypted root, so that I can reboot the machine remotely, physically unattended + +> [Jails](https://docs.freebsd.org/en/books/handbook/jails/) are a lightweight way to containerize applications. They can get a separate process space, network stack, file system, root user, among others. They use the same kernel as the host, so they are more similar to LXC or OCI containers (think Docker, but more mature and flexible) than to virtual machines, which in FreeBSD are managed with [bhyve](https://docs.freebsd.org/en/books/handbook/virtualization/#virtualization-host-bhyve). +> +> Teaser: we will be installing `bhyve` later too. + +Using the install wizard, I set up the system following my rough plan. And here we go, all up and running: + +{{ fig(src="pursotin_fastfetch.png", alt="Fastfetch output showing the machine specs. Disregard the uptime (I took the screenshot way later)") }} + +### RAIDZ + +You might notice that I bought 4 x 1 TB of NVMe disks, but `fastfetch` is only showing ~2TB. That's because I set up the disks into a "RAID 1+0" configuration: + +{{ fig(src="pursotin_raidz.svg", alt='A "RAID 1+0" configuration') }} + +RAID 1+0 is a combination of two RAID levels. RAID 1, or _mirror_, consumes two disks to produce one virtual disk that has the capacity of only one physical disk but can withstand the loss of either one. ZFS can automatically heal missing data in a member of a mirror by copying it over from the healthy member. RAID 0, or _stripe_, consumes two disks to produce a disk that has the capacity of the sum of its member capacities as well as double I/O speed, but fails if either member disk fails. The combination of these is a useful way to get increased speed and increased durability at the price of half your raw capacity. + +## Threat profile and encryption + +To figure out what level and what kind of at-rest encryption I need, I need to stop and think about the threat model. + +Scenario A, _online intruder_. An attacker that gains shell access can exfiltrate any data that the user has access to, since the decryption key has been activated at boot. At-rest encryption won't help here. + +Scenario B, _burglar_. An intruder grabs the machine and brings it to a place where they can inspect the disks, possibly with sophisticated recovery tools. + +- In a non-encrypted-root install, everything outside the encrypted jails is instantly accessible. Stored API keys and similar secrets leak. The administrator must take great care not to keep _anything_ of value on the unencrypted partition(s), and store everything in encrypted datasets. +- An encrypted root would be safe from this attack, assuming the cryptography used in the encryption is bulletproof. + +Scenario C, _evil maid attack_. A friend, spouse or similar tampers with the unattended physical system. Illegitimate access is blocked by requiring login and keeping the credentials in my personal vault. If the whole disk is encrypted, the worst thing the attacker can do is cause temporary harm and possibly data loss by powering off the system. If not, the attacker can do all kinds of nasty things, like booting a live environment and copying the disk contents, replacing the kernel/bootloader, installing malware etc. + +## Conclusion + +It makes sense to encrypt the whole thing. + +⚠️ But wait a minute! This is against my initial idea: + +> unencrypted root, so that I can reboot the machine remotely, physically unattended + +Encrypting the whole disk loses the ability to do unattended reboots. A bit inconvenient, but it is what it is. I'll just make sure to only reboot when I'm physically near the machine, which should be often, considering I work from home and the server is, uh, right there. + +Because of this architectural change, I ended up installing FreeBSD for a second time, now with full disk encryption. + +## System disk? + +Sometimes a separate small system disk is used in addition to a redundant array of "data disks". I decided to not pursue this setup, since then the system would not benefit from the RAIDZ redundancy and self-healing capabilities. In fact, I'd imagine that the ability to repair the OS and packages is even more important to me than repairing bulk data. + +I decided to keep the system next to the data on the disks (a "traditional" install). + +## To be continued + +In the next part(s) we will be looking at networking. I had some – let's say curious – issues with DHCP leases from the ISP. We'll also take a look at my jail setup. diff --git a/content/posts/home-server-part-3/pursotin_fastfetch.png b/content/posts/home-server-part-3/pursotin_fastfetch.png new file mode 100644 index 0000000..241f5e9 Binary files /dev/null and b/content/posts/home-server-part-3/pursotin_fastfetch.png differ diff --git a/content/posts/home-server-part-3/pursotin_raidz.svg b/content/posts/home-server-part-3/pursotin_raidz.svg new file mode 100644 index 0000000..d2942ac --- /dev/null +++ b/content/posts/home-server-part-3/pursotin_raidz.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/content/posts/home-server-part-4.md b/content/posts/home-server-part-4.md deleted file mode 100644 index 1eff36f..0000000 --- a/content/posts/home-server-part-4.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: "A home server journey, part 4: Network" -date: 2025-12-25 -description: | - This is the fourth episode in a series where I set up a FreeBSD home server, explaining all the steps, problems and solutions along the way. This time we're setting up the networking. -extra: - kind: note ---- - -This is the fourth episode in a series where I set up a FreeBSD home server, explaining all the steps, problems and solutions along the way. This time we're setting up the networking. - -Check out episodes [1](/posts/home-server-part-1), [2](/posts/home-server-part-2), [3](/posts/home-server-part-3). - -{{ toc() }} - -## Dual interfaces - -I already have a private network (`192.168.0.0/16`) that uses my pfSense router as its gateway. The FreeBSD server will connect to this network through ethernet interface number one (`lan0`). Packets to and from local devices go through this interface. - -The host will also be connected directly to the ISP's network using its second interface (`wan0`). This interface will get its IP using DHCP. Packets to the internet, as well as packets to public services running on the FreeBSD host go through this interface. - -{{ fig(src="/files/pursotin_network.svg", alt="A simplified diagram showing the two interfaces") }} - -A dual interface set up like this is simple in theory, but there are important nuances, e.g. regarding return traffic routing and DNS. - -## Routing - -If we send a packet out through `eth0`, we should expect return traffic to arrive on `eth0` (and vice versa). However, it is rather easy to misconfigure the system. - -Assume we have a public service, such as an `nginx` web server, which listens on the public interface. If we set up `rc.conf` naively like this: - -```sh -defaultrouter=192.168.0.1 -``` - -...the request might arrive through the public interface, but the response from the web server leaves through the private interface since we have configured the private gateway as the default. This is called _asymmetric routing_. - -This might work! Both routes lead to the internet. From the perspective of the ISP, it doesn't really matter whether the packet went through the home router or not, in this case. - -Sometimes however, this setup leads to the most vexing of networking issues. Figuring out what's wrong taught me a bunch about DHCP and layer 3 routing. - -### Routing issue \#1: ISP DHCP server and MAC addresses - -A DHCP server can keep track of clients using their MAC address. Separate physical interfaces have separate MAC addresses, so there is an obvious problem here. If an initial DHCP request broadcast leaves through one interface, and following DHCP requests (non-broadcast) leave through another interface, the DHCP server might see this as a forged packet. - -This happened to me because of the `defaultrouter` setting: - -1. The initial broadcast leaves through the `wan0` interface correctly. An IP is received. -2. When the lease is about to expire, a targeted request is sent to the now known DHCP server address. This is routed through `lan0` and `192.168.0.1`, since it's the `defaultrouter`. -3. The DHCP server sees the FreeBSD WAN MAC on first contact, and the home router MAC address on second contact. The lease is not renewed. -4. The lease expires, repeat from step 1. - -My solution? Just don't use `defaultrouter`. As part of the routine DHCP song and dance, `dhclient` adds a valid default route to the system routing table. Just use that for all internet-bound traffic. You can see the routes with `netstat -rn`: - -```sh -# netstat -rn -Routing tables - -Internet: -Destination Gateway Flags Netif Expire -default 87.92.64.1 UGS wan0 -87.92.64.0/18 link#36 U wan0 -192.168.0.0/16 link#25 U lan0 -127.0.0.1 link#57 UH lo0 -... -``` - -The `default` route was added by DHCP. - -### Routing issue \#2: DNS-level ad blocker in my router - -I run [pfBlockerNG](https://docs.netgate.com/pfsense/en/latest/packages/pfblocker.html) on my router to block ads on a DNS level (think Pi-hole). If I route traffic through the router, the return traffic is processed by this extra firewall. Some packets got dropped by pfBlockerNG and never arrived at the destination. - -This was very annoying to debug! At least I had logging on, so I could confirm what's happening pretty quickly. - -## DNS - -Nameservers are defined on a whole system basis in `/etc/resolv.conf`, and not per interface or per IP. I have a basic DNS resolver running on my home server, so I simply configured my `resolv.conf` as: - -```sh -nameserver 192.168.0.1 -``` - -### Split horizon - -Which IP should be returned from the DNS server if I query `some-public-service.jan.systems`? The private address from `192.168.0.0/16`, or a public IP reachable from the internet? - -This is called **split horizon** DNS. One approach is to configure the DNS server to respond differently based on the address of the querying host. A private network host gets the private IP, etc. - -I decided to not worry about this, and just use a separate domain, `local.jan.systems` for local addresses. This is a bit inconvenient, but I don't mind. The fewer DNS problems the better. - -### DHCP and `resolv.conf` - -By default, `dhclient` has a hook that overwrites `resolv.conf` with the DHCP-provided nameserver information. I want to always use my router as the DNS server, so I had to disable this functionality. - -On FreeBSD, there are two simple solutions: - -1. `resolvconf.conf`: a meta-config that configures the `resolvconf` tool, which is used internally by `dhclient` - -To disable `resolvconf` altogether, add this to `/etc/resolvconf.conf`: - -```sh -resolvconf=NO -``` - -Now, `resolvconf`, and transitively `dhclient`, won't overwrite your changes anymore. - -2. making `/etc/resolv.conf` immutable with a flag - -As root, you can set the file as immutable with `chflags`. Then, nothing can edit the file before the flag is removed. - -```sh -chflags schg /etc/resolv.conf -``` - -Note that if you have a non-default [`securelevel`](https://man.freebsd.org/cgi/man.cgi?securelevel), you might not be able to remove this flag. - -## Dual stack? - -For now, I'm building everything on IPv4. My ISP has no support for SLAAC which makes IPv6 somewhat non-trivial. I will most likely add IPv6 at some point, but it's not a priority. - -## To be continued - -In the next part(s) we will be looking at provisioning with Ansible. diff --git a/content/posts/home-server-part-4/index.md b/content/posts/home-server-part-4/index.md new file mode 100644 index 0000000..bb44702 --- /dev/null +++ b/content/posts/home-server-part-4/index.md @@ -0,0 +1,124 @@ +--- +title: "A home server journey, part 4: Networking" +date: 2025-12-24 +description: | + This is the fourth episode in a series where I set up a FreeBSD home server, explaining all the steps, problems and solutions along the way. This time we're looking at networking. +extra: + kind: note +--- + +This is the fourth episode in a series where I set up a FreeBSD home server, explaining all the steps, problems and solutions along the way. This time we're looking at networking. + +Check out episodes [1](/posts/home-server-part-1), [2](/posts/home-server-part-2), [3](/posts/home-server-part-3). + +{{ toc() }} + +## Dual interfaces + +I already have a private network (`192.168.0.0/16`) that uses my pfSense router as its gateway. The FreeBSD server will connect to this network through ethernet interface number one (`lan0`). Packets to and from local devices go through this interface. + +The host will also be connected directly to the ISP's network using its second interface (`wan0`). This interface will get its IP using DHCP. Packets to the internet, as well as packets to public services running on the FreeBSD host go through this interface. + +{{ fig(src="pursotin_network.svg", alt="A simplified diagram showing the two interfaces") }} + +A dual interface set up like this is simple in theory, but there are important nuances, e.g. regarding return traffic routing and DNS. + +## Routing + +If we send a packet out through `eth0`, we should expect return traffic to arrive on `eth0` (and vice versa). However, it is rather easy to misconfigure the system. + +Assume we have a public service, such as an `nginx` web server, which listens on the public interface. If we set up `rc.conf` naively like this: + +```sh +defaultrouter=192.168.0.1 +``` + +...the request might arrive through the public interface, but the response from the web server leaves through the private interface since we have configured the private gateway as the default. This is called _asymmetric routing_. + +This might work! Both routes lead to the internet. From the perspective of the ISP, it doesn't really matter whether the packet went through the home router or not, in this case. + +Sometimes however, this setup leads to the most vexing of networking issues. Figuring out what's wrong taught me a bunch about DHCP and layer 3 routing. + +### Routing issue \#1: ISP DHCP server and MAC addresses + +A DHCP server can keep track of clients using their MAC address. Separate physical interfaces have separate MAC addresses, so there is an obvious problem here. If an initial DHCP request broadcast leaves through one interface, and following DHCP requests (non-broadcast) leave through another interface, the DHCP server might see this as a forged packet. + +This happened to me because of the `defaultrouter` setting: + +1. The initial broadcast leaves through the `wan0` interface correctly. An IP is received. +2. When the lease is about to expire, a targeted request is sent to the now known DHCP server address. This is routed through `lan0` and `192.168.0.1`, since it's the `defaultrouter`. +3. The DHCP server sees the FreeBSD WAN MAC on first contact, and the home router MAC address on second contact. The lease is not renewed. +4. The lease expires, repeat from step 1. + +My solution? Just don't use `defaultrouter`. As part of the routine DHCP song and dance, `dhclient` adds a valid default route to the system routing table. Just use that for all internet-bound traffic. You can see the routes with `netstat -rn`: + +```sh +# netstat -rn +Routing tables + +Internet: +Destination Gateway Flags Netif Expire +default 87.92.64.1 UGS wan0 +87.92.64.0/18 link#36 U wan0 +192.168.0.0/16 link#25 U lan0 +127.0.0.1 link#57 UH lo0 +... +``` + +The `default` route was added by DHCP. + +### Routing issue \#2: DNS-level ad blocker in my router + +I run [pfBlockerNG](https://docs.netgate.com/pfsense/en/latest/packages/pfblocker.html) on my router to block ads on a DNS level (think Pi-hole). If I route traffic through the router, the return traffic is processed by this extra firewall. Some packets got dropped by pfBlockerNG and never arrived at the destination. + +This was very annoying to debug! At least I had logging on, so I could confirm what's happening pretty quickly. + +## DNS + +Nameservers are defined on a whole system basis in `/etc/resolv.conf`, and not per interface or per IP. I have a basic DNS resolver running on my home server, so I simply configured my `resolv.conf` as: + +```sh +nameserver 192.168.0.1 +``` + +### Split horizon + +Which IP should be returned from the DNS server if I query `some-public-service.jan.systems`? The private address from `192.168.0.0/16`, or a public IP reachable from the internet? + +This is called **split horizon** DNS. One approach is to configure the DNS server to respond differently based on the address of the querying host. A private network host gets the private IP, etc. + +I decided to not worry about this, and just use a separate domain, `local.jan.systems` for local addresses. This is a bit inconvenient, but I don't mind. The fewer DNS problems the better. + +### DHCP and `resolv.conf` + +By default, `dhclient` has a hook that overwrites `resolv.conf` with the DHCP-provided nameserver information. I want to always use my router as the DNS server, so I had to disable this functionality. + +On FreeBSD, there are two simple solutions: + +1. `resolvconf.conf`: a meta-config that configures the `resolvconf` tool, which is used internally by `dhclient` + +To disable `resolvconf` altogether, add this to `/etc/resolvconf.conf`: + +```sh +resolvconf=NO +``` + +Now, `resolvconf`, and transitively `dhclient`, won't overwrite your changes anymore. + +2. making `/etc/resolv.conf` immutable with a flag + +As root, you can set the file as immutable with `chflags`. Then, nothing can edit the file before the flag is removed. + +```sh +chflags schg /etc/resolv.conf +``` + +Note that if you have a non-default [`securelevel`](https://man.freebsd.org/cgi/man.cgi?securelevel), you might not be able to remove this flag. + +## Dual stack? + +For now, I'm building everything on IPv4. My ISP has no support for SLAAC which makes IPv6 somewhat non-trivial. I will most likely add IPv6 at some point, but it's not a priority. + +## To be continued + +In the next part(s) we will be looking at provisioning with Ansible. diff --git a/content/posts/home-server-part-4/pursotin_network.svg b/content/posts/home-server-part-4/pursotin_network.svg new file mode 100644 index 0000000..79d1dea --- /dev/null +++ b/content/posts/home-server-part-4/pursotin_network.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/content/posts/it-doesnt-mean-that.md b/content/posts/it-doesnt-mean-that.md deleted file mode 100644 index adf171f..0000000 --- a/content/posts/it-doesnt-mean-that.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: It doesn't mean that -date: 2024-03-31 -extra: - kind: note ---- - -A plain circle with a small dot in the center - -## When I learned my first programming language - -I learned about functions. - -A _function_ is a thing you can call. The function might then _return_ a value. - -## Then I learned about functional programming - -And learned that those words did not mean that at all. Or at least that was not their full, universal meaning. - -Those _functions_ were actually _procedures_. Or _subroutines_. A function should be mathematical and pure. A mapping from a type to another. - -_Returning_ was not optional. All functions return, explicitly or implicitly, since function application must be assigned a value. - -I learned new words too. - -_Functors_ are containers. _Monads_ are powered-up functors with useful computational context. - -## Now that I’m learning about category theory… - -…I’m learning that those words do not mean what I thought they meant, either. - -_Functions_ are apparently morphisms, or arrows, in the category of types. _Functors_ are not containers, they are morphisms between categories. They are also their own category. - -_Monads_ are — I haven’t gotten to monads yet. - -## I read that they have a Monad in philosophy - -And it means _god_. [¹](it-doesnt-mean-that#fn1) - ---- - -1. More or less. diff --git a/content/posts/it-doesnt-mean-that/index.md b/content/posts/it-doesnt-mean-that/index.md new file mode 100644 index 0000000..0fb2988 --- /dev/null +++ b/content/posts/it-doesnt-mean-that/index.md @@ -0,0 +1,40 @@ +--- +title: It doesn't mean that +date: 2024-05-16 +--- + +A plain circle with a small dot in the center + +## When I learned my first programming language + +I learned about functions. + +A _function_ is a thing you can call. The function might then _return_ a value. + +## Then I learned about functional programming + +And learned that those words did not mean that at all. Or at least that was not their full, universal meaning. + +Those _functions_ were actually _procedures_. Or _subroutines_. A function should be mathematical and pure. A mapping from a type to another. + +_Returning_ was not optional. All functions return, explicitly or implicitly, since function application must be assigned a value. + +I learned new words too. + +_Functors_ are containers. _Monads_ are powered-up functors with useful computational context. + +## Now that I’m learning about category theory… + +…I’m learning that those words do not mean what I thought they meant, either. + +_Functions_ are apparently morphisms, or arrows, in the category of types. _Functors_ are not containers, they are morphisms between categories. They are also their own category. + +_Monads_ are — I haven’t gotten to monads yet. + +## I read that they have a Monad in philosophy + +And it means _god_. [¹](it-doesnt-mean-that#fn1) + +--- + +1. More or less. diff --git a/content/posts/it-doesnt-mean-that/wikimedia_monad.svg b/content/posts/it-doesnt-mean-that/wikimedia_monad.svg new file mode 100644 index 0000000..887c3c6 --- /dev/null +++ b/content/posts/it-doesnt-mean-that/wikimedia_monad.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/content/posts/now-2024-fall.md b/content/posts/now-2024-fall.md deleted file mode 100644 index b71de95..0000000 --- a/content/posts/now-2024-fall.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: 🍁 Now, fall 2024 -date: 2024-12-10 -description: Dog dug up the yard and the new grass. Painted some rooms. Built a little bathroom shelf, a little nightstand and a sound diffuser. -extra: - kind: now ---- - -{{ toc() }} - -## Home - -- Dog dug up the yard and the new grass. Multiple times even. Planted some clovers to hide the bald spot. Fixed up a vine that fell down from the wall. -- Painted some rooms. The previous owner left them in a sorry state. -- Built a little bathroom shelf, a little nightstand and a sound diffuser. Getting the hang of woodworking. - - - - -## Relationship - -- Got engaged! - -## Quests - -I remember seeing some blog post somewhere that advocated, possibly a bit ironically, the concept of using **main quests**, **side quests** and **daily quests** in tracking your to-dos. I decided to give them a try. I now use main and side quests to keep track of my higher level objectives. These objectives function at the week or month level. I do not use daily quests. - -I’ve always found it hard to stick to to-do tracking schemes. They are often too complex and unable to track priorities or time spans in a way that would feel natural. Maybe this approach is simple and video-gamey enough to stick. - -## Live music 🤘🏻 - -- Valkeat, Ethereal Sin @ Lepakkomies -- Queendyster, Liturgy @ Kuudes Linja -- Havukruunu, Satanic North @ Tavastia - -## Video games - -Played: - -- Outer Wilds (this was a good game) and the DLC (not entirely my vibe) -- Plucky Squire -- Neon White - -Enjoyed watching: - -- Metal Gear Solids 1–4 in [Giant Bomb longplay format](https://www.youtube.com/playlist?list=PLXlhzeWIuTHLfGvMnnWLJK3DRLQwcTpwd) -- Ultrakill - -## Career - -- Finished some certifications: _GCP-ACE_, _AZ-900_, _AI-900_. - -## Reading - -- Still reading _Designing Data-intensive Applications_. Got sidetracked by a database project that was inspired by the book. - -## Top tunes - -- Djennaration – Liturgy -- The Ultrakill OST - -## Previous update - -- [🌞 Now, summer 2024](/posts/now-2024-summer) diff --git a/content/posts/now-2024-fall/diffuser_1.jpg b/content/posts/now-2024-fall/diffuser_1.jpg new file mode 100644 index 0000000..d5e6693 Binary files /dev/null and b/content/posts/now-2024-fall/diffuser_1.jpg differ diff --git a/content/posts/now-2024-fall/diffuser_2.jpg b/content/posts/now-2024-fall/diffuser_2.jpg new file mode 100644 index 0000000..f8c8b84 Binary files /dev/null and b/content/posts/now-2024-fall/diffuser_2.jpg differ diff --git a/content/posts/now-2024-fall/diffuser_3.jpg b/content/posts/now-2024-fall/diffuser_3.jpg new file mode 100644 index 0000000..5efa8ab Binary files /dev/null and b/content/posts/now-2024-fall/diffuser_3.jpg differ diff --git a/content/posts/now-2024-fall/index.md b/content/posts/now-2024-fall/index.md new file mode 100644 index 0000000..1946eda --- /dev/null +++ b/content/posts/now-2024-fall/index.md @@ -0,0 +1,88 @@ +--- +title: 🍁 Now, fall 2024 +date: 2024-12-10 +description: Dog dug up the yard and the new grass. Painted some rooms. Built a little bathroom shelf, a little nightstand and a sound diffuser. +extra: + kind: now +--- + +{{ toc() }} + +## Home + +- Dog dug up the yard and the new grass. Multiple times even. Planted some clovers to hide the bald spot. Fixed up a vine that fell down from the wall. +- Painted some rooms. The previous owner left them in a sorry state. +- Built a little bathroom shelf, a little nightstand and a sound diffuser. Getting the hang of woodworking. + + + + +## Relationship + +- Got engaged! + +## Quests + +I remember seeing some blog post somewhere that advocated, possibly a bit ironically, the concept of using **main quests**, **side quests** and **daily quests** in tracking your to-dos. I decided to give them a try. I now use main and side quests to keep track of my higher level objectives. These objectives function at the week or month level. I do not use daily quests. + +I’ve always found it hard to stick to to-do tracking schemes. They are often too complex and unable to track priorities or time spans in a way that would feel natural. Maybe this approach is simple and video-gamey enough to stick. + +## Live music 🤘🏻 + +- Valkeat, Ethereal Sin @ Lepakkomies +- Queendyster, Liturgy @ Kuudes Linja +- Havukruunu, Satanic North @ Tavastia + +## Video games + +Played: + +- Outer Wilds (this was a good game) and the DLC (not entirely my vibe) +- Plucky Squire +- Neon White + +Enjoyed watching: + +- Metal Gear Solids 1–4 in [Giant Bomb longplay format](https://www.youtube.com/playlist?list=PLXlhzeWIuTHLfGvMnnWLJK3DRLQwcTpwd) +- Ultrakill + +## Career + +- Finished some certifications: _GCP-ACE_, _AZ-900_, _AI-900_. + +## Reading + +- Still reading _Designing Data-intensive Applications_. Got sidetracked by a database project that was inspired by the book. + +## Top tunes + +- Djennaration – Liturgy +- The Ultrakill OST + +## Previous update + +- [🌞 Now, summer 2024](/posts/now-2024-summer) diff --git a/content/posts/now-2024-spring.md b/content/posts/now-2024-spring.md deleted file mode 100644 index aa1fe1f..0000000 --- a/content/posts/now-2024-spring.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: 🌱 Now, spring 2024 -date: 2024-04-22 -description: Inches of snow are falling on the yard, covering any new green growths. The dog likes it, I don't. -extra: - kind: now ---- - -Inches of snow are falling on the yard, covering any new green growths. The dog likes it, I don't. - - - -{{ toc() }} - -## Travel - -- Attended the [QCon London 2024](/posts/qcon-london-2024-takeaways) in London -- Went to [Tahko](https://www.tahko.com/en/) for a company leisure trip to downhill ski and snowmobile - -## Music - -[BLEK](/projects#blek) was live for 3 hours on student radio Radiodiodi with a dungeon synth genre deepdive program. According to metrics, 20 people (!) were listening to our show, which was also our grand EP premiere. Big leagues. - -I bought a [cassette player](/posts/cassettes) and a bunch of metal and dungeon synth tapes, as well some empty ones from the Bezos shop. I'm planning to record BLEK's music on some of them. - -## Games - -We've been on a proper Ratchet and Clank binge, together with Marika. - -- Ratchet and Clank: Rift Apart -- Ratchet and Clank: Tools of Destruction -- Ratchet and Clank: Gladiator (Deadlocked) -- Also we played the original trilogy in 2023 - -Non-Ratchet: - -- Rollerdrome - -Tabletop games: - -- Started playing [Miru](https://hinokodo.itch.io/miru-an-analog-adventure-game) - -## Reading - -- _Category Theory for Programmers_ by Bartosz Milewski - - Turned out to be quite a bit more difficult than I expected. The first half was completely doable with my functional programming and limited math background, but the second half is a piece of work. I'll push through though. - -## Movies - -I went to see Dune 2. It was as ok as the first part. - -## Projects - -### ATK16 - -Picked up [ATK16](/projects/atk16) again, adding some major stuff: - -- A calling convention for functions: arguments in registers `RA`–`RG`, return value in register `RG` -- An emulator & step debugger in Python + Pygame for easier debugging -- A bump allocator for using the heap -- Ergonomics features in the assembler: - - A `@data` directive for storing data in a data segment - - A string datatype that is encoded as a length and data bytes in memory -- Some "standard library" stuff, like `memset` and `memcopy` -- A hardware monitor / shell-like program for interacting with the system in text mode -- An MMIO register for setting the interrupt flag in order to define critical sections for primitive interrupt concurrency - -I feel like a proper introduction post / documentation is long overdue 😅 I should fix that. - -### Garden (jan.systems) - -Rewrote the site generator flow. Previously, each file in the content directory was accessed and processed from start to finish separately. This meant that there was no knowledge of other notes available when rendering a note. This made stuff like a [_dynamic now page_](https://derekkedziora.com/blog/dynamic-now-page) impossible. - -Now, the flow starts by traversing the entire content directory and indexing it into an in-memory database. The database contains all the metadata and filesystem info of all the notes, as well as static files. This makes dynamic pages possible since the database can be queried at render time. This approach also improved performance, since I could reduce the number of filesystem reads and writes. - -Things I still want to add: - -- A bookmarking system, maybe somehow connected to the ~[liked](/liked) page~? - - _Update from the future_: the liked page was migrated to the [linklog](/linklog). -- A project page structure (just a content thing, no code required) - -## Previous update - -[❄️ Now, winter 2023](/posts/now-2023-winter) diff --git a/content/posts/now-2024-spring/index.md b/content/posts/now-2024-spring/index.md new file mode 100644 index 0000000..ad10fe5 --- /dev/null +++ b/content/posts/now-2024-spring/index.md @@ -0,0 +1,87 @@ +--- +title: 🌱 Now, spring 2024 +date: 2024-04-22 +description: Inches of snow are falling on the yard, covering any new green growths. The dog likes it, I don't. +extra: + kind: now +--- + +Inches of snow are falling on the yard, covering any new green growths. The dog likes it, I don't. + + + +{{ toc() }} + +## Travel + +- Attended the [QCon London 2024](/posts/qcon-london-2024-takeaways) in London +- Went to [Tahko](https://www.tahko.com/en/) for a company leisure trip to downhill ski and snowmobile + +## Music + +[BLEK](/projects#blek) was live for 3 hours on student radio Radiodiodi with a dungeon synth genre deepdive program. According to metrics, 20 people (!) were listening to our show, which was also our grand EP premiere. Big leagues. + +I bought a [cassette player](/posts/cassettes) and a bunch of metal and dungeon synth tapes, as well some empty ones from the Bezos shop. I'm planning to record BLEK's music on some of them. + +## Games + +We've been on a proper Ratchet and Clank binge, together with Marika. + +- Ratchet and Clank: Rift Apart +- Ratchet and Clank: Tools of Destruction +- Ratchet and Clank: Gladiator (Deadlocked) +- Also we played the original trilogy in 2023 + +Non-Ratchet: + +- Rollerdrome + +Tabletop games: + +- Started playing [Miru](https://hinokodo.itch.io/miru-an-analog-adventure-game) + +## Reading + +- _Category Theory for Programmers_ by Bartosz Milewski + - Turned out to be quite a bit more difficult than I expected. The first half was completely doable with my functional programming and limited math background, but the second half is a piece of work. I'll push through though. + +## Movies + +I went to see Dune 2. It was as ok as the first part. + +## Projects + +### ATK16 + +Picked up [ATK16](/projects/atk16) again, adding some major stuff: + +- A calling convention for functions: arguments in registers `RA`–`RG`, return value in register `RG` +- An emulator & step debugger in Python + Pygame for easier debugging +- A bump allocator for using the heap +- Ergonomics features in the assembler: + - A `@data` directive for storing data in a data segment + - A string datatype that is encoded as a length and data bytes in memory +- Some "standard library" stuff, like `memset` and `memcopy` +- A hardware monitor / shell-like program for interacting with the system in text mode +- An MMIO register for setting the interrupt flag in order to define critical sections for primitive interrupt concurrency + +I feel like a proper introduction post / documentation is long overdue 😅 I should fix that. + +### Garden (jan.systems) + +Rewrote the site generator flow. Previously, each file in the content directory was accessed and processed from start to finish separately. This meant that there was no knowledge of other notes available when rendering a note. This made stuff like a [_dynamic now page_](https://derekkedziora.com/blog/dynamic-now-page) impossible. + +Now, the flow starts by traversing the entire content directory and indexing it into an in-memory database. The database contains all the metadata and filesystem info of all the notes, as well as static files. This makes dynamic pages possible since the database can be queried at render time. This approach also improved performance, since I could reduce the number of filesystem reads and writes. + +Things I still want to add: + +- A bookmarking system, maybe somehow connected to the ~[liked](/liked) page~? + - _Update from the future_: the liked page was migrated to the [linklog](/linklog). +- A project page structure (just a content thing, no code required) + +## Previous update + +[❄️ Now, winter 2023](/posts/now-2023-winter) diff --git a/content/posts/now-2024-spring/jojo-in-snow.webm b/content/posts/now-2024-spring/jojo-in-snow.webm new file mode 100644 index 0000000..19047e5 Binary files /dev/null and b/content/posts/now-2024-spring/jojo-in-snow.webm differ diff --git a/content/posts/now-2024-summer.md b/content/posts/now-2024-summer.md deleted file mode 100644 index cc7bb74..0000000 --- a/content/posts/now-2024-summer.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: 🌞 Now, summer 2024 -date: 2024-07-18 -extra: - kind: now ---- - -{{ toc() }} - -## Home - -- Yard work: some small landscaping, changed the topsoil to something less dry, and planted grass and flowers. -- Purchased a **wine fridge** for some reason. This led directly to... - -## A new hobby - -- Started learning about wines. Organized a wine tasting. My top pick: Domaine Laroche Chablis 1er Cru Les Vaudevey 2022. - -{{ fig(src="/files/2024-wines.jpg", alt="Wines from the tasting") }} - -### Career - -- I passed the **AWS Certified Developer Associate** certificate exam! A celebratory espresso martini was in order. Planning to do **Solutions Architect Associate** next. - -{{ fig(src="/files/aws-exam-drink.jpeg", alt="My hand holding an espresso martini outside in sunny weather") }} - -## Played games - -- Animal well -- Ratchet & Clank: A Crack in Time -- Snufkin: Melody of Moominvalley -- Cult of the Lamb -- [Miru](https://hinokodo.itch.io/miru-an-analog-adventure-game) -- Celeste - -## Finished reading - -- Finished _Category Theory for Programmers_ by Bartosz Milewski. Had to work through it twice, taking notes on the second pass. I wish I started taking notes from the get go. -- _Wine Simple_ by Aldo Sohm, wine fundamentals for beginners. -- Some CS papers: - - _Do Be Do Be Do_ by Sam Lindley et al. The paper defines a language called Frank that uses a novel algebraic effects based typed effect system instead of monads. Also has types for suspended calculations (think Haskell thunks). Similar to Koka I believe. - - _Cons should not eval its arguments_, a classic that paves the way for lazily evaluated languages. -- Japanese short stories (Yomu Yomu app) such as _人間椅子 (Human chair)_, a story about a carpenter that decides to live inside a chair that he’s made. Adapted to a vocabulary of 1500 words. - -## Started reading - -- _Designing Data-intensive Applications_ by Martin Kleppmann. - -## Top tunes - -- [maudlin of the Well - Gleam in Ranks](https://open.spotify.com/track/5cyKheZd5E3jBtjcflE7Gz?si=y-mOWdUVT36XOo0zl1kK_w&context=spotify%3Aalbum%3A2BwbUYJeuUsv6LUA6GZHB4) -- [predawka - erynias](https://youtu.be/wyOG7ZiVLLo) - -## Previous update - -- [🌱 Now, spring 2024](/posts/now-2024-spring) diff --git a/content/posts/now-2024-summer/2024-wines.jpg b/content/posts/now-2024-summer/2024-wines.jpg new file mode 100644 index 0000000..81cddef Binary files /dev/null and b/content/posts/now-2024-summer/2024-wines.jpg differ diff --git a/content/posts/now-2024-summer/aws-exam-drink.jpeg b/content/posts/now-2024-summer/aws-exam-drink.jpeg new file mode 100644 index 0000000..16f8933 Binary files /dev/null and b/content/posts/now-2024-summer/aws-exam-drink.jpeg differ diff --git a/content/posts/now-2024-summer/index.md b/content/posts/now-2024-summer/index.md new file mode 100644 index 0000000..d716e4a --- /dev/null +++ b/content/posts/now-2024-summer/index.md @@ -0,0 +1,56 @@ +--- +title: 🌞 Now, summer 2024 +date: 2024-07-18 +extra: + kind: now +--- + +{{ toc() }} + +## Home + +- Yard work: some small landscaping, changed the topsoil to something less dry, and planted grass and flowers. +- Purchased a **wine fridge** for some reason. This led directly to... + +## A new hobby + +- Started learning about wines. Organized a wine tasting. My top pick: Domaine Laroche Chablis 1er Cru Les Vaudevey 2022. + +{{ fig(src="2024-wines.jpg", alt="Wines from the tasting") }} + +### Career + +- I passed the **AWS Certified Developer Associate** certificate exam! A celebratory espresso martini was in order. Planning to do **Solutions Architect Associate** next. + +{{ fig(src="aws-exam-drink.jpeg", alt="My hand holding an espresso martini outside in sunny weather") }} + +## Played games + +- Animal well +- Ratchet & Clank: A Crack in Time +- Snufkin: Melody of Moominvalley +- Cult of the Lamb +- [Miru](https://hinokodo.itch.io/miru-an-analog-adventure-game) +- Celeste + +## Finished reading + +- Finished _Category Theory for Programmers_ by Bartosz Milewski. Had to work through it twice, taking notes on the second pass. I wish I started taking notes from the get go. +- _Wine Simple_ by Aldo Sohm, wine fundamentals for beginners. +- Some CS papers: + - _Do Be Do Be Do_ by Sam Lindley et al. The paper defines a language called Frank that uses a novel algebraic effects based typed effect system instead of monads. Also has types for suspended calculations (think Haskell thunks). Similar to Koka I believe. + - _Cons should not eval its arguments_, a classic that paves the way for lazily evaluated languages. +- Japanese short stories (Yomu Yomu app) such as _人間椅子 (Human chair)_, a story about a carpenter that decides to live inside a chair that he’s made. Adapted to a vocabulary of 1500 words. + +## Started reading + +- _Designing Data-intensive Applications_ by Martin Kleppmann. + +## Top tunes + +- [maudlin of the Well - Gleam in Ranks](https://open.spotify.com/track/5cyKheZd5E3jBtjcflE7Gz?si=y-mOWdUVT36XOo0zl1kK_w&context=spotify%3Aalbum%3A2BwbUYJeuUsv6LUA6GZHB4) +- [predawka - erynias](https://youtu.be/wyOG7ZiVLLo) + +## Previous update + +- [🌱 Now, spring 2024](/posts/now-2024-spring) diff --git a/content/posts/now-2025-fall.md b/content/posts/now-2025-fall.md deleted file mode 100644 index fe0d1f2..0000000 --- a/content/posts/now-2025-fall.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: 🍁 Now, fall 2025 -date: 2025-10-05 -description: Late summer and early autumn have been a time of ups and downs. -extra: - kind: now ---- - -Late summer and early autumn have been a time of ups and downs. - -I lost my father to illness. The passing was expected, in a way, so I have had time to process things in advance, but when it actually happened it turned everything on its head for a while. - -Sorting out things after the death has taken a lot of time and effort, but things are now more or less in order. I have got a lot of support and help from my peers, and I feel I have let myself process the grief well. I try to focus on positive things. - -We've also been planning the wedding that's taking place in 2026. In many ways I feel out of my element, but things are moving forward. - -{{ toc() }} - -## Home - -A lot of renovations this summer. One of the biggest ones was the translucent roofing installation: - -{{ fig(src="/files/valokate_1.jpg", alt="Installing the sunroof") }} - -After around six hours (including breaks), it's all done! Just in time for rain. - -{{ fig(src="/files/valokate_2.jpg", alt="Complete sunroof") }} - -You can see the gnarly reddish wall in the picture. That and a bunch of other grime and residue was cleaned off as part of a neighborhood exterior painting project. The place is looking a lot nicer now from the outside (no pictures of this I'm afraid). - -We also got some minor things done, like installing curtains to my fiancé's office room. I got some new toolboxes that I use to keep everything nice and organized, and hidden away when not needed. - -With all the materials and tools lying around our home has felt like a job site, but now that everything's done and cleaned up, I'm happy that everything got done as well as it did. - -## FreeBSD server - -I have been setting up a home server and writing a blog series about it. Check out parts [one](home-server-part-1) and [two](home-server-part-2)! My plan is to move things back from the cloud & other people's computers back to my home and self-host as many things as possible. - -## Books - -**Finished** - -- Robert Nystrom, _Crafting Interpreters_ -- Michael W. Lucas, _Absolute FreeBSD_ -- Michael W. Lucas, _FreeBSD Mastery: ZFS_ -- Michael W. Lucas, _FreeBSD Mastery: Jails_ -- Leo Brodie, _Thinking Forth_ - -**Started** - -- Benjamin C. Pierce, _Types and Programming Languages_ -- Adam Aleksic, _Algospeak_ - -## Games - -**Played** - -- Bomb Rush Cyberfunk -- Hollow Knight: Silksong - -**Started** - -- God of War: Ragnarök - -**Enjoyed as a VOD/live stream** - -- Watched CDawgVA's playthroughs of MGS 1–3 and Revengeance -- A lot of Silksong VODs and speedruns - -## Travel - -I late August I went on a company trip to Krakow, Poland for one weekend. A nice city with beautiful old town buildings, but sadly the weather was a bit dull. My favorite food spot was the [Black Duck](https://czarnakaczka.pl/) 😋. - -In September we had booked a trip to Italy with a group of friends. We stayed in Rome for a couple of days, enjoying the 30C heat and sights such as the Villa Borghese. We had already visited the Colosseum and the Vatican on earlier trips so we decided to avoid the queues and visit less popular places. It was the Jubileum year so many sights were jam-packed. After that we got a rental and drove ~500km south to Calabria, where we spent the next week at a really nice villa overlooking the sea. - -{{ fig(src="/files/villa.jpeg", alt="The view from the villa") }} - -Later in September I attended EuroBSDCon 2025 in Zagreb, Croatia. A lot of great talks and lab sessions! I might write a conference notes post about the trip. - -So, a lot of traveling in a short timespan, so I've been feeling quite exhausted. The rest of the autumn is looking less hectic, so I might be able to work on projects more 🤔 - -## Anime - -- Puella Magi Madoka Magica -- Started Kill la Kill -- Chainsaw Man (still a couple of eps to go) - -## Previous update - -- [☀️ Now, summer 2025](/posts/now-2025-summer) diff --git a/content/posts/now-2025-fall/index.md b/content/posts/now-2025-fall/index.md new file mode 100644 index 0000000..0c21cd6 --- /dev/null +++ b/content/posts/now-2025-fall/index.md @@ -0,0 +1,90 @@ +--- +title: 🍁 Now, fall 2025 +date: 2025-10-05 +description: Late summer and early autumn have been a time of ups and downs. +extra: + kind: now +--- + +Late summer and early autumn have been a time of ups and downs. + +I lost my father to illness. The passing was expected, in a way, so I have had time to process things in advance, but when it actually happened it turned everything on its head for a while. + +Sorting out things after the death has taken a lot of time and effort, but things are now more or less in order. I have got a lot of support and help from my peers, and I feel I have let myself process the grief well. I try to focus on positive things. + +We've also been planning the wedding that's taking place in 2026. In many ways I feel out of my element, but things are moving forward. + +{{ toc() }} + +## Home + +A lot of renovations this summer. One of the biggest ones was the translucent roofing installation: + +{{ fig(src="valokate_1.jpg", alt="Installing the sunroof") }} + +After around six hours (including breaks), it's all done! Just in time for rain. + +{{ fig(src="valokate_2.jpg", alt="Complete sunroof") }} + +You can see the gnarly reddish wall in the picture. That and a bunch of other grime and residue was cleaned off as part of a neighborhood exterior painting project. The place is looking a lot nicer now from the outside (no pictures of this I'm afraid). + +We also got some minor things done, like installing curtains to my fiancé's office room. I got some new toolboxes that I use to keep everything nice and organized, and hidden away when not needed. + +With all the materials and tools lying around our home has felt like a job site, but now that everything's done and cleaned up, I'm happy that everything got done as well as it did. + +## FreeBSD server + +I have been setting up a home server and writing a blog series about it. Check out parts [one](home-server-part-1) and [two](home-server-part-2)! My plan is to move things back from the cloud & other people's computers back to my home and self-host as many things as possible. + +## Books + +**Finished** + +- Robert Nystrom, _Crafting Interpreters_ +- Michael W. Lucas, _Absolute FreeBSD_ +- Michael W. Lucas, _FreeBSD Mastery: ZFS_ +- Michael W. Lucas, _FreeBSD Mastery: Jails_ +- Leo Brodie, _Thinking Forth_ + +**Started** + +- Benjamin C. Pierce, _Types and Programming Languages_ +- Adam Aleksic, _Algospeak_ + +## Games + +**Played** + +- Bomb Rush Cyberfunk +- Hollow Knight: Silksong + +**Started** + +- God of War: Ragnarök + +**Enjoyed as a VOD/live stream** + +- Watched CDawgVA's playthroughs of MGS 1–3 and Revengeance +- A lot of Silksong VODs and speedruns + +## Travel + +I late August I went on a company trip to Krakow, Poland for one weekend. A nice city with beautiful old town buildings, but sadly the weather was a bit dull. My favorite food spot was the [Black Duck](https://czarnakaczka.pl/) 😋. + +In September we had booked a trip to Italy with a group of friends. We stayed in Rome for a couple of days, enjoying the 30C heat and sights such as the Villa Borghese. We had already visited the Colosseum and the Vatican on earlier trips so we decided to avoid the queues and visit less popular places. It was the Jubileum year so many sights were jam-packed. After that we got a rental and drove ~500km south to Calabria, where we spent the next week at a really nice villa overlooking the sea. + +{{ fig(src="villa.jpeg", alt="The view from the villa") }} + +Later in September I attended EuroBSDCon 2025 in Zagreb, Croatia. A lot of great talks and lab sessions! I might write a conference notes post about the trip. + +So, a lot of traveling in a short timespan, so I've been feeling quite exhausted. The rest of the autumn is looking less hectic, so I might be able to work on projects more 🤔 + +## Anime + +- Puella Magi Madoka Magica +- Started Kill la Kill +- Chainsaw Man (still a couple of eps to go) + +## Previous update + +- [☀️ Now, summer 2025](/posts/now-2025-summer) diff --git a/content/posts/now-2025-fall/valokate_1.jpg b/content/posts/now-2025-fall/valokate_1.jpg new file mode 100644 index 0000000..1ddccf2 Binary files /dev/null and b/content/posts/now-2025-fall/valokate_1.jpg differ diff --git a/content/posts/now-2025-fall/valokate_2.jpg b/content/posts/now-2025-fall/valokate_2.jpg new file mode 100644 index 0000000..3d66088 Binary files /dev/null and b/content/posts/now-2025-fall/valokate_2.jpg differ diff --git a/content/posts/now-2025-fall/villa.jpeg b/content/posts/now-2025-fall/villa.jpeg new file mode 100644 index 0000000..51cc84b Binary files /dev/null and b/content/posts/now-2025-fall/villa.jpeg differ diff --git a/content/posts/now-2025-summer.md b/content/posts/now-2025-summer.md deleted file mode 100644 index 81293ca..0000000 --- a/content/posts/now-2025-summer.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: ☀️ Now, summer 2025 -date: 2025-06-15 -description: | - Here's three seasons of updates in one package. -extra: - kind: now ---- - -{{ fig(src="/files/kenrokuen.jpg", alt="A torii gate in the Kenroku-en garden") }} - -Here's three seasons of updates in one package. - -{{ toc() }} - -## AutereDB project - -I was reading [Designing Data-intensive Applications](https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/) and I came across a chapter where the author goes over log-structured database architecture. I knew about B-tree based systems, but this seemingly simpler approach was new to me. I was intrigued, but I also felt like I didn't fully grok how every cog in the theoretical database machine worked together. - -Therefore, I decided to write a quick MVP thing in Rust during a conference flight. The result is **AutereDB** ([Github](https://github.com/jantuomi/autere_db)). - -AutereDB is more like a database engine. It doesn't have a query language, authorization mechanisms, multi-table support or other higher-level features. It simply makes sure that records are written to disk as expected, and queries return the correct data. - -You can read more about the project in the `README.md`. - -I have no plans to really further this project. I feel it was a one-off to better grok how these things work. I consider this goal met; I am now more confident about reasoning about data systems. Many things that I learned the hard way during this project have already proved to be beneficial in my day job, so mission success. - -Help yourself to the `ARCHITECTURE.md` file in the repository, and have a laugh at how I made multiple major miscalculations early on in the project, and then scrambled to fix these as I realized my folly. I tried to document most of these in the architecture decision log, for posterity. - -## FemtoQueue project - -Another data-centric project I conjured up: a Python task queue library that uses files in the filesystem for task persistence, and `rename()` to atomically move tasks from one state to another. - -FemtoQueue is on [Github](https://github.com/jantuomi/femtoqueue), as well as on [PyPI](https://pypi.org/project/femtoqueue/) as a pip-installable package. - -I'm pretty proud of this one. The core idea fits in under 100 lines of no-dependency Python. The current version with QoL stuff and docstrings clocks in at around 350 LoC. I could see it being very useful for small projects where you need some kind of a durable queue for sending emails etc., but don't want to add a whole separate networked Redis-like thing, or Celery or a home-cooked SQLite-based solution. - -## Japan trip - -Me and my fiancée made a long-awaited trip to Japan in the spring. We landed in the KIX airport near Ōsaka right in the middle of the cherry blossom season, hanami. - -We traveled the central island, Honshū, for three weeks. Mostly by train, but also by bus. We visited Ōsaka, Nara, Kyōto, Gifu-Takayama, Kanazawa and finally Tōkyō. This route skips the popular south-coast bullet train connection, instead going north through the mountains. - -{{ fig(src="/files/samurai_garden.jpeg", alt="The garden of a preserved samurai family home, with a koi fish pond and stone lantern") }} - -I got to finally test my Japanese. Speaking was very laborious at first, but it got way easier the more I got to practise. My vocabulary didn't improve that much, but what improved were things like _cadence_, _[aizuchi](https://en.wikipedia.org/wiki/Aizuchi)_, and ability to respond with more natural word choices. Big up to active listening and copying native speakers. - -We ate and drank well. We mostly gravitated towards traditional-style, or _washoku_, establishments. Our favorite meals were prepared by a sweet grandma in a hot springs guesthouse in the mountains. Simple and clean ingredients. - -Something to note: pickled veggies go great with meat-centered, hearty meals. We were eager to implement this in our home cooking as soon as we got home. - -{{ fig(src="/files/wagyu_grill.jpeg", alt="Wagyu beef, mushroom and peppers on a tabletop charcoal grill") }} - -We visited the obligatory tourist spots, like the _Thousand torī gates_ in Kyōto, and the _Dōtonbori shopping street_ in Ōsaka. We like seeing sights, but we know that our most memorable experiences have always come naturally from exploration and keeping an open mind. That's why we spent only a fraction of our time visiting Tripadvisor locations and most of the time wandering around, following local recommendations and keeping our eyes, ears and nostrils peeled. - -We are planning to travel there again, maybe on honeymoon. - -## FreeBSD home server - -I have recently started a project of setting up a small publicly accessible home server that will replace my DigitalOcean VPS in some time. The system will be very FreeBSD jail focused. I have just received the hardware and verified that the everything is up to par. Very hyped about this one. - -I am planning to write some posts about the progress. - -## Home - -A lot of small things need renovated. I guess this is what owning a house is. We have done a lot, and even more is still on the backlog. - -しょうがないね。 - -Going to install some patio roofing during the next couple of weeks, first time doing that. - -## Books - -Mostly FreeBSD stuff by [Michael W. Lucas](https://mwl.io/nonfiction/os). - -**Finished** - -- [Designing Data-intensive Applications](https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/) (took a long time to work through this one) -- FreeBSD Mastery: Storage Essentials - -**Started** - -- Absolute FreeBSD -- FreeBSD Mastery: ZFS -- FreeBSD Mastery: Jails - -## Games - -**Played** - -- Gato Roboto -- A Short Hike -- Cozy Grove (watched my fiancée play this one) -- Warhammer 40k: Boltgun - -**Enjoyed as a VOD/live stream** - -- Blue Prince -- Rainworld - -## Anime - -- Jujutsu Kaisen 0, S1, S2 -- FLCL Progressive -- Demon Slayer: Mugen Train -- Evangelion rebuild movies -- Blame! (movie) -- Puella Magi Madoka Magica -- Dandadan -- Chainsaw Man (still a couple of eps to go) - -## Previous update - -- [🍁 Now, fall 2024](/posts/now-2024-fall) diff --git a/content/posts/now-2025-summer/index.md b/content/posts/now-2025-summer/index.md new file mode 100644 index 0000000..d3bbaa5 --- /dev/null +++ b/content/posts/now-2025-summer/index.md @@ -0,0 +1,114 @@ +--- +title: ☀️ Now, summer 2025 +date: 2025-06-15 +description: | + Here's three seasons of updates in one package. +extra: + kind: now +--- + +{{ fig(src="kenrokuen.jpg", alt="A torii gate in the Kenroku-en garden") }} + +Here's three seasons of updates in one package. + +{{ toc() }} + +## AutereDB project + +I was reading [Designing Data-intensive Applications](https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/) and I came across a chapter where the author goes over log-structured database architecture. I knew about B-tree based systems, but this seemingly simpler approach was new to me. I was intrigued, but I also felt like I didn't fully grok how every cog in the theoretical database machine worked together. + +Therefore, I decided to write a quick MVP thing in Rust during a conference flight. The result is **AutereDB** ([Github](https://github.com/jantuomi/autere_db)). + +AutereDB is more like a database engine. It doesn't have a query language, authorization mechanisms, multi-table support or other higher-level features. It simply makes sure that records are written to disk as expected, and queries return the correct data. + +You can read more about the project in the `README.md`. + +I have no plans to really further this project. I feel it was a one-off to better grok how these things work. I consider this goal met; I am now more confident about reasoning about data systems. Many things that I learned the hard way during this project have already proved to be beneficial in my day job, so mission success. + +Help yourself to the `ARCHITECTURE.md` file in the repository, and have a laugh at how I made multiple major miscalculations early on in the project, and then scrambled to fix these as I realized my folly. I tried to document most of these in the architecture decision log, for posterity. + +## FemtoQueue project + +Another data-centric project I conjured up: a Python task queue library that uses files in the filesystem for task persistence, and `rename()` to atomically move tasks from one state to another. + +FemtoQueue is on [Github](https://github.com/jantuomi/femtoqueue), as well as on [PyPI](https://pypi.org/project/femtoqueue/) as a pip-installable package. + +I'm pretty proud of this one. The core idea fits in under 100 lines of no-dependency Python. The current version with QoL stuff and docstrings clocks in at around 350 LoC. I could see it being very useful for small projects where you need some kind of a durable queue for sending emails etc., but don't want to add a whole separate networked Redis-like thing, or Celery or a home-cooked SQLite-based solution. + +## Japan trip + +Me and my fiancée made a long-awaited trip to Japan in the spring. We landed in the KIX airport near Ōsaka right in the middle of the cherry blossom season, hanami. + +We traveled the central island, Honshū, for three weeks. Mostly by train, but also by bus. We visited Ōsaka, Nara, Kyōto, Gifu-Takayama, Kanazawa and finally Tōkyō. This route skips the popular south-coast bullet train connection, instead going north through the mountains. + +{{ fig(src="samurai_garden.jpeg", alt="The garden of a preserved samurai family home, with a koi fish pond and stone lantern") }} + +I got to finally test my Japanese. Speaking was very laborious at first, but it got way easier the more I got to practise. My vocabulary didn't improve that much, but what improved were things like _cadence_, _[aizuchi](https://en.wikipedia.org/wiki/Aizuchi)_, and ability to respond with more natural word choices. Big up to active listening and copying native speakers. + +We ate and drank well. We mostly gravitated towards traditional-style, or _washoku_, establishments. Our favorite meals were prepared by a sweet grandma in a hot springs guesthouse in the mountains. Simple and clean ingredients. + +Something to note: pickled veggies go great with meat-centered, hearty meals. We were eager to implement this in our home cooking as soon as we got home. + +{{ fig(src="wagyu_grill.jpeg", alt="Wagyu beef, mushroom and peppers on a tabletop charcoal grill") }} + +We visited the obligatory tourist spots, like the _Thousand torī gates_ in Kyōto, and the _Dōtonbori shopping street_ in Ōsaka. We like seeing sights, but we know that our most memorable experiences have always come naturally from exploration and keeping an open mind. That's why we spent only a fraction of our time visiting Tripadvisor locations and most of the time wandering around, following local recommendations and keeping our eyes, ears and nostrils peeled. + +We are planning to travel there again, maybe on honeymoon. + +## FreeBSD home server + +I have recently started a project of setting up a small publicly accessible home server that will replace my DigitalOcean VPS in some time. The system will be very FreeBSD jail focused. I have just received the hardware and verified that the everything is up to par. Very hyped about this one. + +I am planning to write some posts about the progress. + +## Home + +A lot of small things need renovated. I guess this is what owning a house is. We have done a lot, and even more is still on the backlog. + +しょうがないね。 + +Going to install some patio roofing during the next couple of weeks, first time doing that. + +## Books + +Mostly FreeBSD stuff by [Michael W. Lucas](https://mwl.io/nonfiction/os). + +**Finished** + +- [Designing Data-intensive Applications](https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/) (took a long time to work through this one) +- FreeBSD Mastery: Storage Essentials + +**Started** + +- Absolute FreeBSD +- FreeBSD Mastery: ZFS +- FreeBSD Mastery: Jails + +## Games + +**Played** + +- Gato Roboto +- A Short Hike +- Cozy Grove (watched my fiancée play this one) +- Warhammer 40k: Boltgun + +**Enjoyed as a VOD/live stream** + +- Blue Prince +- Rainworld + +## Anime + +- Jujutsu Kaisen 0, S1, S2 +- FLCL Progressive +- Demon Slayer: Mugen Train +- Evangelion rebuild movies +- Blame! (movie) +- Puella Magi Madoka Magica +- Dandadan +- Chainsaw Man (still a couple of eps to go) + +## Previous update + +- [🍁 Now, fall 2024](/posts/now-2024-fall) diff --git a/content/posts/now-2025-summer/kenrokuen.jpg b/content/posts/now-2025-summer/kenrokuen.jpg new file mode 100644 index 0000000..f739d82 Binary files /dev/null and b/content/posts/now-2025-summer/kenrokuen.jpg differ diff --git a/content/posts/now-2025-summer/samurai_garden.jpeg b/content/posts/now-2025-summer/samurai_garden.jpeg new file mode 100644 index 0000000..f6637b0 Binary files /dev/null and b/content/posts/now-2025-summer/samurai_garden.jpeg differ diff --git a/content/posts/now-2025-summer/wagyu_grill.jpeg b/content/posts/now-2025-summer/wagyu_grill.jpeg new file mode 100644 index 0000000..0e835bc Binary files /dev/null and b/content/posts/now-2025-summer/wagyu_grill.jpeg differ diff --git a/content/posts/now-2025-winter.md b/content/posts/now-2025-winter.md deleted file mode 100644 index 0462760..0000000 --- a/content/posts/now-2025-winter.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: ❄️ Now, winter 2025 -date: 2025-12-16 -description: | - Fall has gone by, fast. Mostly rain and darkness. Managing the estate of my late father has taken up a lot of time I would've otherwise spent on hobbies. -extra: - kind: now ---- - -Fall has gone by, fast. Mostly rain and darkness. - -Managing the estate of my late father has taken up a lot of time I would've otherwise spent on hobbies. - -Some decor and reno at home, some game programming, a lot of games. Game design has been on my mind a lot lately. - -I also attended my first ever Finnish defence forces reservist refresher training exercise. I had a good time! - -{{ toc() }} - -## Metroidvania game dev - -🚨 Original game idea alert 🚨 - -I decided to make a 2D platformer with ability-gated progression. It's gonna have pixel art too. - -It's been a very long time since I made a complete game project. I don't care about how many players I'm gonna get. I just want to create a game, for me. - -I figured I should do some proper design upfront instead of doing the easy thing, i.e. jumping straight into programming mechanics. That's why I started writing a Game Design Document ASAP. With that, maybe I can come back to this project easier, after the inevitable plateau and loss of interest. - -Maybe some screenshots later. - -## Future of ATK16 - -An idea came to me in my sleep. I want to change the course of my computing project ATK16 and turn it into a stack-based, Forth-like system. - -Clearly I've been subconsciously processing ideas from Forth and [Uxntal](https://wiki.xxiivv.com/site/uxntal.html), since my current vision is a hodgepodge of features from those two: - -- an interactive REPL-compiler, able to compile native code on the fly -- a system-wide dictionary (map of symbols to code or data), giving structure to the linear memory -- reverse Polish notation, which falls naturally out of the stack machine design - -A basic session could look like this: - -```sh -ATK16 v0.1 -Dictionary usage: 10 KB - -: average3 (a b c -- avg) - + + 3 / ; -``` - -This would define a new symbol, `average3`, that computes the average of the top 3 elements on the stack and pushes the result on the stack. The stack could be implemented in hardware with a top-of-stack optimization: the top three slots live in fast registers, while the rest is in dedicated SRAM. This would allow fast access to the most important, i.e. topmost, elements of the stack. - -In addition, I'm thinking of doing some things a bit unorthodox: - -- The system dictionary could live in FRAM, which is non-volatile. All symbol definitions would then be automatically persistent, like files on a disk. This could be huge. -- A programmer board could then allow me to directly update this dictionary from my dev laptop, possibly by emulating the same REPL software that runs on the hardware. - -In fact, it might be possible to design this in a way that completely does away with assemblers and cross-compilers. I would just need an emulator and a bit of bootstrap assembly that implements a minimal REPL that can self-compile new symbols into the dictionary. Like this, I wouldn't need to worry about ensuring that the assembler and self-compiler work exactly the same: there is only one compiler implementation! I just emulate it on my laptop. Everything is implementation defined! - -## Home - -### ”Dopamine office” decor - -Office room number one is now pretty much complete. We tried to combine some of pastel colors and fun patterns, while keeping it smart and tidy. - -{{ fig(src="/files/dopamine_office.jpeg", alt="The dopamine office") }} - -### Backdoor clothes rack and wall feature - -We use our apartment's back door a lot, more than the front door really. It's easier to take the dog out that way. - -Until now, there has been nowhere to really hang our outdoor clothes nicely. The dining table and its chairs have doubled as a clothing rack (not ideal). - -So we got the idea to repurpose the empty space in the corner, adding some visual interest with acoustic paneling as well as utility with some colorful "knobs" that you can hang coats and scarves on. - -{{ fig(src="/files/backdoor_feature_wip.jpeg", alt="Install in progress") }} - -And the final product (in completely different lighting): - -{{ fig(src="/files/backdoor_feature_done.jpeg", alt="An installed wood paneling with some coats hanging off of colored knobs") }} - -The white box is an IKEA shoebox. We keep some dog gear in there. - -### Cool dog print - -{{ fig(src="/files/taulu_koira.jpeg", alt="Cool dog") }} - -## Games - -**Played** - -- God of War: Ragnarök -- Cocoon -- Another Crab’s Treasure -- Super Metroid -- Metroid Dread -- Prince of Persia: The Lost Crown -- Ori and the Blind Forest - -## Anime - -**Finished** - -- Bocchi the Rock S1 -- Spirited Away (movie) -- Ghost in the Shell (movie) -- Kill la Kill - -**Started** - -- Dandadan S2 -- Spy x Family S1 - -## Tunes - -Mostly [Moomin music](https://youtu.be/Bf1pR4rkPK8). I went to see the _Muumimusiikkia_ show in Musiikkitalo (Helsinki) in November, and after that I haven't been able to get Shiratori's melodies out of my head. This is a positive problem. - -{{ fig(src="/files/muumimusiikkia.jpeg", alt="A photo from our seats at Musiikkitalo, showing the brochure") }} - -### Spotify Wrapped - -I feel like I'm using Spotify less and less. Might drop the subscription in the near future. I really don't like the policies they are driving. - -{{ fig(src="/files/2025_wrapped_genres.jpeg", alt="My top genres, all over the place") }} - -## Previous update - -- [🍁 Now, fall 2025](/posts/now-2025-fall) diff --git a/content/posts/now-2025-winter/2025_wrapped_genres.jpeg b/content/posts/now-2025-winter/2025_wrapped_genres.jpeg new file mode 100644 index 0000000..630be8a Binary files /dev/null and b/content/posts/now-2025-winter/2025_wrapped_genres.jpeg differ diff --git a/content/posts/now-2025-winter/backdoor_feature_done.jpeg b/content/posts/now-2025-winter/backdoor_feature_done.jpeg new file mode 100644 index 0000000..a9c71d5 Binary files /dev/null and b/content/posts/now-2025-winter/backdoor_feature_done.jpeg differ diff --git a/content/posts/now-2025-winter/backdoor_feature_wip.jpeg b/content/posts/now-2025-winter/backdoor_feature_wip.jpeg new file mode 100644 index 0000000..2f381d1 Binary files /dev/null and b/content/posts/now-2025-winter/backdoor_feature_wip.jpeg differ diff --git a/content/posts/now-2025-winter/dopamine_office.jpeg b/content/posts/now-2025-winter/dopamine_office.jpeg new file mode 100644 index 0000000..aad4e65 Binary files /dev/null and b/content/posts/now-2025-winter/dopamine_office.jpeg differ diff --git a/content/posts/now-2025-winter/index.md b/content/posts/now-2025-winter/index.md new file mode 100644 index 0000000..2fae6f8 --- /dev/null +++ b/content/posts/now-2025-winter/index.md @@ -0,0 +1,129 @@ +--- +title: ❄️ Now, winter 2025 +date: 2025-12-16 +description: | + Fall has gone by, fast. Mostly rain and darkness. Managing the estate of my late father has taken up a lot of time I would've otherwise spent on hobbies. +extra: + kind: now +--- + +Fall has gone by, fast. Mostly rain and darkness. + +Managing the estate of my late father has taken up a lot of time I would've otherwise spent on hobbies. + +Some decor and reno at home, some game programming, a lot of games. Game design has been on my mind a lot lately. + +I also attended my first ever Finnish defence forces reservist refresher training exercise. I had a good time! + +{{ toc() }} + +## Metroidvania game dev + +🚨 Original game idea alert 🚨 + +I decided to make a 2D platformer with ability-gated progression. It's gonna have pixel art too. + +It's been a very long time since I made a complete game project. I don't care about how many players I'm gonna get. I just want to create a game, for me. + +I figured I should do some proper design upfront instead of doing the easy thing, i.e. jumping straight into programming mechanics. That's why I started writing a Game Design Document ASAP. With that, maybe I can come back to this project easier, after the inevitable plateau and loss of interest. + +Maybe some screenshots later. + +## Future of ATK16 + +An idea came to me in my sleep. I want to change the course of my computing project ATK16 and turn it into a stack-based, Forth-like system. + +Clearly I've been subconsciously processing ideas from Forth and [Uxntal](https://wiki.xxiivv.com/site/uxntal.html), since my current vision is a hodgepodge of features from those two: + +- an interactive REPL-compiler, able to compile native code on the fly +- a system-wide dictionary (map of symbols to code or data), giving structure to the linear memory +- reverse Polish notation, which falls naturally out of the stack machine design + +A basic session could look like this: + +```sh +ATK16 v0.1 +Dictionary usage: 10 KB + +: average3 (a b c -- avg) + + + 3 / ; +``` + +This would define a new symbol, `average3`, that computes the average of the top 3 elements on the stack and pushes the result on the stack. The stack could be implemented in hardware with a top-of-stack optimization: the top three slots live in fast registers, while the rest is in dedicated SRAM. This would allow fast access to the most important, i.e. topmost, elements of the stack. + +In addition, I'm thinking of doing some things a bit unorthodox: + +- The system dictionary could live in FRAM, which is non-volatile. All symbol definitions would then be automatically persistent, like files on a disk. This could be huge. +- A programmer board could then allow me to directly update this dictionary from my dev laptop, possibly by emulating the same REPL software that runs on the hardware. + +In fact, it might be possible to design this in a way that completely does away with assemblers and cross-compilers. I would just need an emulator and a bit of bootstrap assembly that implements a minimal REPL that can self-compile new symbols into the dictionary. Like this, I wouldn't need to worry about ensuring that the assembler and self-compiler work exactly the same: there is only one compiler implementation! I just emulate it on my laptop. Everything is implementation defined! + +## Home + +### ”Dopamine office” decor + +Office room number one is now pretty much complete. We tried to combine some of pastel colors and fun patterns, while keeping it smart and tidy. + +{{ fig(src="dopamine_office.jpeg", alt="The dopamine office") }} + +### Backdoor clothes rack and wall feature + +We use our apartment's back door a lot, more than the front door really. It's easier to take the dog out that way. + +Until now, there has been nowhere to really hang our outdoor clothes nicely. The dining table and its chairs have doubled as a clothing rack (not ideal). + +So we got the idea to repurpose the empty space in the corner, adding some visual interest with acoustic paneling as well as utility with some colorful "knobs" that you can hang coats and scarves on. + +{{ fig(src="backdoor_feature_wip.jpeg", alt="Install in progress") }} + +And the final product (in completely different lighting): + +{{ fig(src="backdoor_feature_done.jpeg", alt="An installed wood paneling with some coats hanging off of colored knobs") }} + +The white box is an IKEA shoebox. We keep some dog gear in there. + +### Cool dog print + +{{ fig(src="taulu_koira.jpeg", alt="Cool dog") }} + +## Games + +**Played** + +- God of War: Ragnarök +- Cocoon +- Another Crab’s Treasure +- Super Metroid +- Metroid Dread +- Prince of Persia: The Lost Crown +- Ori and the Blind Forest + +## Anime + +**Finished** + +- Bocchi the Rock S1 +- Spirited Away (movie) +- Ghost in the Shell (movie) +- Kill la Kill + +**Started** + +- Dandadan S2 +- Spy x Family S1 + +## Tunes + +Mostly [Moomin music](https://youtu.be/Bf1pR4rkPK8). I went to see the _Muumimusiikkia_ show in Musiikkitalo (Helsinki) in November, and after that I haven't been able to get Shiratori's melodies out of my head. This is a positive problem. + +{{ fig(src="muumimusiikkia.jpeg", alt="A photo from our seats at Musiikkitalo, showing the brochure") }} + +### Spotify Wrapped + +I feel like I'm using Spotify less and less. Might drop the subscription in the near future. I really don't like the policies they are driving. + +{{ fig(src="2025_wrapped_genres.jpeg", alt="My top genres, all over the place") }} + +## Previous update + +- [🍁 Now, fall 2025](/posts/now-2025-fall) diff --git a/content/posts/now-2025-winter/muumimusiikkia.jpeg b/content/posts/now-2025-winter/muumimusiikkia.jpeg new file mode 100644 index 0000000..a99d8f6 Binary files /dev/null and b/content/posts/now-2025-winter/muumimusiikkia.jpeg differ diff --git a/content/posts/now-2025-winter/taulu_koira.jpeg b/content/posts/now-2025-winter/taulu_koira.jpeg new file mode 100644 index 0000000..11c4f32 Binary files /dev/null and b/content/posts/now-2025-winter/taulu_koira.jpeg differ diff --git a/content/posts/qcon-london-2024-takeaways.md b/content/posts/qcon-london-2024-takeaways.md deleted file mode 100644 index 17d8b3b..0000000 --- a/content/posts/qcon-london-2024-takeaways.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: QCon London 2024 takeaways -date: 2024-04-20 -extra: - kind: post ---- - -QCon London 2024 was a multidisciplinary software engineering conference in the London QEII Centre in April 2024. I attended with the intention to learn about what's going on in the software-sphere. Especially in terms of software architecture. - -This was also my first time in the UK so I had to do some touristing. The weather was a bit chilly, half-cloudy with some intermittent drizzle. - -{{ fig(src="/files/london-from-above.jpg", alt="London from above in the late evening") }} - -## Common themes - -### Data products - -A term from data mesh architecture. Think of the data you produce as a product. A product has an audience and marketing. - -### Platform thinking, platform teams - -Enable your software teams by building a platform of supported programming languages/runtimes, CI/CD pipeline configurations, deployment clusters, etc. so that each team does not have to spend resources reinventing the wheel. - -Provide a _golden path_ (tried and tested technologies supported by the platform team) for new projects but do not smother your engineers' freedom of choice. - -### “GenAI/LLMs are not necessarily that useful” - -Probably comes as a surprise but the latest wave of AI hype isn't very substantiated. Issues of security, trust, quality, ownership and licensing. Keep a human in the loop. - -### Safe, performant and ecological - -Running software causes carbon emissions. Choose runtimes, programming languages and hosting options that minimize idle and active compute use. - -Avoid entire categories of vulnerabilities by picking safe languages such as Rust. - -## Most inspiring talks - -### **The Home Computer That Roared: How the BBC Micro Shaped Our World** by _Jeremy Ruston_ - -A deep history dive to the advent of home computing in the UK. Jeremy was involved in building the educational BBC Micro computer as well as TV children's show animations and Doctor Who games. Super inspiring stuff, especially since I can relate to many of the constraints Jeremy et al. faced since I'm working on my very constrained "ATK16" hobby CPU project myself. - -### **Thinking like an architect** by _Gregor Hohpe (AWS)_ - -Architects find connections. Between perspectives, between technologies, between people. - -The director's budgets, risks and customer success are connected to the engineer's refactorings, scalability and backups. - -Architects are an IQ multiplier, not the smartest person in the room. Architects make other people smarter. - -### **Architecting for Data Products** by _Danilo Sato (Thoughtworks)_ - -Move from _left-to-right_ architectures (operational ↣ analytics) to a data mesh. - -Make your data discoverable and usable via different protocols and formats. Make it self-serve (platform thinking). - -> 🙋🏼 Note: I didn't know much about data mesh literature before this talk. The most useful things I got from it were the words and terms to look up, such as the _DATSIS principles_, and the books to read (see [Reading list](#reading-list)). - -### **Building Your First Platform Team** in a Fast Growing Startup by _Jessica Andersson (Kognic)_ - -The spirit of DevOps has in part transmogrified into the idea of _software platforms_. DevOps as a term has degraded to just mean Ops in many places. -Empower product teams with an explicit platform. Each company has a platform, implicit or explicit. -A _base plaform_ should provide: - -- **CI/CD**: pipeline templates, runner images, best practices -- **Runtime**: programming languages and runtimes, but also container runtimes, orchestration -- **Observability**: distributed tracing, logging, monitoring, alerting - -## Reading list {#reading-list} - -- ⭐️ [Team topologies](https://teamtopologies.com/book) by _Matthew Skelton and Manuel Pais_ -- [Domain-Driven Design](https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215) by _Eric Evans_ -- [Data Mesh](https://www.oreilly.com/library/view/data-mesh/9781492092384/) by _Zhamak Dehghani_ -- [Architect Elevator](https://architectelevator.com/) by _Gregor Hohpe_ - - all the other books by Hohpe also - -## Word dump - -I did not recognize these words or concepts. - -- attestation testing, SLSA -- server-driven UI -- DATSIS principles -- data vault architecture -- source-aligned, consumer-aligned data products -- galaxy apps -- 2-step commit -- wardley map -- BPMN (business process model and notation) -- eBPF -- expand-contract pattern -- SCI (software carbon intensity) -- WASI (WebAssembly System Interface) -- Gartner hype cycle -- trust boundary (in context of LLMs) -- LLM agent -- shift left (in context of software platforms) - -## Food and drink - -### Fantastic Indian cuisine: [Dishoom Covent Garden](https://www.dishoom.com/covent-garden/) - -You don't get Indian food like this in Finland. Super flavourful, suitably spicy. Was handed a gratis chai to drink while queuing up in the drizzling rain too. Excellent customer service. - -### Real Ale Pub: [The Harp](https://www.harpcoventgarden.com/) - -Nothing mindblowing, just good ale and a comfy vibe. A good place to sit out the rain. - -### Bloody lovely: [Duke of Argyll](https://maps.app.goo.gl/21YHi1ZBrXohhczj9) - -I had to eat fish & chips at least once just to check it off my bucket list. I don't know if theirs is the best or even proper, but I enjoyed it a lot. - -{{ fig(src="/files/fish-and-chips-duke-of-argyll.jpg", alt="Fish and chips at the Duke of Argyll") }} diff --git a/content/posts/qcon-london-2024-takeaways/fish-and-chips-duke-of-argyll.jpg b/content/posts/qcon-london-2024-takeaways/fish-and-chips-duke-of-argyll.jpg new file mode 100644 index 0000000..a9fefc8 Binary files /dev/null and b/content/posts/qcon-london-2024-takeaways/fish-and-chips-duke-of-argyll.jpg differ diff --git a/content/posts/qcon-london-2024-takeaways/index.md b/content/posts/qcon-london-2024-takeaways/index.md new file mode 100644 index 0000000..4c644e7 --- /dev/null +++ b/content/posts/qcon-london-2024-takeaways/index.md @@ -0,0 +1,112 @@ +--- +title: QCon London 2024 takeaways +date: 2024-04-20 +extra: + kind: post +--- + +QCon London 2024 was a multidisciplinary software engineering conference in the London QEII Centre in April 2024. I attended with the intention to learn about what's going on in the software-sphere. Especially in terms of software architecture. + +This was also my first time in the UK so I had to do some touristing. The weather was a bit chilly, half-cloudy with some intermittent drizzle. + +{{ fig(src="london-from-above.jpg", alt="London from above in the late evening") }} + +## Common themes + +### Data products + +A term from data mesh architecture. Think of the data you produce as a product. A product has an audience and marketing. + +### Platform thinking, platform teams + +Enable your software teams by building a platform of supported programming languages/runtimes, CI/CD pipeline configurations, deployment clusters, etc. so that each team does not have to spend resources reinventing the wheel. + +Provide a _golden path_ (tried and tested technologies supported by the platform team) for new projects but do not smother your engineers' freedom of choice. + +### “GenAI/LLMs are not necessarily that useful” + +Probably comes as a surprise but the latest wave of AI hype isn't very substantiated. Issues of security, trust, quality, ownership and licensing. Keep a human in the loop. + +### Safe, performant and ecological + +Running software causes carbon emissions. Choose runtimes, programming languages and hosting options that minimize idle and active compute use. + +Avoid entire categories of vulnerabilities by picking safe languages such as Rust. + +## Most inspiring talks + +### **The Home Computer That Roared: How the BBC Micro Shaped Our World** by _Jeremy Ruston_ + +A deep history dive to the advent of home computing in the UK. Jeremy was involved in building the educational BBC Micro computer as well as TV children's show animations and Doctor Who games. Super inspiring stuff, especially since I can relate to many of the constraints Jeremy et al. faced since I'm working on my very constrained "ATK16" hobby CPU project myself. + +### **Thinking like an architect** by _Gregor Hohpe (AWS)_ + +Architects find connections. Between perspectives, between technologies, between people. + +The director's budgets, risks and customer success are connected to the engineer's refactorings, scalability and backups. + +Architects are an IQ multiplier, not the smartest person in the room. Architects make other people smarter. + +### **Architecting for Data Products** by _Danilo Sato (Thoughtworks)_ + +Move from _left-to-right_ architectures (operational ↣ analytics) to a data mesh. + +Make your data discoverable and usable via different protocols and formats. Make it self-serve (platform thinking). + +> 🙋🏼 Note: I didn't know much about data mesh literature before this talk. The most useful things I got from it were the words and terms to look up, such as the _DATSIS principles_, and the books to read (see [Reading list](#reading-list)). + +### **Building Your First Platform Team** in a Fast Growing Startup by _Jessica Andersson (Kognic)_ + +The spirit of DevOps has in part transmogrified into the idea of _software platforms_. DevOps as a term has degraded to just mean Ops in many places. +Empower product teams with an explicit platform. Each company has a platform, implicit or explicit. +A _base plaform_ should provide: + +- **CI/CD**: pipeline templates, runner images, best practices +- **Runtime**: programming languages and runtimes, but also container runtimes, orchestration +- **Observability**: distributed tracing, logging, monitoring, alerting + +## Reading list {#reading-list} + +- ⭐️ [Team topologies](https://teamtopologies.com/book) by _Matthew Skelton and Manuel Pais_ +- [Domain-Driven Design](https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215) by _Eric Evans_ +- [Data Mesh](https://www.oreilly.com/library/view/data-mesh/9781492092384/) by _Zhamak Dehghani_ +- [Architect Elevator](https://architectelevator.com/) by _Gregor Hohpe_ + - all the other books by Hohpe also + +## Word dump + +I did not recognize these words or concepts. + +- attestation testing, SLSA +- server-driven UI +- DATSIS principles +- data vault architecture +- source-aligned, consumer-aligned data products +- galaxy apps +- 2-step commit +- wardley map +- BPMN (business process model and notation) +- eBPF +- expand-contract pattern +- SCI (software carbon intensity) +- WASI (WebAssembly System Interface) +- Gartner hype cycle +- trust boundary (in context of LLMs) +- LLM agent +- shift left (in context of software platforms) + +## Food and drink + +### Fantastic Indian cuisine: [Dishoom Covent Garden](https://www.dishoom.com/covent-garden/) + +You don't get Indian food like this in Finland. Super flavourful, suitably spicy. Was handed a gratis chai to drink while queuing up in the drizzling rain too. Excellent customer service. + +### Real Ale Pub: [The Harp](https://www.harpcoventgarden.com/) + +Nothing mindblowing, just good ale and a comfy vibe. A good place to sit out the rain. + +### Bloody lovely: [Duke of Argyll](https://maps.app.goo.gl/21YHi1ZBrXohhczj9) + +I had to eat fish & chips at least once just to check it off my bucket list. I don't know if theirs is the best or even proper, but I enjoyed it a lot. + +{{ fig(src="fish-and-chips-duke-of-argyll.jpg", alt="Fish and chips at the Duke of Argyll") }} diff --git a/content/posts/qcon-london-2024-takeaways/london-from-above.jpg b/content/posts/qcon-london-2024-takeaways/london-from-above.jpg new file mode 100644 index 0000000..a7762ed Binary files /dev/null and b/content/posts/qcon-london-2024-takeaways/london-from-above.jpg differ diff --git a/content/posts/subjective-review-miru.md b/content/posts/subjective-review-miru.md deleted file mode 100644 index d728a45..0000000 --- a/content/posts/subjective-review-miru.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: "Subjective review: Miru" -date: 2024-07-14 -extra: - kind: note ---- - -{{ fig(src="/files/miru_time_to_kill_triple.jpg", alt="A graphic from the first pages of the Miru zine with the text ”Time to kill a god” overlaid on an imposing four-eyed figure.") }} - -## TL;DR - -It’s my favorite solo game, but it has some pacing problems. 8/10. - -## Miru, the solo analog adventure - -> 🎲 **Intended audience**: people who are familiar with basic tabletop role-playing game concepts. - -[**Miru**](https://hinokodo.itch.io/miru-an-analog-adventure-game) is a journaling solo RPG adventure by _Hinokodo_. - -Solo RPGs are pen-and-paper games that require only one player to play. Whereas most tabletop games require one player to take up the role of the game master or referee, solo RPGs replace this role with various mechanisms, such as an _oracle_ or a system of _random event tables_, paired with an increased player responsibility over the progression of the game. What would be ruled by the referee in a non-solo TTRPG, is resolved instead with a roll of the dice, or some other, potentially more mechanically curious procedure. - -Many solo games, Miru included, tell a single curated story. The focus can be very narrow: the game might take place in a specific location at a specific time, for instance. Miru does not allow you to create or customize your character either, which is par for the course. Solo systems are usually not generic enough to support arbitrary settings or adventure prompts. That is one of their strengths; the system can be tightly intertwined with the story in a way that would be inconvenient or even impossible in non-solo systems. - -Solo games are mechanically diverse and often involve innovative approaches to both visuals and game design. They also tend to be rather lightweight, including only the necessary rules or content in the often somewhat slim zine. Players often have to massage their brains a bit and deduce how some properties of the game interact. This is part of the appeal, for me at least. - -> I enjoy [The Soloist](https://soloist.substack.com/) and [Dan's News](https://danews.substack.com/) for my solo RPG news. - -_Journaling_ solo games are solo games that involve writing a journal of some kind as you progress. Miru asks you to write down a short rundown of what happened on each day of your adventure. You also draw the adventure map, hex by hex, on a blank map template. - -With definitions out of the way, let me start by saying that _Miru is the best solo adventure I have played_. The creative setting, the mechanics and distinctive visual identity come together to create a cohesive, well designed experience that I can wholeheartedly recommend. However, it is not perfect. There is a bit of a pacing issue during mid-game as well as some confusing or contradictory rules that are either explained by looking up the author's comments on the [itch.io](https://hinokodo.itch.io/miru-an-analog-adventure-game) page or not explained at all. These are minor issues, though, and can be circumvented with some _GM's fiat_ (which is of course also _player's fiat_ when you're flying solo). - -## First look - -{{ fig(src="/files/miru_gameplay.jpeg", alt="The Miru zine, polyhedral dice, various stationery and other items strewn across a dining table.") }} - -Miru paints a picture of a dystopian, post-metropolitan society future where humans begrudgingly coexist with humanoid and animal-like robots. The story is kicked off in a scene where a farm worker robot kills a relative of the main character in an act of self defense when it evaluates their drunken hooliganism to be a threat. Stricken, the main character vows revenge and sets off to find out the truth about the machines’ origins. - -The game is a procedurally generated hex crawl with apocalyptic gear-scavenging mechanisms and straightforward combat with a dash of god-slaying thrown in for good measure. - -Hexes are generated by combining 3 oracle tables: - -> **_Hex type_** (mountain, grassland, swamp...) → **_Event type_** → **_Particular event_** - -Visiting a single hex takes one in-game day. The main gameplay loop is about generating a new hex, surviving the generated event, and planning your next move such that you don't lose too many resources, such as food or sleep. Near the endgame, this survival aspect turns into loadout optimization when you prepare for the final boss. - -There is also currency management. Money, or **bitliths** (a snarky reference to cryptocurrency), are used to purchase survival resources as well as equipment from villages. The available stock improves as you discover more villages: the first village has level 1 stock, the second one level 2, and all the following ones level 3. - -## My experience - -The beginning was excellent. I quickly [grokked](https://www.merriam-webster.com/dictionary/grok) the rules and the objective of the game. The first hexes were significant; you could never know if you're going to get important gear, or nearly die to a robot-wolf. The plot was nicely propelled forwards by special events that happened on predetermined dates, and character progression felt good. These events, as well as random events dropped little bits of lore here and there. As a big fan of From Software games and figuring out the world by reading item descriptions, this kind of soft worldbuilding hit the nail on the head. - -This well thought-out and balanced part of the game lasted maybe 10 to 20 in-game days. - -My entire playthrough lasted 41 days. In wall clock time, it lasted me over three of months. There wasn’t actually enough much gameplay to warrant multiple months of play; I just had an extended break near the near-endgame part. I felt that the pacing there was a bit off, every hex felt very same-y. I had obtained enough resources and gear for exploring to be very safe and so the random events began to mean less and less. Little by little, the grinding-adjacent preparation for the final boss fight started to feel repetitive, and so I inadvertently took a break from the game. - -I returned to the game just recently and decided that I'm just going to have a try at the boss. Screw getting the best gear, I will finish the game! This was a good call, since the battle was intense. I threw everything at my disposal at my opponent and was _just_ strong enough to defeat it with one (1) HP remaining! Talk about a close call. - -I will not spoil the final boss or the ending here, but I want to say a bit about it nevertheless. Depending on whether or not you picked up on the [solarpunky](https://en.wikipedia.org/wiki/Solarpunk) undertones of the game during your playthrough, the ending may come either as a bit of a surprise. It surprised me at least. - -There's also something that seems to be a hook for the next game in the series, [Miru 2](https://hinokodo.itch.io/miru-ii-an-analog-horror-game), subtitled "Analog Horror Game". The third installation, [Miru 3](https://www.kickstarter.com/projects/mimicpublishing/miru-3-an-analog-defense-game), is an "Analog Defense Game". I am left wondering what happens in the plot between parts two and three. - -I give Miru a solid 8 out of 10. The visuals, the theme, the mechanics, and the overall vibe are all excellent. The grindy bit in the middle was really the only thing that reduced my enjoyment somewhat. Note however that your mileage may vary. Everything is determined by a roll of the dice. - -## Mixed media addendum - -I love mixed media art. Combining disciplines and breaking traditional boundaries makes great art. - -With that in mind, the designer has released an official soundtrack called [Static Abyss](https://hinokodo.itch.io/static-abyss) for the Miru game series. The physical minidisk release of the soundtrack comes with some kind of game rules too, based on photos that I've seen. Sadly, it has sold out, possibly soon after its release in April 2023. The digital version is available on the itch.io page. - -The concept of a soundtrack for a physical game is badass. I own one physical release of such a thing, the Mörk Borg adventure [Putrescence Regnant](https://jnohr.itch.io/putrescence-regnant), which takes the form of a highly stylized LP disc and sleeve. Very cool. - -{{ fig(src="/files/hinokodo-static-abyss.png", alt="A photo of the Static Abyss minidisk in its enclosure") }} -Photo attribution: [Hinokodo](https://hinokodo.itch.io/static-abyss) diff --git a/content/posts/subjective-review-miru/hinokodo-static-abyss.png b/content/posts/subjective-review-miru/hinokodo-static-abyss.png new file mode 100644 index 0000000..edfac67 Binary files /dev/null and b/content/posts/subjective-review-miru/hinokodo-static-abyss.png differ diff --git a/content/posts/subjective-review-miru/index.md b/content/posts/subjective-review-miru/index.md new file mode 100644 index 0000000..59ec7e4 --- /dev/null +++ b/content/posts/subjective-review-miru/index.md @@ -0,0 +1,73 @@ +--- +title: "Subjective review: Miru" +date: 2024-07-14 +extra: + kind: note +--- + +{{ fig(src="miru_time_to_kill_triple.jpg", alt="A graphic from the first pages of the Miru zine with the text ”Time to kill a god” overlaid on an imposing four-eyed figure.") }} + +## TL;DR + +It’s my favorite solo game, but it has some pacing problems. 8/10. + +## Miru, the solo analog adventure + +> 🎲 **Intended audience**: people who are familiar with basic tabletop role-playing game concepts. + +[**Miru**](https://hinokodo.itch.io/miru-an-analog-adventure-game) is a journaling solo RPG adventure by _Hinokodo_. + +Solo RPGs are pen-and-paper games that require only one player to play. Whereas most tabletop games require one player to take up the role of the game master or referee, solo RPGs replace this role with various mechanisms, such as an _oracle_ or a system of _random event tables_, paired with an increased player responsibility over the progression of the game. What would be ruled by the referee in a non-solo TTRPG, is resolved instead with a roll of the dice, or some other, potentially more mechanically curious procedure. + +Many solo games, Miru included, tell a single curated story. The focus can be very narrow: the game might take place in a specific location at a specific time, for instance. Miru does not allow you to create or customize your character either, which is par for the course. Solo systems are usually not generic enough to support arbitrary settings or adventure prompts. That is one of their strengths; the system can be tightly intertwined with the story in a way that would be inconvenient or even impossible in non-solo systems. + +Solo games are mechanically diverse and often involve innovative approaches to both visuals and game design. They also tend to be rather lightweight, including only the necessary rules or content in the often somewhat slim zine. Players often have to massage their brains a bit and deduce how some properties of the game interact. This is part of the appeal, for me at least. + +> I enjoy [The Soloist](https://soloist.substack.com/) and [Dan's News](https://danews.substack.com/) for my solo RPG news. + +_Journaling_ solo games are solo games that involve writing a journal of some kind as you progress. Miru asks you to write down a short rundown of what happened on each day of your adventure. You also draw the adventure map, hex by hex, on a blank map template. + +With definitions out of the way, let me start by saying that _Miru is the best solo adventure I have played_. The creative setting, the mechanics and distinctive visual identity come together to create a cohesive, well designed experience that I can wholeheartedly recommend. However, it is not perfect. There is a bit of a pacing issue during mid-game as well as some confusing or contradictory rules that are either explained by looking up the author's comments on the [itch.io](https://hinokodo.itch.io/miru-an-analog-adventure-game) page or not explained at all. These are minor issues, though, and can be circumvented with some _GM's fiat_ (which is of course also _player's fiat_ when you're flying solo). + +## First look + +{{ fig(src="miru_gameplay.jpeg", alt="The Miru zine, polyhedral dice, various stationery and other items strewn across a dining table.") }} + +Miru paints a picture of a dystopian, post-metropolitan society future where humans begrudgingly coexist with humanoid and animal-like robots. The story is kicked off in a scene where a farm worker robot kills a relative of the main character in an act of self defense when it evaluates their drunken hooliganism to be a threat. Stricken, the main character vows revenge and sets off to find out the truth about the machines’ origins. + +The game is a procedurally generated hex crawl with apocalyptic gear-scavenging mechanisms and straightforward combat with a dash of god-slaying thrown in for good measure. + +Hexes are generated by combining 3 oracle tables: + +> **_Hex type_** (mountain, grassland, swamp...) → **_Event type_** → **_Particular event_** + +Visiting a single hex takes one in-game day. The main gameplay loop is about generating a new hex, surviving the generated event, and planning your next move such that you don't lose too many resources, such as food or sleep. Near the endgame, this survival aspect turns into loadout optimization when you prepare for the final boss. + +There is also currency management. Money, or **bitliths** (a snarky reference to cryptocurrency), are used to purchase survival resources as well as equipment from villages. The available stock improves as you discover more villages: the first village has level 1 stock, the second one level 2, and all the following ones level 3. + +## My experience + +The beginning was excellent. I quickly [grokked](https://www.merriam-webster.com/dictionary/grok) the rules and the objective of the game. The first hexes were significant; you could never know if you're going to get important gear, or nearly die to a robot-wolf. The plot was nicely propelled forwards by special events that happened on predetermined dates, and character progression felt good. These events, as well as random events dropped little bits of lore here and there. As a big fan of From Software games and figuring out the world by reading item descriptions, this kind of soft worldbuilding hit the nail on the head. + +This well thought-out and balanced part of the game lasted maybe 10 to 20 in-game days. + +My entire playthrough lasted 41 days. In wall clock time, it lasted me over three of months. There wasn’t actually enough much gameplay to warrant multiple months of play; I just had an extended break near the near-endgame part. I felt that the pacing there was a bit off, every hex felt very same-y. I had obtained enough resources and gear for exploring to be very safe and so the random events began to mean less and less. Little by little, the grinding-adjacent preparation for the final boss fight started to feel repetitive, and so I inadvertently took a break from the game. + +I returned to the game just recently and decided that I'm just going to have a try at the boss. Screw getting the best gear, I will finish the game! This was a good call, since the battle was intense. I threw everything at my disposal at my opponent and was _just_ strong enough to defeat it with one (1) HP remaining! Talk about a close call. + +I will not spoil the final boss or the ending here, but I want to say a bit about it nevertheless. Depending on whether or not you picked up on the [solarpunky](https://en.wikipedia.org/wiki/Solarpunk) undertones of the game during your playthrough, the ending may come either as a bit of a surprise. It surprised me at least. + +There's also something that seems to be a hook for the next game in the series, [Miru 2](https://hinokodo.itch.io/miru-ii-an-analog-horror-game), subtitled "Analog Horror Game". The third installation, [Miru 3](https://www.kickstarter.com/projects/mimicpublishing/miru-3-an-analog-defense-game), is an "Analog Defense Game". I am left wondering what happens in the plot between parts two and three. + +I give Miru a solid 8 out of 10. The visuals, the theme, the mechanics, and the overall vibe are all excellent. The grindy bit in the middle was really the only thing that reduced my enjoyment somewhat. Note however that your mileage may vary. Everything is determined by a roll of the dice. + +## Mixed media addendum + +I love mixed media art. Combining disciplines and breaking traditional boundaries makes great art. + +With that in mind, the designer has released an official soundtrack called [Static Abyss](https://hinokodo.itch.io/static-abyss) for the Miru game series. The physical minidisk release of the soundtrack comes with some kind of game rules too, based on photos that I've seen. Sadly, it has sold out, possibly soon after its release in April 2023. The digital version is available on the itch.io page. + +The concept of a soundtrack for a physical game is badass. I own one physical release of such a thing, the Mörk Borg adventure [Putrescence Regnant](https://jnohr.itch.io/putrescence-regnant), which takes the form of a highly stylized LP disc and sleeve. Very cool. + +{{ fig(src="hinokodo-static-abyss.png", alt="A photo of the Static Abyss minidisk in its enclosure") }} +Photo attribution: [Hinokodo](https://hinokodo.itch.io/static-abyss) diff --git a/content/posts/subjective-review-miru/miru_gameplay.jpeg b/content/posts/subjective-review-miru/miru_gameplay.jpeg new file mode 100644 index 0000000..51d8d44 Binary files /dev/null and b/content/posts/subjective-review-miru/miru_gameplay.jpeg differ diff --git a/content/posts/subjective-review-miru/miru_time_to_kill_triple.jpg b/content/posts/subjective-review-miru/miru_time_to_kill_triple.jpg new file mode 100644 index 0000000..97be7fe Binary files /dev/null and b/content/posts/subjective-review-miru/miru_time_to_kill_triple.jpg differ diff --git a/content/posts/theres-an-rss-feed-now.md b/content/posts/theres-an-rss-feed-now.md deleted file mode 100644 index 8ec5448..0000000 --- a/content/posts/theres-an-rss-feed-now.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: There's an RSS feed now -date: 2024-02-15 -extra: - kind: note ---- - -As part of the site build process, I use [`pandoc-rss`](https://github.com/chambln/pandoc-rss) to automatically build an RSS feed of my posts. - -![](https://jan.systems/files/internet_surf.png) diff --git a/content/posts/theres-an-rss-feed-now/index.md b/content/posts/theres-an-rss-feed-now/index.md new file mode 100644 index 0000000..e52db1a --- /dev/null +++ b/content/posts/theres-an-rss-feed-now/index.md @@ -0,0 +1,10 @@ +--- +title: There's an RSS feed now +date: 2024-02-15 +extra: + kind: note +--- + +As part of the site build process, I use [`pandoc-rss`](https://github.com/chambln/pandoc-rss) to automatically build an RSS feed of my posts. + +![](internet_surf.png) diff --git a/content/posts/theres-an-rss-feed-now/internet_surf.png b/content/posts/theres-an-rss-feed-now/internet_surf.png new file mode 100644 index 0000000..7787770 Binary files /dev/null and b/content/posts/theres-an-rss-feed-now/internet_surf.png differ diff --git a/content/posts/unfold.md b/content/posts/unfold.md deleted file mode 100644 index 241703a..0000000 --- a/content/posts/unfold.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Automatic slideshows with reveal-unfold.js -date: 2024-04-21 -extra: - kind: project - slideshow: defined ---- - -## Lightning talk - -

-I recently presented a lightning talk about the IndieWeb and personal websites to my colleagues at the office. Even though I don't normally enjoy presenting, speaking about things I'm passionate about always turns out to be rather easy. The talk and the presentation that I used to support the talk were well received. -

- -{{ fig(src="/files/indieweb_presentation.png", alt="A slide from the PowerPoint presentation") }} - ---- - -## Tinkering - -

-Later, when I shared my PowerPoint slides in the IndieWeb chat, I was asked if I had considered using HTML slides instead of pptx. The thought had crossed my mind, but I didn’t have time to put the thought into practice before my talk. It was a curious idea though. -

-

-So curious in fact, that I decided to study up on the ”HTML slideshow landscape”: what kind of tools there are, how do they work on a static site, things like that. Turns out that a tool called `reveal.js` is very popular and often recommended. An idea entered my mind: what if I could turn an HTML note (like this one that you’re reading) into an HTML slideshow, in a somewhat automated fashion? -

- -{{ fig(src="/files/reveal-js-logo.png", alt="Reveal.js logo") }} - ---- - -## Literate slideshow - -- A portmanteau of _literate program_ and _slideshow_ -- Convert a semantically marked up post to a slideshow with a click -- This post is a literate slideshow - ---- - -## Direction - -I don't know if I'll even need this project. Maybe I'll use it in some posts in the future? diff --git a/content/posts/unfold/index.md b/content/posts/unfold/index.md new file mode 100644 index 0000000..8ab3b89 --- /dev/null +++ b/content/posts/unfold/index.md @@ -0,0 +1,42 @@ +--- +title: Automatic slideshows with reveal-unfold.js +date: 2024-04-21 +extra: + kind: project + slideshow: defined +--- + +## Lightning talk + +

+I recently presented a lightning talk about the IndieWeb and personal websites to my colleagues at the office. Even though I don't normally enjoy presenting, speaking about things I'm passionate about always turns out to be rather easy. The talk and the presentation that I used to support the talk were well received. +

+ +{{ fig(src="indieweb_presentation.png", alt="A slide from the PowerPoint presentation") }} + +--- + +## Tinkering + +

+Later, when I shared my PowerPoint slides in the IndieWeb chat, I was asked if I had considered using HTML slides instead of pptx. The thought had crossed my mind, but I didn’t have time to put the thought into practice before my talk. It was a curious idea though. +

+

+So curious in fact, that I decided to study up on the ”HTML slideshow landscape”: what kind of tools there are, how do they work on a static site, things like that. Turns out that a tool called `reveal.js` is very popular and often recommended. An idea entered my mind: what if I could turn an HTML note (like this one that you’re reading) into an HTML slideshow, in a somewhat automated fashion? +

+ +{{ fig(src="reveal-js-logo.png", alt="Reveal.js logo") }} + +--- + +## Literate slideshow + +- A portmanteau of _literate program_ and _slideshow_ +- Convert a semantically marked up post to a slideshow with a click +- This post is a literate slideshow + +--- + +## Direction + +I don't know if I'll even need this project. Maybe I'll use it in some posts in the future? diff --git a/content/posts/unfold/indieweb_presentation.png b/content/posts/unfold/indieweb_presentation.png new file mode 100644 index 0000000..e9d0096 Binary files /dev/null and b/content/posts/unfold/indieweb_presentation.png differ diff --git a/content/posts/unfold/reveal-js-logo.png b/content/posts/unfold/reveal-js-logo.png new file mode 100644 index 0000000..f7b671f Binary files /dev/null and b/content/posts/unfold/reveal-js-logo.png differ -- cgit v1.3