mljr.eu
Open to opportunities

Hi, I'm Michael.

I build

Dipl.-Ing. in Computer Science (Networks & IT Security) from JKU Linz, now an IT Security Engineer at Land Oberösterreich. My master thesis abstracted cloud permission systems into a Prolog-based metamodel. I care about correctness, performance, and shipping things that actually work.

Michael Reinegger
Michael Reinegger
Linz, Austria
Current focus
IT Security @ Land OÖ
Linz, Austria
Near
Linz, Austria
Open to interesting projects
MSc / Dipl.-Ing.
Networks & IT Security
JKU Linz · 2026
Homelab
VPS edge + home servers
Caddy · CrowdSec · Tailscale
23
Projects
11+
Years coding
8+
Yrs coding
23
Projects
7
Companies
3
Degrees
Go
Rust
TypeScript
Python
Docker
Linux
Puppet
Tailscale
Grafana
Svelte
Kotlin
Security
Networking
Homelab
IAM / PAM
Embedded
PostgreSQL
SQLite
02

Projects

13 projects
glucava 1
glucava 2
glucava 3
glucava 4
glucava 5
glucava 6

Glucava

After a Strava activity ends, Glucava reads your glucose data (Dexcom Share, FreeStyle Libre, Nightscout) and writes time in range, min, max, average and a sparkline into the activity description, opt…

GoPocketBaseDatastarStrava
LSTM-Based-Speaker-Diarization 1
LSTM-Based-Speaker-Diarization 2
LSTM-Based-Speaker-Diarization 3
LSTM-Based-Speaker-Diarization 4

LSTM Based Speaker Diarization

Bachelor thesis research implementing LSTM and BiLSTM networks for speaker diarization — the task of labeling who speaks when in an audio recording. Compares d-vector generation architectures and four…

PythonPyTorchMachine LearningAudio
cg-lab-2023-project-reineggersilber 1
cg-lab-2023-project-reineggersilber 2
cg-lab-2023-project-reineggersilber 3

Cg Lab 2023 Project Reineggersilber

A university computer graphics lab project implementing real-time animated 3D scenes directly against raw WebGL (no engine, no three.js) using hand-rolled GLSL shaders. A person wanders a furnished ro…

JavaScriptWebGLGLSLComputer Graphics
face-auth 1
face-auth 2
face-auth 3
face-auth 4

Face Auth

★ 1

A Linux PAM module for facial recognition login using IR cameras and Windows Hello–compatible hardware. Features liveness anti-spoofing, an egui graphical configuration tool, and plugs into any PAM st…

RustPAMSecurityLinux
jku-master-project-network-devices-power-consumption-analysis 1
jku-master-project-network-devices-power-consumption-analysis 2
jku-master-project-network-devices-power-consumption-analysis 3
jku-master-project-network-devices-power-consumption-analysis 4

Jku Master Project Network Devices Power Consumption Analysis

★ 1

A master's project measuring the power consumption of network devices under different traffic loads. A FritzBox smart plug captures energy data while Go tooling generates UDP, TCP, and Layer-2 loads; …

TeXGoNetworkingData Analysis
Game-of-Life-Multiplatform 1
Game-of-Life-Multiplatform 2

Game Of Life Multiplatform

★ 1

Conway's Game of Life implemented as a Kotlin Multiplatform project for desktop and Android. Developed as a university programming project exploring KMP's shared logic and platform-specific UI capabil…

KotlinMultiplatformSimulation
Lebenslauf 1
Lebenslauf 2
Lebenslauf 3

Lebenslauf

Source files for my CV and cover letter written in Typst — a modern typesetting language. Clean, version-controlled, and trivially re-compilable to PDF.

TypstResumePDF
webcambot 1
webcambot 2
webcambot 3
webcambot 4

Webcambot

A Discord bot that fetches snapshots and video clips from Home Assistant camera entities on command. Configurable clip lengths and instant image delivery make it useful for home monitoring over Discor…

PythonDiscordHome Assistant
Flexbar-Plugin-Youtube-Music-Desktop-App

Flexbar Plugin Youtube Music Desktop App

★ 1

A Node.js plugin for the Flexbar macro pad that controls YouTube Music Desktop App via Socket.IO. Shows the current track, album art, and playback controls directly on the Flexbar display.

JavaScriptTypeScriptPluginDesktop
WordWiz 1
WordWiz 2
WordWiz 3

