feat: entire blog now looks good :thumbs_up:
All checks were successful
ci/woodpecker/manual/woodpecker Pipeline was successful

This commit is contained in:
hexlocation 2025-02-19 22:41:31 +01:00
parent 014a99d7e2
commit f76196b017
Signed by: hex
GPG key ID: A19EFFAAF8C00FCF
18 changed files with 2584 additions and 3 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
build
node_modules
_site

17
.woodpecker.yaml Normal file
View file

@ -0,0 +1,17 @@
when:
branch: ["main"]
event: ["push", "manual"]
steps:
- name: build
image: woodpeckerci/plugin-docker-buildx
settings:
repo: git.iwakura.rip/iwakura/blog
platforms: linux/amd64
dockerfile: Dockerfile
tags:
["${CI_COMMIT_BRANCH}-latest", "${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA}"]
username: hex
registry:
git.iwakura.rip
password:
from_secret: gitpat

25
Dockerfile Normal file
View file

@ -0,0 +1,25 @@
FROM docker.io/node:23-alpine3.20 as compiled
WORKDIR /tmp
USER root
# Copy the source code into the temp folder.
COPY . /tmp
# Installing the dependencies required for compiling.
RUN npm install
RUN npm install @11ty/eleventy -g
RUN npm run compile
FROM docker.io/jitesoft/lighttpd as main
ARG UID=82
ARG GID=82
RUN mkdir -p /html /logs
COPY --chown=$UID:$GID --from=compiled /tmp/build/ /html
RUN chown -R $UID:$GID /html
RUN chown -R $UID:$GID /logs
COPY --chown=$UID:$GID --from=compiled /tmp/config/lighttpd.conf /etc/lighttpd/lighttpd.conf

View file

