<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>johanneskueber.com</title><link>https://johanneskueber.com/</link><description>Recent content on johanneskueber.com</description><generator>Hugo</generator><language>en_US</language><lastBuildDate>Tue, 26 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://johanneskueber.com/index.xml" rel="self" type="application/rss+xml"/><item><title>Signed Dependency Updates with Renovate and Gitea</title><link>https://johanneskueber.com/posts/2026-05-26-sign-renovate-commits/</link><pubDate>Tue, 26 May 2026 00:00:00 +0000</pubDate><guid>https://johanneskueber.com/posts/2026-05-26-sign-renovate-commits/</guid><description>&lt;p&gt;Keeping dependencies up to date is one of those chores that is easy to neglect and expensive to ignore. Renovate solves it nicely: it scans my repositories, opens pull requests for outdated dependencies, and - if I let it - merges them on its own. On a self-hosted Gitea instance with branch protection, however, there is a catch. If I require signed commits on my protected branches, an unsigned bot commit is simply rejected. So before automating anything, Renovate needs an identity and a signing key, and its commits need to show up as &lt;em&gt;Verified&lt;/em&gt;.&lt;/p&gt;</description></item><item><title>Running a rootless NetBird Routing Peer Inside Kubernetes</title><link>https://johanneskueber.com/posts/2026-05-25-netbird-routing-peer/</link><pubDate>Mon, 25 May 2026 00:00:00 +0000</pubDate><guid>https://johanneskueber.com/posts/2026-05-25-netbird-routing-peer/</guid><description>&lt;p&gt;This article documents how to run a NetBird client &lt;em&gt;inside&lt;/em&gt; a Kubernetes cluster as a &lt;strong&gt;routing peer&lt;/strong&gt; — rootless, with an in-memory state volume, a shell-based readiness probe, and dropped capabilities — so that remote mesh members can reach cluster-internal services over the encrypted overlay, without exposing kernel WireGuard and without making the cluster a peer of every workload.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-why-a-netbird-peer-in-the-cluster"&gt;1. Why a NetBird peer in the cluster&lt;/h2&gt;
&lt;p&gt;NetBird is a WireGuard-based identity mesh. Each peer holds keys, exchanges them via the management plane, and routes encrypted traffic to other peers. The default deployment runs the client on a host (Linux VM, MacBook, etc.) and uses the host&amp;rsquo;s kernel WireGuard.&lt;/p&gt;</description></item><item><title>Envoy Gateway Configuration to Reach SSL Labs A+</title><link>https://johanneskueber.com/posts/2026-05-14-envoy-gateway-ssllabs-a-plus/</link><pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate><guid>https://johanneskueber.com/posts/2026-05-14-envoy-gateway-ssllabs-a-plus/</guid><description>&lt;p&gt;This article documents the Envoy Gateway configuration required to achieve an A+ rating on Qualys SSL Labs, with the rationale for each setting.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-tls-security-background"&gt;1. TLS security background&lt;/h2&gt;
&lt;p&gt;Before any application data flows over &lt;code&gt;https://&lt;/code&gt;, the TLS session completes two steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Authentication.&lt;/strong&gt; The server presents an X.509 certificate signed by a trusted Certificate Authority.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key agreement and encryption.&lt;/strong&gt; Client and server negotiate a session key via a cipher suite (key exchange, signature, bulk cipher, MAC) and encrypt the channel.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Weaknesses in this chain enable specific attack classes:&lt;/p&gt;</description></item><item><title>Intel iGPU passthrough with Proxmox and Talos</title><link>https://johanneskueber.com/posts/2025-10-11-proxmox-passthrough-talos/</link><pubDate>Sat, 11 Oct 2025 21:06:26 +0000</pubDate><guid>https://johanneskueber.com/posts/2025-10-11-proxmox-passthrough-talos/</guid><description>&lt;h2 id="igpu-passthrough-with-proxmox-and-talos"&gt;iGPU Passthrough with Proxmox and Talos&lt;/h2&gt;
&lt;p&gt;To use the GPU of the host system in K8s, it needs to be made aware of its existence. As I use VMs in Proxmox to run my Talos Cluster, there is an additional step to consider: passthrough of the hardware into the VM. The idea is the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Disable usage of GPU on the Proxmox Host - done via IOMMU and VFIO&lt;/li&gt;
&lt;li&gt;Passthrough of the GPU into a Talos Worker Node - done via hostpci&lt;/li&gt;
&lt;li&gt;Activation of GPU drivers in Talos - done via talhelper&lt;/li&gt;
&lt;li&gt;GPU management in the cluster - done via Intel GPU Plugin&lt;/li&gt;
&lt;li&gt;Usage of GPU in a deployment - by requesting the resource&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are quite some steps and all of them are specific to your environment. Different host system? Different steps. Different Cluster Software? You need to adept. Different GPU? You need other drivers and management. So please look out for the pitfalls and only copy and paste if you run proxmox with talos and have an Intel iGPU.&lt;/p&gt;</description></item><item><title>Use Longhorn with Talos 1.10 and userVolumes</title><link>https://johanneskueber.com/posts/2025-06-17-longhorn-uservolumes-talos/</link><pubDate>Tue, 17 Jun 2025 07:06:26 +0000</pubDate><guid>https://johanneskueber.com/posts/2025-06-17-longhorn-uservolumes-talos/</guid><description>&lt;p&gt;When building a cluster, especially in a homelab, local storage is needed for application data. Especially for databases fast read and write is required. Offloading the workload to a NAS most of the time is slower. The solution I use is to provision on-node storage with &lt;a href="https://longhorn.io/"&gt;Longhorn&lt;/a&gt;. Longhorn acts as a CSI and offers on-node storage, replication, backups and more.&lt;/p&gt;
&lt;p&gt;As I am currently building a Talos cluster I need to integrate the longhorn CSI into the setup. This is not as straigt forward as with K3s oder K8s, as Talos has tighter security constraints and also needs additional plugins to handle SCSI - the underlying file system protocol used by longhorn. On top I am using &lt;a href="https://budimanjojo.github.io/talhelper/latest/"&gt;Talhelper&lt;/a&gt; to allow a GitOps style usage of talosctl. The main advantage is the encryption of secrets used by talos config files with &lt;a href="https://github.com/getsops/sops"&gt;SOPS&lt;/a&gt; - something that I already use for Tofu and fluxCD.&lt;/p&gt;</description></item><item><title>Enable hardware acceleration for Jellyfin in Kubernetes - AMD Edition</title><link>https://johanneskueber.com/posts/2024-06-24-hardware-acceleration-kubernetes-jellyfin/</link><pubDate>Mon, 24 Jun 2024 07:06:26 +0000</pubDate><guid>https://johanneskueber.com/posts/2024-06-24-hardware-acceleration-kubernetes-jellyfin/</guid><description>&lt;p&gt;&lt;a href="https://jellyfin.org/"&gt;Jellyfin&lt;/a&gt; is an open-source media server software that allows users to manage and stream their personal collection of movies, TV shows, music, and other media files. It is designed as an alternative to proprietary media server solutions like Plex and Emby, offering similar functionality but without any licensing costs or restrictions.&lt;/p&gt;
&lt;p&gt;Jellyfin is running in my bare-metal kubernetes cluster. However, running the container without additional configuraion only gives Jellyfin access to the CPU for decoding video streams. If a GPU is available it would be better to use the GPU as it - most of the time - also has hardware acceleration for well-known codecs and in addition it takes some work off the CPU. In my case, the Athlon 3000G has an on-board Vega 3 graphics chip. Now the only thing left to do is to give Jellyfin access to the GPU.&lt;/p&gt;</description></item><item><title>Migrating data between baserow instances</title><link>https://johanneskueber.com/posts/2024-06-19-migrating-baserow-data-between-instances/</link><pubDate>Wed, 19 Jun 2024 07:06:26 +0000</pubDate><guid>https://johanneskueber.com/posts/2024-06-19-migrating-baserow-data-between-instances/</guid><description>&lt;p&gt;&lt;a href="https://baserow.io/"&gt;Baserow&lt;/a&gt; is an open-source alternative to tools like Airtable and Google Sheets. It allows users to create databases and manage data in a user-friendly, spreadsheet-like interface. With Baserow, you can store, share, and collaborate on data with your team, all while maintaining full control over your data as it&amp;rsquo;s self-hosted. It offers features like row-level permissions, different field types, views (like table, gallery, kanban), and more. It also provides APIs for developers to build custom apps or integrations.&lt;/p&gt;</description></item><item><title>Running an SPA and an API in the same Docker Container</title><link>https://johanneskueber.com/posts/2021-04-28-spa-and-server-in-one-dockerfile/</link><pubDate>Wed, 28 Apr 2021 18:12:26 +0000</pubDate><guid>https://johanneskueber.com/posts/2021-04-28-spa-and-server-in-one-dockerfile/</guid><description>&lt;p&gt;Hosting a static web page was never a problem. A simple Apache or nginx server and a local directory on the server was always enough. With cloud environment these tools are still available. And it is simple enough to mount a directory into an nginx container. However, you still need to spin up a container just for the purpose of hosting a static page. Using a JAMstack application, you also need an API container to connect to. In order to reduce the number of containers and the overhead, I will show how we can integrate the the server for the static page into our API server. This way, we will have everything included in a single container. This is all achieved by using dockers multi-stage builds.&lt;/p&gt;</description></item><item><title>Selfhosted Continuous Integration - all parts required</title><link>https://johanneskueber.com/posts/2020-01-08-selfhosted-continuous-integration-part-1-overview/</link><pubDate>Wed, 08 Jan 2020 21:06:26 +0100</pubDate><guid>https://johanneskueber.com/posts/2020-01-08-selfhosted-continuous-integration-part-1-overview/</guid><description>&lt;p&gt;As of late I came to wonder how dependent I want to be on cloud-solutions. After some researching I decided I wanted to be independent. This also includes leaving out great open source communities such as &lt;a href="https://github.com/"&gt;Github&lt;/a&gt;. There are plenty of great solutions for every aspect of the Software Development Lifecycle - most of them are hosted in the cloud, i.e. the computer of someone else. This is not only a problem once your internet is not working - but it also happens to become a problem when a certain service is shut down. Sometimes without warning. Sometimes forever. So i wondered: could I set up a basic continuous integration environment completely hosted in my environment.&lt;/p&gt;</description></item><item><title>Getting the color palette of an image with Coil in Android</title><link>https://johanneskueber.com/posts/2019-12-12-android-coil-palette/</link><pubDate>Thu, 12 Dec 2019 23:06:26 +0100</pubDate><guid>https://johanneskueber.com/posts/2019-12-12-android-coil-palette/</guid><description>&lt;p&gt;For part of my applications I wanted to load an image into an activity. Based on the images main colors, I wanted to adjust the UI of the activity. Loading of the image is the easy part. This can be done via a number of libraries. At the time of writing, the most prominent libraries are: &lt;a href="https://square.github.io/picasso/"&gt;Picasso&lt;/a&gt; and &lt;a href="https://bumptech.github.io/glide/"&gt;Glide&lt;/a&gt;. Lately however, there is a new library which targets Kotlin specifically: Coil (see &lt;a href="https://coil-kt.github.io/coil/"&gt;coil-kt.github.io/coil/&lt;/a&gt;).&lt;/p&gt;</description></item><item><title>About</title><link>https://johanneskueber.com/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://johanneskueber.com/about/</guid><description>&lt;h1 id="about-johanneskuebercom"&gt;About johanneskueber.com&lt;/h1&gt;
&lt;p&gt;This homepage is dedicated to my work and pet projects all around IT. In no particular order I try to keep myself entertained with new technologies, programming, automation, (self-)hosting.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mobile Development&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://johanneskueber.com/tags/android-architecture-components"&gt;Android Architecture Components&lt;/a&gt; &lt;a href="https://developer.android.com/topic/architecture"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/mvvm"&gt;MVVM&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/dagger"&gt;Dagger 2&lt;/a&gt; &lt;a href="https://dagger.dev/"&gt;(↗)&lt;/a&gt; (&lt;a href="https://johanneskueber.com/tags/hilt"&gt;Hilt&lt;/a&gt; &lt;a href="https://dagger.dev/hilt/"&gt;(↗)&lt;/a&gt;),&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/kotlin/"&gt;Kotlin&lt;/a&gt; &lt;a href="https://kotlinlang.org/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/grpc"&gt;GRPC&lt;/a&gt; &lt;a href="https://grpc.io/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/rest"&gt;REST&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/REST"&gt;(↗)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://johanneskueber.com/tags/angularjs"&gt;AngularJS&lt;/a&gt; &lt;a href="https://angularjs.org/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/angular"&gt;Angular&lt;/a&gt; &lt;a href="https://angular.dev/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/vue"&gt;Vue.js&lt;/a&gt; &lt;a href="https://vuejs.org/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/gridsome"&gt;Gridsome&lt;/a&gt; &lt;a href="https://gridsome.org/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/nuxt/"&gt;Nuxt&lt;/a&gt; &lt;a href="https://nuxt.com/"&gt;(↗)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Backend Development&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://johanneskueber.com/tags/go"&gt;Golang&lt;/a&gt; &lt;a href="https://go.dev/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/kotlin/"&gt;Kotlin&lt;/a&gt; &lt;a href="https://kotlinlang.org/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/nodejs"&gt;Node.js&lt;/a&gt; &lt;a href="https://nodejs.org/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/java"&gt;Java&lt;/a&gt; &lt;a href="https://www.java.com/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/php"&gt;PHP&lt;/a&gt; &lt;a href="https://www.php.net/"&gt;(↗)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hosting and Toolchains&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://johanneskueber.com/tags/k8s/"&gt;K8s&lt;/a&gt; &lt;a href="https://kubernetes.io/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/k3s"&gt;K3s&lt;/a&gt; &lt;a href="https://k3s.io/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/k3d"&gt;K3d&lt;/a&gt; &lt;a href="https://k3d.io/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/minikube"&gt;Minikube&lt;/a&gt; &lt;a href="https://minikube.sigs.k8s.io/docs/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/argocd"&gt;ArgoCD&lt;/a&gt; &lt;a href="https://argo-cd.readthedocs.io/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/fluxcd/"&gt;FluxCD&lt;/a&gt; &lt;a href="https://fluxcd.io/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/github"&gt;GitHub&lt;/a&gt; &lt;a href="https://github.com/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/github-actions"&gt;GitHub Actions&lt;/a&gt; &lt;a href="https://github.com/features/actions"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/ghcr"&gt;GHCR&lt;/a&gt; &lt;a href="https://github.com/features/packages"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/renovate/"&gt;Renovate&lt;/a&gt; &lt;a href="https://www.mend.io/renovate/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/docker/"&gt;Docker&lt;/a&gt; &lt;a href="https://www.docker.com/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/docker-swarm"&gt;Docker Swarm&lt;/a&gt; &lt;a href="https://docs.docker.com/engine/swarm/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/drone/"&gt;Drone.io&lt;/a&gt; &lt;a href="https://www.drone.io/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/gitea/"&gt;Gitea&lt;/a&gt; &lt;a href="https://about.gitea.com/"&gt;(↗)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://johanneskueber.com/tags/cicd"&gt;CI/CD&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/CI/CD"&gt;(↗)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>