WordWiz

A SvelteKit word finder and unscrambler: type a bag of letters and it returns every word that can be made from them, in English or German, filtered to a chosen length range. Backed by 450k+ and 670k+ …

JavaScriptTypeScriptSvelteKitWeb
nightscout-display 1
nightscout-display 2

Nightscout Display

A Stream Deck plugin that shows live Nightscout CGM glucose readings on a Stream Deck key. Supports numeric display and a scrolling sparkline graph, with configurable time ranges and color-coded alert…

TypeScriptGoNightscoutStream Deck
AdventOfCode2022_MrCode

AdventOfCode2022 MrCode

Advent of Code 2022 solutions in Kotlin, exploring algorithmic challenges across the December puzzle calendar.

KotlinAlgorithmsPuzzles
AOC2024

AOC2024

Advent of Code 2024 solutions written in Kotlin, working through all December puzzles with clean, readable implementations.

KotlinAlgorithmsPuzzles
03

Live Tools

3 live tool

Regex Lab

LIVE

An interactive regex workbench built in Go + Datastar. Uses regexp2 (PCRE-compatible engine) for backreferences, lookahead, and lookbehind. Matches highlight as you type via server-sent events, with a built-in cheat sheet and 20+ preset examples.

GoRegexPCREDatastarSSE

Cron Explorer

LIVE

An interactive cron expression explorer built in Go + Datastar. Supports standard 5-field and 6-field (with seconds) syntax, @aliases, and common presets. Shows a field-by-field breakdown and the next 10 execution times with countdown.

GoCronDatastarSSE

Codec

LIVE

A multi-mode encode/decode tool built in Go + Datastar. Hash mode computes all four digests simultaneously. Encoding modes support Base64, URL percent-encoding, and HTML entity encoding — all processed server-side via SSE.

GoCryptoBase64DatastarSSE
04

Playground

old side projects, rebuilt

AI Snake

Snake plays itself by following a fixed loop through every cell on the board — a mathematical guarantee it can never trap itself.

AI Snake Live

One snake game running on the server, played by a tiny neural network — everyone on the page watches the same game live.

Snake

The classic, keyboard-controlled. Eat apples, grow longer, don't hit the wall or yourself.

Minenfeld

Cross a minefield one row at a time — one wrong step and it's over.

Double Pendulum

A chaotic n-segment pendulum — tune the physics and watch tiny changes explode into wildly different motion.

Fourier Drawing

Draw any shape and watch a stack of rotating circles reconstruct it from pure sine waves.

Boids

A flock that organizes itself from three simple local rules — no leader, no plan, just steering.

Particle Life

Colored particles that attract and repel each other by simple pairwise rules — and organize into swarming, chasing clusters on their own.

Maze

Watch a maze carve itself out cell by cell, then watch a breadth-first search solve it.

Sorting Visualizer

Race classic sorting algorithms as animated bars and watch how differently each one earns its comparisons and swaps.

05

Open Source

live data
Contributions

A year of commits

