Our Self-Hosted Stack 2024: Open-Source Tools Overview
Three and a Half Years Later
In early 2021, we described why we at encircle360 rely on self-hosted open source. The reasons -- data sovereignty, vendor independence, cost control -- remain unchanged. What has changed is the stack itself. Services have been added, others replaced, and the platform underneath has evolved. Time for an update.
This post is a catalog. Not a deep dive into individual tools, but an overview of the building blocks that make up our internal infrastructure in mid-2024. Everything runs on our K3s clusters, which we've been operating in production for years. Depending on the setup, we use Helmfile or Argo CD for deployment management -- Helmfile for the clusters we've been running longer, Argo CD in newer setups where the pull-based GitOps approach is a better fit. The nodes underneath run NixOS -- declaratively configured, reproducible, and after over two years in production, exactly as reliable as we had hoped.
Gitea: Git Hosting Without the Bloat
Gitea was already part of our stack in 2021 and has remained so. The software is written in Go, starts in seconds, and consumes a fraction of the resources of a comparable GitLab instance. For a team our size, that's a real advantage -- less resource consumption means fewer nodes, lower costs, less complexity.
We use Gitea for all source code, pull requests, code reviews, and issue tracking. The API is stable and well-documented, making integration into our CI/CD pipelines straightforward.
Directus: Headless CMS on Your Own Database
Directus has evolved from an experiment to a central building block since 2021. We use it as a headless CMS for our website, for blog posts, and for structured data served via REST and GraphQL APIs. What makes Directus special: it sits directly on an existing PostgreSQL database and automatically generates the API from the database schema. No proprietary data format, no migration -- the data truly belongs to us.
In day-to-day operations, we appreciate the admin interface that enables non-technical team members to maintain content. The Flows engine allows automations to be configured directly in Directus -- webhooks on changes, automatic image processing, notifications. For a small team, that saves a lot of glue code.
Keycloak: Identity Management and SSO
Keycloak handles identity and access management for our entire stack. Single sign-on via OpenID Connect, user management, role assignment, two-factor authentication -- all in one place. Every internal service that needs authentication connects to Keycloak via OIDC: Gitea, Directus, Grafana, our own applications.
The initial configuration of Keycloak remains involved. Realms, clients, flows, mappers -- the learning curve is steep. But once set up, it runs reliably and offers a level of flexibility that hosted alternatives like Auth0 don't match -- at least not without enterprise pricing. Since Keycloak 22, the migration from WildFly to Quarkus is complete, which has significantly improved resource consumption and startup times. For deployment on Kubernetes, we use the codecentric Keycloakx Helm chart after the earlier Bitnami chart was deprecated.
PostgreSQL: The Database for Everything
PostgreSQL is the backbone of our data storage. Directus, Keycloak, Gitea, and various custom applications use PostgreSQL as their primary database. We run multiple PostgreSQL instances on the cluster, separated by service and environment.
For managing PostgreSQL instances on Kubernetes, we rely on the CloudNativePG operator. The operator handles provisioning, automatic backups, point-in-time recovery, and failover. What used to require manual backup scripting and carefully configured replication is now a Kubernetes custom resource. Backups go automatically to MinIO -- which brings us to the next building block.
MinIO: Object Storage in Your Own Cluster
MinIO provides S3-compatible object storage on our own infrastructure. We use it for database backups, Directus assets, build artifacts, and everything that doesn't belong in a relational database. S3 API compatibility is the decisive point: any tool or library that can talk to AWS S3 works without modification with MinIO.
MinIO runs in a distributed configuration across multiple nodes, ensuring redundancy and availability. Performance is more than sufficient for our use cases. And compared to the costs of S3 or comparable cloud storage services, running on our own hardware is significantly cheaper -- especially with larger data volumes, where cloud providers' egress fees add up considerably.
Grafana and Prometheus: Monitoring and Alerting
Monitoring is not an optional feature when you run your own infrastructure. Prometheus collects metrics from all services and nodes, Grafana visualizes them in dashboards and triggers alerts when thresholds are exceeded.
We deploy the kube-prometheus-stack via Helmfile, which includes Prometheus and Grafana as well as Alertmanager, node-exporter, and kube-state-metrics. The pre-built dashboards cover Kubernetes cluster health, node resources, and pod metrics. For our own Spring Boot services, we've built additional dashboards that display Micrometer metrics like request latencies, JVM heap usage, and thread pools.
Alerts go via Alertmanager to our messaging channel. When a pod is stuck in CrashLoopBackOff, a node is unreachable, or disk space is running low, we find out within minutes -- not only when a user reports it.
Gatus: Health Checks and Status Page
For external monitoring, we use Gatus. Gatus is written in Go, configured via a single YAML file, and checks the reachability of our services at configurable intervals -- HTTP endpoints, TCP ports, DNS resolution, TLS certificates. The built-in status page shows the current state of all services at a glance.
Gatus complements Prometheus but doesn't replace it. Prometheus monitors the internals -- metrics, resources, performance. Gatus monitors from the outside: Is the service reachable? Does it respond within acceptable times? Is the TLS certificate still valid? This external perspective is important because internal metrics alone don't reveal whether a service actually works for end users. Previously, we used Uptime Kuma for this purpose, but Gatus has integrated better into our GitOps workflow thanks to its YAML-based configuration.
The Platform: K3s on NixOS
Underneath all these services lies our K3s infrastructure on NixOS hosts. K3s delivers Kubernetes with minimal overhead -- a single binary, no separate etcd cluster in most setups, Traefik as an ingress controller out of the box. We now operate three clusters (dev, staging, production) managed via Helmfile with environments and selectors.
NixOS as the host operating system has proven itself over the years. Each node is fully described by its configuration.nix. A new node isn't a manual installation but a deployment of a declarative configuration. Kernel updates, systemd services, network configuration -- everything versioned, everything reproducible, everything rollbackable.
What Has Changed Since 2021
Comparing with our stack from early 2021 reveals a clear evolution. The core building blocks -- Gitea, Keycloak, Directus, PostgreSQL, Prometheus/Grafana -- have remained and matured. Added are MinIO as object storage, Gatus for external health monitoring, CloudNativePG for database management, and Argo CD as a complementary deployment option alongside Helmfile. We still use Nextcloud, but increasingly less for core tasks as specialized services cover the respective responsibilities better.
The biggest change, however, isn't a single tool but the maturity of the overall system. Helmfile and Argo CD for deployment management, automated backups via CloudNativePG and MinIO, end-to-end SSO via Keycloak, comprehensive monitoring through Prometheus and Gatus. Each building block complements the others. The result is a platform that feels like a product -- not like a collection of individual tools.
Conclusion
Our self-hosted stack in 2024 is no longer a hobby project. It's a mature, well-thought-out infrastructure that supports our daily work. The operational effort is real -- updates, troubleshooting, capacity planning don't go away just because you use open source. But the effort is predictable, the costs are manageable, and the control over our data and processes is complete.
For us as a Kubernetes consultancy, our own stack is simultaneously a production environment and a learning platform. Every problem we solve on our own infrastructure makes us better at advising our clients. That's not a side effect -- it's part of the strategy.
Written by
Patrick HütterFounder & Software Architect
Software architect, engineer and entrepreneur. Patrick has been building products and platforms for over a decade — from enterprise backends and cloud-native infrastructure to AI-powered applications. As founder of encircle360, he combines deep technical expertise with entrepreneurial vision, driving open source projects that create real impact.
You might also like
CI Runners in a microVM: Docker Builds with Kata Containers on Kubernetes
Aug 31, 2026 · 10 min read
GitOps with Helmfile and Kyverno: Our Deployment Workflow
Mar 10, 2025 · 7 min read
K3s and KubeVirt: Converged Infrastructure on Bare Metal
Jan 20, 2025 · 6 min read