@ -1,3 +1,4 @@
# blog
iwakura.rip blog
# iwakura blog
This repository contains the blog we run under the iwakura.rip domain. It is made using [11ty](https://11ty.dev).
The main branch contains the production version of our blog running [here](https://blog.iwakura.rip). The review branch contains blog posts that need to be reviewed.

28
config/lighttpd.conf Normal file
View file

@ -0,0 +1,28 @@
server.modules += ("mod_accesslog", "mod_rewrite", "mod_dirlisting", "mod_staticfile")
# General daemon settings
server.username = "www-data"
server.groupname = "www-data"
server.port = 80
server.max-fds = 600
server.follow-symlink = "enable"
# Security
static-file.exclude-extensions = (".php", ".pl", ".cgi", ".fcgi", "~")
url.access-deny = ("~", ".inc")
# Content
server.document-root = "/html"
server.indexfiles = ("index.html", "index.htm")
server.error-handler = "/error.html"
mimetype.assign = ( ".png" => "image/png",
".jpg" => "image/jpeg",
".jpeg" => "image/jpeg",
".html" => "text/html",
".txt" => "text/plain;charset=utf-8",
".css" => "text/css" )
server.errorlog = "/logs/error.log"
accesslog.filename = "/logs/access.log"
server.breakagelog = "/logs/breakage.log"

18
eleventy.config.js Normal file
View file

@ -0,0 +1,18 @@
import markdownIt from "markdown-it";
import mkgh from "markdown-it-github-alerts";
export default function(eleventyConfig) {
const options = {
html: true,
breaks: true,
linkify: true,
};
const md = markdownIt(options);
md.use(mkgh);
eleventyConfig.setLibrary("md", md);
eleventyConfig.addPassthroughCopy("src/fonts/typewriter.ttf");
eleventyConfig.addPassthroughCopy("src/post.css");
};

1953
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

22
package.json Normal file
View file

@ -0,0 +1,22 @@
{
"name": "iwakura-blog",
"version": "1.0.0",
"description": "iwakura.rip blog",
"scripts": {
"t:compile": "npx @tailwindcss/cli -i ./src/global.css -o ./build/global.css",
"t:watch": "npx @tailwindcss/cli -i ./src/global.css -o ./build/global.css --watch",
"e:compile": "eleventy --input=src --output=build",
"compile": "npm run e:compile && npm run t:compile",
"e:watch": "eleventy --input=src --output=build --serve"
},
"keywords": [],
"author": "iwakura.rip",
"license": "GPL-3.0",
"dependencies": {
"@tailwindcss/cli": "^4.0.6",
"@tailwindcss/vite": "^4.0.6",
"markdown-it": "^14.1.0",
"markdown-it-github-alerts": "^0.3.0",
"tailwindcss": "^4.0.6"
}
}

15
src/_includes/base.njk Normal file
View file

@ -0,0 +1,15 @@
<html lang="en">
<head>
<link rel="stylesheet" href="/global.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
</head>
<body class="scheme-dark bg-gray-900 px-[25%] pt-10">
<h3 id="title" class="text-3xl font-bold leading-none text-gray-200 font-[typewriter]">iwakura blog</h3>
<a class="link pl-10 text-gray-600 text-xs" href="https://iwakura.rip">by the iwakura computer club</a>
<hr class="m-3">
<div class="">
{{ content | safe }}
</div>
</body>
</html>

5
src/_includes/post.njk Normal file
View file

@ -0,0 +1,5 @@
---
layout: base.njk
---
<link rel="stylesheet" href="/post.css">
{{ content | safe }}

BIN
src/fonts/typewriter.ttf Normal file

Binary file not shown.

45
src/global.css Normal file
View file

@ -0,0 +1,45 @@
@import "tailwindcss";
@font-face {
font-family: 'typewriter';
src: url('/fonts/typewriter.ttf') format('truetype');
}
body {
/* background-color: #0E0E0E;*/
color: white;
}
a {
transition: 0.5s;
}
a:hover:not(.postbtn) {
font-size: var(--text-lg);
}
hr {
opacity: 0.4;
}
.blogbox {
border: 1px solid var(--color-gray-500);
background-color: var(--color-gray-800);
border-radius: 5px;
padding: 0.6vw;
transition: 0.2s;
line-height: 1.3vw;
}
.blogbox:hover {
border-color: var(--color-gray-300);
scale: 1.05;
}
/*
#header h3, #links a {
display: inline;
}
#page {
padding: 10px 15%;
}*/

23
src/index.html Normal file
View file

@ -0,0 +1,23 @@
---
layout: base.njk
title: Blog Posts
---
<div id="content">
<h1 class="text-3xl font-bold">Posts</h1>
<ul class="px-1 py-2">
{%- for post in collections.post -%}
<li class="py-2">
<a href="{{ post.url | url }}" class="postbtn">
<div class="blogbox">
<h2 class="text-gray-200">{{ post.data.title }}</h2>
<p class="text-gray-500 text-xs">{{ post.date }}</p>
<p id="preview" class="text-gray-400">{{ post.data.desc }}</p>
</div>
</a>
</li>
{%- endfor -%}
</ul>
<p>Want to help out reviewing (upcoming) blog posts? See the "review" branch at the <a
href="https://git.iwakura.rip/iwakura/blog">git repository</a> for this blog!</p>
</div>

52
src/post.css Normal file
View file

@ -0,0 +1,52 @@
code {
font-size: var(--text-base);
}
pre {
background-color: var(--color-gray-800);
overflow: auto;
padding: 0.5vw;
margin: 0.5vw 0;
}
blockquote {
box-sizing: revert;
margin: revert;
padding: revert;
border: revert;
}
.markdown-alert-title {
font-family: 'typewriter';
display: flex;
gap: 5px;
align-items: center;
width: auto;
}
.markdown-alert-warning .markdown-alert-title {
fill: var(--color-red-400);
color: var(--color-red-400);
}
.markdown-alert {
padding: 1vw;
}
blockquote {
font-style: italic;
}
h1, h2, h3:not(#title), h4, h5 {
font-weight: revert;
font-size: revert;
margin-top: 10px;
}
a {
transition: 0.5s;
}
a:hover {
font-size: var(--text-lg);
}

33
src/posts/classicube1.md Normal file
View file

@ -0,0 +1,33 @@
---
title: "ClassiCube: Minecraft Classic, reimagined!"
desc: ""
tags: post
date: 2024-08-17
---
# ClassiCube: Minecraft Classic, reimagined!
I had recently taken an interest again in the Minecraft Classic community, seeing as how this part of the Minecraft community is very different from your average Minecraft player.
This part of the Minecraft community is much more focussed on the building & modding aspect of Minecraft, rather than Minecraft's (mostly competitive) gamemodes, making it an excellent platform to let your creativity free.
![Classicube (Netherlands) on Not Awesome 2](/assets/classicube/nl.png)
![Classicube (Linux) on Not Awesome 2](/assets/classicube/linux.png)
## ClassiCube? That doesn't sound like Minecraft Classic?
You'd be right. ClassiCube is (atleast nowadays) much more focussed on **continuing** from Minecraft Classic, rather than **being** Minecraft Classic, although this used to be their main focus, from what i can find.
ClassiCube is basically what the team at CC imagines Minecraft Classic (and onwards) should have been, although some features are pretty weird and/or quality-of-life (think about, built-in "hacks" to navigate around), i would personally consider this an entire game in itself.
ClassiCube also features its own client built entirely from scratch in C (wen rust rewrite???), mimicing the look and feel of the Minecraft Classic client, while being much more performant and moddable.
## Alright, sign me up!
You can [register here](https://classicube.net) & download their client.
My in-game name is ``hexlocation``, say hi if you see me :)
### More screenshots :)
![Server List](/assets/classicube/serverlist.png)
![Freebuild Map on Not Awesome 2](/assets/classicube/ingame.png)
-- hex

224
src/posts/init.md Normal file
View file

@ -0,0 +1,224 @@
---
title: "Hijacking your init system for fun and profit!"
desc: "Click here for some hackery."
tags: post
date: 2024-11-20
---
# Hijacking your init system for fun and profit!
## Prologue
Recently, I have begun messing with the Linux kernel, modifying some code, printing out some ascii art and making a very tiny initramfs without busybox for fun. This has made me aware of the fact that your init system resides in (or is bootstrapped from) a **single** binary! So, as one typically does, I decided to mess around with the things you can do when running as the init system.
## Replacing your init system
Ah yes, irresponsibly modifying your system files, the killer of immutable distros...
So... how would one replace their init system? Well, to test this, I wrote a simple C program to print out hello world...
```
#include <stdlib.h>
int main() {
printf("Hello world! This is init speaking to you from the linux kernel.\n");
return 0;
}
```
I compiled it with ``gcc test.c``, ran it by adding init=\<path to binary\> to my kernel parameters, and... it failed?
```
[ 1.547957] Failed to execute /test (error -2)
[ 1.549016] Default init /sbin/init failed (error -2)
[ 1.550202] Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance.
[ 1.550792] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.6.62_1 #1
[ 1.551034] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
[ 1.551468] Call Trace:
[ 1.551602] <TASK>
[ 1.551921] dump_stack_lvl+0x47/0x60
[ 1.552280] panic+0x180/0x340
[ 1.552392] ? __pfx_kernel_init+0x10/0x10
[ 1.552509] kernel_init+0x18d/0x1f0
[ 1.552611] ret_from_fork+0x34/0x50
[ 1.552719] ? __pfx_kernel_init+0x10/0x10
[ 1.552834] ret_from_fork_asm+0x1b/0x30
[ 1.552978] </TASK>
[ 1.553421] Kernel Offset: 0x1d000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
[ 1.553901] ---[ end Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance. ]---
```
Oh, right... my test environment doesn't include any libraries, it's just a cpio image with the binary at /test! Oh well, we can fix that! I added ``-static`` to the GCC flags to include the libraries with the binary, and...
```
Hello world! This is init speaking to you from the linux kernel.
[ 1.615461] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000
[ 1.616336] CPU: 0 PID: 1 Comm: init Not tainted 6.6.62_1 #1
[ 1.616712] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
[ 1.617199] Call Trace:
[ 1.617343] <TASK>
[ 1.617494] dump_stack_lvl+0x47/0x60
[ 1.617882] panic+0x180/0x340
[ 1.617987] do_exit+0x9c1/0xb40
[ 1.618097] do_group_exit+0x31/0x80
[ 1.618205] __x64_sys_exit_group+0x18/0x20
[ 1.618326] do_syscall_64+0x5a/0x80
[ 1.618457] ? __count_memcg_events+0x73/0xc0
[ 1.618595] ? count_memcg_events.constprop.0+0x1a/0x30
[ 1.618749] ? handle_mm_fault+0xa2/0x360
[ 1.618865] ? preempt_count_add+0x4b/0xa0
[ 1.618978] ? up_read+0x3b/0x80
[ 1.619087] ? do_user_addr_fault+0x30b/0x620
[ 1.619211] ? fpregs_assert_state_consistent+0x26/0x50
[ 1.619353] ? exit_to_user_mode_prepare+0x40/0x1b0
[ 1.619489] entry_SYSCALL_64_after_hwframe+0x78/0xe2
[ 1.619785] RIP: 0033:0x4172b5
[ 1.620186] Code: ff ff ff c3 48 c7 c0 c0 ff ff ff 64 c7 00 26 00 00 00 eb ea 90 48 c7 c6 c0 ff ff ff ba e7 00 00 00 eb 03 66 90 f4 89 d0 0f 05 <48> 3d 00 f0 ff ff 76 f3 f7 d8 64 89 06 eb0
[ 1.620764] RSP: 002b:00007fffe87e5058 EFLAGS: 00000206 ORIG_RAX: 00000000000000e7
[ 1.621005] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00000000004172b5
[ 1.621210] RDX: 00000000000000e7 RSI: ffffffffffffffc0 RDI: 0000000000000000
[ 1.621407] RBP: 0000000000000000 R08: 00007fffe87e4f58 R09: 000000000000001c
[ 1.621627] R10: 0000000000000007 R11: 0000000000000206 R12: 0000000000000001
[ 1.621830] R13: 0000000000000000 R14: 000000000049d100 R15: 000000000049f3e0
[ 1.622077] </TASK>
[ 1.622537] Kernel Offset: 0x22000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
[ 1.623075] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000 ]---
```
**It worked!** We have successfully created our own init system, if you will.
## Replacing your init system on a real system.
Right, so now we have our own, working "init system", but **what if we want to do this on a real system, while still being able to boot**?
It's simple, really! Make your init system redirect execution to the "real" init system. We can do this by executing the execve syscall at the end of our C program, passing /sbin/init as the argument.
From the execve man page:
> **execve**() executes the program referred to by _pathname_. This
causes the program that is currently being run by the calling
process to be replaced with a new program, with newly initialized
stack, heap, and (initialized and uninitialized) data segments.
My simple C program now looks like this:
```
#include <stdlib.h>
int main() {
printf("Hello world! This is init speaking to you from the linux kernel.\n");
execve("/sbin/init", NULL, NULL); // redirect execution to the real init system
return 0;
}
```
And... it now boots!
## What do we do now?
> [!WARNING]
> This section *should* be safe to follow on a production system, but could still brick it. I am not responsible for any damage you cause to your system.
What everyone wants of course! Some ascii art! For this, I have made a simple C program that slowly reads out a file on the root filesystem and centers it.
I have gone through many revisions, but here is the final (janky) program I came up with.
```
#include <math.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mount.h>
#include <unistd.h>
#include <asm/termbits.h>
#include <sys/ioctl.h>
#include <string.h>
#include <linux/kd.h>
int main(void)
{
FILE *fptr;
char c;
struct winsize ws;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1) {
printf("fuck the terminal size");
}
fptr = fopen("/sequence", "r");
if (fptr == NULL) {
printf("Couldn't find file!");
return 1;
}
char line[256];
memset(line, 0, sizeof(line)); // clear line string
while ((c = fgetc(fptr)) != EOF) {
int len = strlen(line);
line[len] = c; // append char to string
if (c == '\n') {
int width = round(
len +
(ws.ws_col - len) /
2); // calculate appropriate width to add to start of line
char line_no_padding[sizeof(
line)]; // copy line without the padding for use in formatting
memcpy(line_no_padding, line,
sizeof(line_no_padding)); // copy old line var to line_no_padding
sprintf(line, "%*s", width,
line_no_padding); // recycle old line var for new line with padding
// slowly print out each char
for (int i = 0; i < strlen(line) + 1; i++) {
printf("%c", line[i]); // print char
if (line[i] != ' ')
usleep(25 *
1000); // sleep if char is not a space
fflush(stdout); // flush tty
}
memset(line, 0,
sizeof(line)); // clear the line to make room for the next line
}
}
fclose(fptr);
execve("/sbin/init", NULL, NULL);
return 0;
}
```
Compile with ``gcc -static main.c`` and move the resulting binary to /splash, and then put your ascii art into ``/sequence``. Here's mine:
```
#######################################################################################
# #
# ..####....####...######...####............####....####.. |\---/| #
# .##......##..##....##....##..##..........##..##..##..... | ,_, | #
# .##.###..######....##....##..##..........##..##...####.. \_`_/-..----. #
# .##..##..##..##....##....##..##..........##..##......##. ___/ ` ' ,""+ \ meow #
# ..####...##..##....##.....####............####....####.. (__...' __\ |`.___.'; #
# ........................................................ (_,...'(_,.`__)/'.....+ #
# #
#######################################################################################
doing some tomfoolery...
```
Now the last thing you need to do is modify your bootloader to use /splash, this can be done by changing the init parameter to /splash. If you use grub, append ``init=/splash`` to GRUB_CMDLINE_LINUX_DEFAULT, and run ``update-grub``.
Tada! You now have some fancy ascii art at boot.
-- hex

114
src/posts/micros.md Normal file
View file

@ -0,0 +1,114 @@
---
title: "Migrating all of my servers over to OpenSUSE MicroOS - and discovering Podman Quadlet."
desc: "Wake up, it is 2025. Stop using Debian."
tags: post
date: 2024-12-18
---
# Migrating all of my servers over to OpenSUSE MicroOS.
## Why?
TL;DR: Grew tired of Debian, wanted something immutable and low-maintenance.
Every single server I have ever touched has always turned into a mess, because random packages with no use to me that held back updates and/or bloated my system (For context, my main server, which hosts my arr stack and some other services, has ~1700 packages installed, which is a lot, as I mainly only use Docker to deploy services), or even packages that have completely broken all kinds of libraries and required me to spend a Saturday reinstalling.
Furthermore, I do not have a lot of time anymore to maintain everything, as my real life is starting to take up more and more space. The fact that I use most of the things I host on a daily basis ment that I had to start finding alternatives.
And find an alternative I did. It's called OpenSUSE MicroOS.
It has been developed by a reputable company called OpenSUSE, it targets container workloads, it is easy to deploy en masse using something like Combustion (although I won't be taking full advantage of this, I only have 2 nodes as of writing this) & **minimal maintenance**, as Micro OS auto-updates and can rollback automatically in the event of a failed update. This right here is the most crucial part.
The only downside I have found so far is... well... it uses systemd.
However, even systemd haters like myself have to admit - it has the (financial) support of multiple big companies, it is the most widely used init system today, and the most secure. OpenRC or runit are not really viable alternatives on servers, as they just aren't popular enough. I will **never** use systemd on any of my desktop machines though - don't worry!
All of this combined makes MicroOS the perfect choice. So... how do we get started?
## Installing MicroOS
Installing it is actually extremely simple. [Download](https://download.opensuse.org/tumbleweed/iso/openSUSE-MicroOS-DVD-x86_64-Current.iso) the iso pre-packaged with Podman (note: combustion and ignition are not enabled on the iso image provided by OpenSUSE), flash it to a usb stick and you're good to go.
You'll notice that MicroOS boots up pretty fast for a systemd distro. Took around 5-6 seconds to boot on my Dell Optiplex 3050 Micro. Once it has finished booting, it will ask you some simple questions and now you're done!
Once you have booted into the system, make sure you add your SSH key(s) and change the hostname, as is standard practice.
## Deploying services using Podman
Something I found out later while trying to install MicroOS in a VM for the first time is that there was no option to pre-install Docker, only Podman was available!
I thought this was a good excuse for me to try Podman as I had heard of it before but didn't exactly know why I should be using it.
Initially I started by installing Podman Compose, but quickly realized something while looking at blog posts others had made on deploying using Podman - they were all using [Podman Quadlet](https://www.redhat.com/en/blog/quadlet-podman). This looked pretty cool to me, so I decided to delve a little deeper.
Quadlet is, in short, a way to easily declare and deploy containers, like docker/podman compose. But instead of using docker compose, you let systemd do all the hard work for you.
Here's what a container deployment looks like using Quadlet:
```
# /etc/containers/systemd/caddy.container
[Unit]
Description=Caddy reverse proxy
After=local-fs.target
[Container]
Image=caddy:latest
PublishPort=80:80
PublishPort=443:443
Volume=/var/caddy:/etc/caddy
Volume=caddydata.volume:/data
Volume=caddyconfig.volume:/config
[Service]
Restart=always
[Install]
WantedBy=multi-user.target
```
...looks pretty similar to a systemd service right?
To get systemd to recognize these files, Podman uses a so called "systemd generator", called [podman-systemd.unit](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html). This generator dynamically translates those aforementioned .container files into fully working systemd services. Awesome!
So... how do we deploy this?
It's simple, really:
1. Put the given container file into /etc/containers/systemd/caddy.container
2. Create two files named caddydata.volume and caddyconfig.volume. You can compare these to named volumes in Docker.
3. Reload systemd using ``systemd daemon-reload``
4. Start the container using ``systemctl start caddy``
And now we have caddy up and running... right?
> WARNING: Do not use this on special system directories like /home or /bin. It WILL break your system (according to the docker manual).
Well, It's not that simple. You see, MicroOS uses SELinux. In short, SELinux defines policies for every application, file, directory etc, and it doesn't play well with container volumes by default. Using this in its current state, caddy wouldn't be able to read or write anything. Fortunately, this is just a simple fix. Add a single z to any lines that define a volume, like so:
```
# /etc/containers/systemd/caddy.container
[Unit]
Description=Caddy reverse proxy
After=local-fs.target
[Container]
Image=caddy:latest
PublishPort=80:80
PublishPort=443:443
Volume=/var/caddy:/etc/caddy:z
Volume=caddydata.volume:/data:z
Volume=caddyconfig.volume:/config:z
[Service]
Restart=always
[Install]
WantedBy=multi-user.target
```
And now we have a working container! It's as simple as that.
## Note on Libreboot
Something I've had to deal with is that Libreboot does not want to boot MicroOS. I have yet to find out why, but I found a simple workaround; just use SeaBIOS instead by pressing esc at boot, and select your boot medium.
-- hex⏎

3
src/posts/posts.json Normal file
View file

@ -0,0 +1,3 @@
{
"layout": "post.njk"
}