MonWedFriDec10 contributions on Dec 1011 contributions on Dec 123 contributions on Dec 161 contributions on Dec 174 contributions on Dec 187 contributions on Dec 1911 contributions on Dec 209 contributions on Dec 2113 contributions on Dec 2210 contributions on Dec 2311 contributions on Dec 275 contributions on Dec 2813 contributions on Dec 2911 contributions on Dec 307 contributions on Dec 31Jan3 contributions on Jan 13 contributions on Jan 21 contributions on Jan 33 contributions on Jan 45 contributions on Jan 59 contributions on Jan 1120 contributions on Jan 125 contributions on Jan 1349 contributions on Jan 147 contributions on Jan 1515 contributions on Jan 1613 contributions on Jan 1743 contributions on Jan 1819 contributions on Jan 205 contributions on Jan 2121 contributions on Jan 2223 contributions on Jan 2314 contributions on Jan 2416 contributions on Jan 253 contributions on Jan 261 contributions on Jan 271 contributions on Jan 284 contributions on Jan 295 contributions on Jan 30Feb12 contributions on Feb 11 contributions on Feb 21 contributions on Feb 814 contributions on Feb 932 contributions on Feb 1022 contributions on Feb 112 contributions on Feb 142 contributions on Feb 202 contributions on Feb 2313 contributions on Feb 2412 contributions on Feb 253 contributions on Feb 2611 contributions on Feb 2717 contributions on Feb 28Mar15 contributions on Mar 13 contributions on Mar 23 contributions on Mar 112 contributions on Mar 133 contributions on Mar 143 contributions on Mar 171 contributions on Mar 205 contributions on Mar 213 contributions on Mar 222 contributions on Mar 31Apr6 contributions on Apr 42 contributions on Apr 121 contributions on Apr 164 contributions on Apr 216 contributions on Apr 22May1 contributions on May 24 contributions on May 87 contributions on May 91 contributions on May 107 contributions on May 1315 contributions on May 1418 contributions on May 151 contributions on May 1617 contributions on May 1717 contributions on May 189 contributions on May 197 contributions on May 208 contributions on May 225 contributions on May 2311 contributions on May 2416 contributions on May 2514 contributions on May 2611 contributions on May 278 contributions on May 291 contributions on May 31Jun4 contributions on Jun 11 contributions on Jun 21 contributions on Jun 105 contributions on Jun 1121 contributions on Jun 1221 contributions on Jun 138 contributions on Jun 146 contributions on Jun 1526 contributions on Jun 1628 contributions on Jun 177 contributions on Jun 186 contributions on Jun 194 contributions on Jun 205 contributions on Jun 236 contributions on Jun 281 contributions on Jun 29Jul2 contributions on Jul 11 contributions on Jul 26 contributions on Jul 34 contributions on Jul 42 contributions on Jul 144 contributions on Jul 201 contributions on Jul 211 contributions on Jul 2620 contributions on Jul 2822 contributions on Jul 291 contributions on Jul 3012 contributions on Jul 31Aug8 contributions on Aug 14 contributions on Aug 36 contributions on Aug 410 contributions on Aug 521 contributions on Aug 71 contributions on Aug 84 contributions on Aug 912 contributions on Aug 1017 contributions on Aug 1111 contributions on Aug 1241 contributions on Aug 1322 contributions on Aug 143 contributions on Aug 1614 contributions on Aug 1711 contributions on Aug 1814 contributions on Aug 191 contributions on Aug 201 contributions on Aug 2114 contributions on Aug 2249 contributions on Aug 2321 contributions on Aug 2428 contributions on Aug 2530 contributions on Aug 2611 contributions on Aug 274 contributions on Aug 2850 contributions on Aug 2926 contributions on Aug 3014 contributions on Aug 31Sep25 contributions on Sep 148 contributions on Sep 219 contributions on Sep 318 contributions on Sep 720 contributions on Sep 88 contributions on Sep 1711 contributions on Sep 2018 contributions on Sep 2112 contributions on Sep 228 contributions on Sep 2315 contributions on Sep 2425 contributions on Sep 2537 contributions on Sep 2623 contributions on Sep 2710 contributions on Sep 2835 contributions on Sep 2920 contributions on Sep 30Oct4 contributions on Oct 12 contributions on Oct 42 contributions on Oct 716 contributions on Oct 104 contributions on Oct 1611 contributions on Oct 196 contributions on Oct 2012 contributions on Oct 215 contributions on Oct 2214 contributions on Oct 2353 contributions on Oct 2449 contributions on Oct 2528 contributions on Oct 2621 contributions on Oct 2812 contributions on Oct 2913 contributions on Oct 3032 contributions on Oct 31Nov5 contributions on Nov 1
32%GO
17%SVELTE
10%JAVASCRIPT
23
Public repos
4
GitHub stars
1529
Commits / year
19d
Longest streak
06

Experience

10 positions
1
2
3
Land Oberösterreich
Land Oberösterreich
Oct 2026 – Present · 1 month

IT Security Engineer

IT security engineering at the state administration of Upper Austria.

SecurityFirewallsSaltStackActive DirectoryLDAPISO 27001
Dynatrace
Dynatrace
Nov 2025 – Sep 2026 · 11 months

Master Thesis · Software Engineer

Master thesis: abstracting complex IAM systems into a Prolog-based unified permission metamodel (completed)

GoPrologIAMSecurity
Dynatrace
Dynatrace
Aug 2025 – Sep 2025 · 2 months

Software Engineering Intern

Software engineering internship at Dynatrace Engineering Headquarters.

GoJavaSecurity
4
5
6
Johannes Kepler University Linz
Johannes Kepler University Linz
Oct 2023 – Jun 2026 · 2 yrs 9 mo

Student Assistant · Tutor

Tutor for Digital Circuits and Computer Architecture across six semesters

TeachingElectronicsArchitecture
ventopay gmbh
ventopay gmbh
Jul 2024 – Jul 2024 · 1 month

Software Development Intern

Angular and C# development of an existing cashless payment system

AngularC#UI/UX
Bosch
Bosch
Aug 2023 – Sep 2023 · 2 months

Software Development Intern

Development of a dashboard for team-relevant information with SvelteKit and TailwindCSS

SvelteKitTailwindCSSREST
7
8
9
Bosch Rexroth
Bosch Rexroth
Jun 2021 – Jun 2021 · 1 month

Assembly & Testing Intern

Assembly of cable ducts and switch cabinets

HardwareHydraulics
HerzReha Bad Ischl
HerzReha Bad Ischl
Sep 2020 – May 2021 · 9 months

Civil Servant

Support of office staff

Healthcare
ENGEL
ENGEL
Jul 2018 – Jul 2018 · 1 month

Mandatory Internship

Data processing with Excel

Manufacturing
10
ENGEL
ENGEL
Jul 2017 – Jul 2017 · 1 month

Mandatory Internship

Assistance in production

ManufacturingElectronics
Land OberösterreichOct 2026 – Present · 1 month
IT Security Engineer
Land Oberösterreich

IT security engineering at the state administration of Upper Austria.

DynatraceNov 2025 – Sep 2026 · 11 months
Master Thesis · Software Engineer
Dynatrace

Master thesis: abstracting complex IAM systems into a Prolog-based unified permission metamodel (completed)

DynatraceAug 2025 – Sep 2025 · 2 months
Software Engineering Intern
Dynatrace

Software engineering internship at Dynatrace Engineering Headquarters.

Johannes Kepler University LinzOct 2023 – Jun 2026 · 2 yrs 9 mo
Student Assistant · Tutor
Johannes Kepler University Linz

Tutor for Digital Circuits and Computer Architecture across six semesters

ventopay gmbhJul 2024 – Jul 2024 · 1 month
Software Development Intern
ventopay gmbh

Angular and C# development of an existing cashless payment system

BoschAug 2023 – Sep 2023 · 2 months
Software Development Intern
Bosch

Development of a dashboard for team-relevant information with SvelteKit and TailwindCSS

Bosch RexrothJun 2021 – Jun 2021 · 1 month
Assembly & Testing Intern
Bosch Rexroth

Assembly of cable ducts and switch cabinets

HerzReha Bad IschlSep 2020 – May 2021 · 9 months
Civil Servant
HerzReha Bad Ischl

Support of office staff

ENGELJul 2018 – Jul 2018 · 1 month
Mandatory Internship
ENGEL

Data processing with Excel

ENGELJul 2017 – Jul 2017 · 1 month
Mandatory Internship
ENGEL

Assistance in production

Education

3 degrees
Johannes Kepler University Linz
Johannes Kepler University Linz
Oct 2024 – Oct 2026

MSc Networks and IT Security

Coursework and thesis work in network security, cryptography, and formal methods.

Johannes Kepler University Linz
Johannes Kepler University Linz
Oct 2021 – Jul 2024

BSc Computer Science

Computer Science fundamentals with specialization in software engineering.

HTL Steyr
HTL Steyr
Sep 2015 – Jun 2020

Matura · Mechatronics and Robotics

Robotics, automation engineering, embedded systems, and practical technical project work.

Papers & Theses

research work
HTL

HTL Diploma Thesis

Diploma thesis at HTL Steyr (Mechatronics, Robotics & Automation).

Bachelor

Bachelor Thesis

Bachelor thesis in Computer Science at JKU Linz — LSTM-based speaker diarization.

Master

Master Thesis

Abstracting complex permission systems into a Prolog-based metamodel: an 18-predicate schema for AWS, Azure and GCP IAM, a Go gathering pipeline, a Go query engine validated against SWI-Prolog (about 3x faster) and an MCP server for AI agents. Written at Dynatrace, supervised at JKU by Prof. Stefan Rass.

Project

JKU Master Project Report

Network devices power consumption analysis — a Go-based test runner measuring UDP/TCP/L2 throughput against real-time power draw via FritzBox smart plug.

Places

work · education · home
07

Homelab

live via tailscale
Services

Self-hosted fleet

20 / 20 up
SMTP: mail.mljr.eu35 ms
authelia127 ms
cglab108 ms
gameoflife104 ms
glance79 ms
goaccess161 ms
homeassistant98 ms
homepage220 ms
immich657 ms
kuma242 ms
mailcow174 ms
nas341 ms
nextcloud350 ms
ntfy80 ms
nuc-webui194 ms
projects101 ms
sudoku120 ms
syncthing211 ms
ui-showcase177 ms
wordwiz148 ms
Tailscale mesh

Live infra topology

5 / 5 online
tailnethomeassistant — homeassistantLNXhomeassistant1 svcmljr — authelia, canarytokens, glance, ntfy, goaccess, mailcow, crowdsec, cockpit, diun, hellpot, endlessh, spidertrap, caddy-poc, homepage, ui-showcase, regex, cron, codec, newsletter, weather-cli, statusLNXmljr21 svcnas — nas-alloy, iperf3-nas, netronome-agent-nas, ollama, immich-kiosk, photon, nextcloud-notify, crowdsec-nas, smartctl-exporter-nas, nas, immich, auto-media-sort, nextcloud, dockhand, syncthing, opencloud, projects, dawarich, paperlessLNXnas19 svcnuc — nocturne, glucava, actual-budget, sure, defectdojo, kuma, healthreport, crowdsec-nuc, backup-dashboard, grafana, mail-archiver, paperless-mail-export, dmarc-monitor, csp-reports, umami, forgejo, speedtest, smartctl-exporter-nuc, nuc-webui, wordwiz, sudoku, gameoflife, cglab, godrive-demo, service-templateLNXnuc25 svcugreen — syncthing-ugreen, oxicloud, smartctl-exporterLNXugreen3 svc

Avg response time

186 ms
237.6147.324h agonow

Avg CPU · all hosts · 24h

10%
21.47.1

CrowdSec perimeter

15194
Active bans
1489
Blocked · 24h
4944
Alerts · total
6
Hosts online
Community blocklist · 15154caught here · 40

Top threats · active bans

HTTP scanning14528
HTTP brute force434
HTTP exploits184
http sensitive files14
Aggressive crawling8
http crawl non_statics7
CrowdSec · last 12 months

Attacks blocked per day

135002 total
MonWedFriDecJanFebMarAprMayJun109 attacks blocked on Jun 112256 attacks blocked on Jun 12629 attacks blocked on Jun 131905 attacks blocked on Jun 142049 attacks blocked on Jun 151105 attacks blocked on Jun 16466 attacks blocked on Jun 17434 attacks blocked on Jun 18384 attacks blocked on Jun 19440 attacks blocked on Jun 20390 attacks blocked on Jun 21330 attacks blocked on Jun 221524 attacks blocked on Jun 232475 attacks blocked on Jun 243251 attacks blocked on Jun 255207 attacks blocked on Jun 263648 attacks blocked on Jun 272648 attacks blocked on Jun 282347 attacks blocked on Jun 29791 attacks blocked on Jun 30Jul851 attacks blocked on Jul 1466 attacks blocked on Jul 2606 attacks blocked on Jul 3718 attacks blocked on Jul 41957 attacks blocked on Jul 53994 attacks blocked on Jul 63754 attacks blocked on Jul 73087 attacks blocked on Jul 81726 attacks blocked on Jul 9932 attacks blocked on Jul 10330 attacks blocked on Jul 11462 attacks blocked on Jul 12745 attacks blocked on Jul 13512 attacks blocked on Jul 14351 attacks blocked on Jul 151316 attacks blocked on Jul 16821 attacks blocked on Jul 17640 attacks blocked on Jul 18986 attacks blocked on Jul 19159 attacks blocked on Jul 20438 attacks blocked on Jul 21190 attacks blocked on Jul 22557 attacks blocked on Jul 23658 attacks blocked on Jul 24689 attacks blocked on Jul 25443 attacks blocked on Jul 26566 attacks blocked on Jul 27250 attacks blocked on Jul 28215 attacks blocked on Jul 29189 attacks blocked on Jul 30142 attacks blocked on Jul 31Aug892 attacks blocked on Aug 1426 attacks blocked on Aug 2350 attacks blocked on Aug 3436 attacks blocked on Aug 4371 attacks blocked on Aug 5358 attacks blocked on Aug 6340 attacks blocked on Aug 7428 attacks blocked on Aug 8963 attacks blocked on Aug 9936 attacks blocked on Aug 10980 attacks blocked on Aug 11961 attacks blocked on Aug 12581 attacks blocked on Aug 13381 attacks blocked on Aug 14324 attacks blocked on Aug 15513 attacks blocked on Aug 16563 attacks blocked on Aug 17391 attacks blocked on Aug 18404 attacks blocked on Aug 19241 attacks blocked on Aug 20214 attacks blocked on Aug 21430 attacks blocked on Aug 22468 attacks blocked on Aug 23304 attacks blocked on Aug 24319 attacks blocked on Aug 25444 attacks blocked on Aug 261060 attacks blocked on Aug 27907 attacks blocked on Aug 28638 attacks blocked on Aug 29490 attacks blocked on Aug 30430 attacks blocked on Aug 31Sep594 attacks blocked on Sep 1580 attacks blocked on Sep 2602 attacks blocked on Sep 31555 attacks blocked on Sep 4625 attacks blocked on Sep 5623 attacks blocked on Sep 6490 attacks blocked on Sep 7292 attacks blocked on Sep 8544 attacks blocked on Sep 9481 attacks blocked on Sep 10431 attacks blocked on Sep 11638 attacks blocked on Sep 12588 attacks blocked on Sep 13602 attacks blocked on Sep 141711 attacks blocked on Sep 151194 attacks blocked on Sep 161160 attacks blocked on Sep 171785 attacks blocked on Sep 181402 attacks blocked on Sep 19912 attacks blocked on Sep 201774 attacks blocked on Sep 211332 attacks blocked on Sep 22848 attacks blocked on Sep 231105 attacks blocked on Sep 241012 attacks blocked on Sep 251098 attacks blocked on Sep 261013 attacks blocked on Sep 27789 attacks blocked on Sep 281524 attacks blocked on Sep 29853 attacks blocked on Sep 30Oct2161 attacks blocked on Oct 1706 attacks blocked on Oct 2129 attacks blocked on Oct 3404 attacks blocked on Oct 4945 attacks blocked on Oct 5510 attacks blocked on Oct 6495 attacks blocked on Oct 71664 attacks blocked on Oct 81071 attacks blocked on Oct 91598 attacks blocked on Oct 102074 attacks blocked on Oct 111055 attacks blocked on Oct 121029 attacks blocked on Oct 13571 attacks blocked on Oct 14323 attacks blocked on Oct 151285 attacks blocked on Oct 16957 attacks blocked on Oct 17376 attacks blocked on Oct 1836 attacks blocked on Oct 191208 attacks blocked on Oct 20441 attacks blocked on Oct 211794 attacks blocked on Oct 221318 attacks blocked on Oct 23671 attacks blocked on Oct 241268 attacks blocked on Oct 25613 attacks blocked on Oct 26831 attacks blocked on Oct 27450 attacks blocked on Oct 28346 attacks blocked on Oct 29946 attacks blocked on Oct 30356 attacks blocked on Oct 31Nov1533 attacks blocked on Nov 1
live — uptime kuma + victoriametrics over tailscale · updated 21:46:19
Architecture

How it hangs together

100% IaC

All public traffic enters through Caddy on the VPS, with CrowdSec banning attackers at the edge and Authelia guarding private apps. Behind that, three machines talk over an encrypted Tailscale mesh — no open ports at home. Every host, container and config file is declared in one OpenVox (Puppet) repo; each machine runs an agent that applies it, so there is no central server and no SSH fan-out.

Internet
→ HTTPS :443 · Caddy ingress · CrowdSec at the edge →
Tailscale mesh · WireGuard
mljr
VPS · public entry
CaddyCrowdSecAutheliapublic apps
nuc
home server
VictoriaMetricsGrafanaLokiinternal services
nas
Unraid NAS
storagebackupsmedia
OpenVox agents provision the hosts — hardening, Docker Compose services, Caddy snippets, monitoring. Agent-based instead of push over SSH. No snowflakes.
08

Activity

public aggregates
Strava snapshot

Training as data

Distance
270.8 km
run · hike · ski
Moving time
87 h 37 m
logged effort
Sessions
112
year to date
Elevation
2821 m
climbed
Avg HR
138 bpm
session-weighted
Running · 219Cycling · 60Training · 180

Recent public activities

aggregated
Morning Laufen
01.11.2026 · 30:32 · 5.0 km · 5:59 /km · ↑ 41 m · ♥ 176 bpm · 442 kcal
Afternoon Training
22.10.2026 · 1:09:34 · ♥ 105 bpm · 439 kcal
Afternoon Training
20.10.2026 · 1:00:24 · ♥ 126 bpm · 532 kcal
Morning Laufen
18.10.2026 · 30:35 · 5.0 km · 6:05 /km · ↑ 41 m · ♥ 174 bpm · 443 kcal
Afternoon Training
08.10.2026 · 1:01:54 · ♥ 105 bpm · 390 kcal
Afternoon Training
01.10.2026 · 1:18:13 · ♥ 101 bpm · 460 kcal
Morning Laufen
30.09.2026 · 29:19 · 5.0 km · 5:49 /km · ↑ 40 m · ♥ 172 bpm · 417 kcal
Morning Laufen
13.09.2026 · 2:36:32 · 20.9 km · 7:29 /km · ↑ 280 m · ♥ 173 bpm · 2254 kcal

Training load

Fitness (CTL) · Fatigue (ATL) · Form, last 90 days
Form +1.0
59.4-32.7Aug 4Aug 26Sep 17Oct 9Oct 31
Fitness
Fatigue
Form
09

Skills

depth × breadth
LanguagesWebInfraSecurityEmbeddedOps/Data
self-assessed depth per area · dots match the cards

Languages

8
GoRustTypeScriptJavaScriptPythonKotlinJavaC#

Web

8
HTMLCSSSvelteSvelteKitAngularJSAngularASP.NET.NET

Infra / Homelab

7
DockerPuppetLinuxUnraidTailscaleCaddyCI/CD

Security

5
CybersecurityNetwork SecurityIAMPrologPAM

Embedded / BLE

5
ESP32BLEDexcom G7NightscoutKotlin Multiplatform

Ops / Data

5
SQLiteVictoriaMetricsGrafanaslogWebGL
Go
Rust
TypeScript
JavaScript
Python
Kotlin
Java
C#
HTML
CSS
Svelte
SvelteKit
AngularJS
Angular
ASP.NET
.NET
Docker
Puppet
Linux
Unraid
Tailscale
Caddy
CI/CD
SQLite
VictoriaMetrics
Grafana
slog
WebGL
Cybersecurity
Network Security
IAM
Prolog
PAM
ESP32
BLE
Dexcom G7
Nightscout
Kotlin Multiplatform
10

Under the hood

this site, in code

Every component on this page is a Go function. No React, no npm, no build pipeline for the markup — the server renders HTML, Datastar adds reactivity, and SVG charts are computed at request time.

Browser
no framework runtime — Datastar (14 kB) only
↓HTTPS · one round trip
Caddy ingress
TLS, CrowdSec + Authelia in front
↓reverse proxy
One Go binary
gomponents render HTML · SSE patches fragments · SVG charts computed per request
175
UI components
0
npm runtime deps
4×2
themes × modes
1
binary to deploy
5 real excerpts from this site

The arc math behind the gauges in the open-source section.

ui/data/gauge.go
Go
// Gauge renders a circular gauge as inline SVG.
// Zero JS, zero dependencies — pure server-side Go.
func Gauge(p GaugeProps) g.Node {
	cx, cy := float64(p.Size)/2, float64(p.Size)/2
	radius := float64(p.Size) * 0.38
	strokeW := float64(p.Size) * 0.1

	// Arc spans 270° (from 135° to 45°)
	startAngle := 135.0
	totalAngle := 270.0
	pct := (p.Value - p.Min) / (p.Max - p.Min)

	toRad := func(deg float64) float64 {
		return deg * math.Pi / 180
	}
	arcPt := func(deg float64) (float64, float64) {
		a := toRad(deg)
		return cx + radius*math.Cos(a),
			cy + radius*math.Sin(a)
	}
	arcPath := func(start, end float64, color string) string {
		x1, y1 := arcPt(start)
		x2, y2 := arcPt(end)
		large := 0
		if math.Abs(end-start) > 180 {
			large = 1
		}
		return fmt.Sprintf(
			'<path d="M %.1f %.1f A %.1f %.1f 0 %d 1 %.1f %.1f"
			   fill="none" stroke="%s" stroke-width="%.1f"
			   stroke-linecap="round"/>',
			x1, y1, radius, radius, large, x2, y2,
			color, strokeW)
	}

	// Track (full arc), then value arc on top
	sb.WriteString(arcPath(startAngle, startAngle+totalAngle, p.TrackColor))
	sb.WriteString(arcPath(startAngle, startAngle+totalAngle*pct, p.Color))
	// …
}

The homelab panel polls VictoriaMetrics — range queries over 40 days come back empty, so the attack heatmap is fetched in 30-day chunks.

projects/homepage/homelab/homelab.go
Go
// Attacks blocked per day, last ~12 months.
// VictoriaMetrics range queries spanning >40 days can return
// empty results (per-day index cutoff), so fetch the year in
// 30-day chunks and dedupe by day.
seenDay := map[string]bool{}
for chunk := 11; chunk >= 0; chunk-- {
	start := now.AddDate(0, 0, -30*(chunk+1))
	end := now.AddDate(0, 0, -30*chunk)
	pts, err := p.promQueryRange(ctx,
		"sum(increase(cs_bucket_overflowed_total[1d]))",
		start, end, 24*time.Hour,
	)
	if err != nil {
		continue // empty until a year of data exists
	}
	for _, pt := range pts {
		day := time.Unix(int64(pt[0]), 0)
		key := day.Format("2006-01-02")
		if pt[1] > 0 && !seenDay[key] {
			seenDay[key] = true
			s.AttackDays = append(s.AttackDays,
				DayValue{Date: day, Count: int(pt[1])})
		}
	}
}

This very carousel. Pages flip on a Datastar signal; the observer only reacts to display:none→visible, so the animation can never re-trigger itself.

ui/data/pagination.go
Go
// PaginatedPages: each page shown while the shared
// Datastar signal matches its index.
for i, page := range pages {
	wrapped[i] = h.Div(
		g.Attr("data-slot", "page"),
		ui.Show(fmt.Sprintf("$%s === %d", sig, i)),
		page,
	)
}

// Entrance animation replays exactly once per page switch:
// the observer only reacts to style mutations whose OLD value
// was display:none — the CSS animation itself can never
// re-trigger it.
var obs=new MutationObserver(function(muts){
  muts.forEach(function(m){
    var was=(m.oldValue||'');
    var wasHidden=was.indexOf('display:none')>-1;
    if(wasHidden&&m.target.style.display!=='none'){
      m.target.removeAttribute('data-anim');
      void m.target.offsetWidth;      // restart keyframes
      m.target.setAttribute('data-anim','');
    }
  });
});

Live updates without a framework: one attribute on the section, one SSE handler, Datastar morphs the panel in place.

projects/homepage/handlers.go
Go
// One attribute on the section…
h.Section(
	h.ID("homelab"),
	g.Attr("data-on-interval__duration.60s",
		"@get('/api/homelab')"),
	// …
)

// …one SSE handler on the server.
e.GET("/api/homelab", func(c echo.Context) error {
	sse := datastar.NewSSE(c.Response().Writer, c.Request())
	return sse.PatchElements(
		web.RenderToString(pages.HomelabPanel(snapshot())),
	)
})

// Datastar morphs #homelab-panel in place every 60 s:
// no reload, no virtual DOM, no client-side state to sync.

The skills radar — plain trigonometry rendered to an SVG polygon at request time.

ui/data/radarchart.go
Go
// Radar chart: axis i sits at angle 2πi/n, starting at
// 12 o'clock. Values scale along the spoke; the series
// becomes a single <polygon>.
angle := func(i int) float64 {
	return float64(i)*2*math.Pi/float64(n) - math.Pi/2
}
pt := func(radius float64, i int) (float64, float64) {
	a := angle(i)
	return cx + radius*math.Cos(a), cy + radius*math.Sin(a)
}

pts := make([]string, len(p.Axes))
for i := range p.Axes {
	scaled := (s.Values[i] / p.Max) * r
	x, y := pt(scaled, i)
	pts[i] = fmt.Sprintf("%.1f,%.1f", x, y)
}
sb.WriteString(fmt.Sprintf(
	'<polygon points="%s" fill="%s" fill-opacity="0.18"
	   stroke="%s" stroke-width="2"/>',
	strings.Join(pts, " "), color, color))
11

Get in touch

Let's talk

Open to interesting projects, thesis collaborations, and conversations about systems, security, and self-hosting.

Currently

  • IT Security Engineer @ Land Oberösterreich
  • Tutor for Digital Circuits @ JKU Linz
  • Building this site with Go · gomponents · Datastar