An open API service indexing awesome lists of open source software.

https://github.com/psimaker/homelab

Self-hosted home infra: a 53-container Docker dataplane (hosts loogi.ch) + a k3s/GitOps platform I'm building as a CKA learning lab.
https://github.com/psimaker/homelab

ansible devops docker flux gitops homelab kubernetes searxng self-hosted terraform

Last synced: 23 days ago
JSON representation

Self-hosted home infra: a 53-container Docker dataplane (hosts loogi.ch) + a k3s/GitOps platform I'm building as a CKA learning lab.

Awesome Lists containing this project

README

          

# homelab

Five years of self-hosted, pre-AI Docker operations on bare metal — **53 containers
across 18 Compose stacks**, including one service live for real users: the search
engine [**loogi.ch**](https://loogi.ch). That is **Tier-2**, my production dataplane.

**Tier-1** is a k3s / GitOps platform I'm designing and learning as I prepare for the
CKA. The manifests, OpenTofu and 13 ADRs in this repo are real and written — designed
to learn from, not yet deployed to production. Throughout the README, what is
*running* and what is *designed* are labelled apart.

[![Tier-2](https://img.shields.io/badge/Tier--2-in_production-2EA043?logo=docker&logoColor=white)](compose/)
[![loogi.ch](https://img.shields.io/badge/loogi.ch-live-2EA043?logo=searxng&logoColor=white)](https://loogi.ch)
[![Tier-1](https://img.shields.io/badge/Tier--1-learning_lab%20%2B%20roadmap-FFC61C?logo=kubernetes&logoColor=white)](docs/architecture.md)
[![CKA](https://img.shields.io/badge/CKA-in_prep-blue)](docs/adr/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

> *I automate things so I can spend more time breaking other things.*

## What runs today — Tier-2 (Docker, production)

A bare-metal Debian host (`airbase`) with five years of hands-on operations — self-taught
and started well before the AI era, so the core understanding is mine, not a model's.

- **[loogi.ch](https://loogi.ch)** — a public, privacy-first SearXNG search engine
with a custom theme, served for real users.
- **53 containers across 18 Compose stacks**: Nextcloud-AIO, Immich, Plex + *arr,
Paperless, Vaultwarden, n8n, Vikunja, Syncthing, ntfy, Gitea …
- **Self-hosted CI/CD** — Gitea Actions with my own runner on `airbase`: build and
deploy pipelines on my own hardware, with this public repo as a one-way GitHub
mirror. End-to-end ownership of the delivery path, not a managed SaaS runner.
- **Nginx Proxy Manager** — reverse proxy and TLS (Let's Encrypt) for the dataplane.
- **Watchtower** — automated container image updates.
- **WireGuard / gluetun**, a segmented home network.

Compose files live in [`compose/`](compose/) as 1:1 snapshots of what runs. This tier
owns terabytes of real state and has survived Docker upgrades, kernel upgrades and a
disk migration. Keeping it on Docker rather than Kubernetes is a deliberate call,
reasoned out in [ADR-0001](docs/adr/0001-tier1-tier2-split.md).

## What I'm building — Tier-1 (k3s platform, learning lab + roadmap)

The target stack I've chosen and am working through as part of my CKA preparation —
each tool picked deliberately and documented as one of **13 ADRs** in
[`docs/adr/`](docs/adr/). I have the basics hands-on (kubectl, writing manifests);
the advanced pieces are exactly what the lab is for.

I spin up a single-node k3s lab on a Raspberry Pi to practise for the CKA and to try
the manifests in this repo — a learning cluster, not a 24/7 deployment. The two-site
Hetzner-edge mesh in the diagram below is the design target, not a running cluster.

**Target stack** (chosen and documented, not yet operated in production): k3s 1.31 +
Cilium, Flux v2 for GitOps, OpenTofu on Hetzner, Headscale mesh, Pocket-ID (OIDC),
Longhorn, kube-prometheus-stack + Loki + Tempo, restic 3-2-1, Traefik + cert-manager.
The manifests and Terraform are committed and thought through; I'm validating them
piece by piece in the lab, not running them under load.

**Goal:** once the platform is solid and I'm CKA-certified, move selected *new*
workloads onto it — never the stateful Tier-2 giants without a concrete reason that
pays for the migration.

## Architecture — today vs. roadmap

```mermaid
flowchart LR
user[End user] --> npm

subgraph Today["Running today — Tier-2 (Docker)"]
npm["Nginx Proxy Manager
+ Let's Encrypt"] --- docker[("53 Compose containers
loogi.ch, Nextcloud, Immich, …")]
end

subgraph Roadmap["Roadmap — Tier-1 (k3s, in build)"]
direction TB
edge["edge — Hetzner
k3s server (planned)"]
agent["airbase — k3s worker
(planned)"]
edge -. Tailscale mesh / Headscale
(planned) .-> agent
end

Today -.->|migrate new workloads once solid| Roadmap

classDef plan stroke-dasharray:5 5;
class edge,agent plan;
```

## Tour

Most of this repo is design and code I've written and reasoned about. What is
*running* is the `compose/` tier; the `kubernetes/` and `terraform/` trees are the
lab and the roadmap.

| You'd like to see... | Look at... | State |
| --- | --- | --- |
| The Tier-1 / Tier-2 split decision | [`docs/adr/0001-tier1-tier2-split.md`](docs/adr/0001-tier1-tier2-split.md) | design |
| All 13 decisions and *why* | [`docs/adr/`](docs/adr/) | design |
| The full design | [`docs/architecture.md`](docs/architecture.md) | design |
| Cloud infrastructure as code | [`terraform/live/prod/`](terraform/live/prod/) | written, lab |
| How nodes are configured | [`ansible/roles/`](ansible/roles/) | written, lab |
| The Tier-1 platform manifests | [`kubernetes/infrastructure/`](kubernetes/infrastructure/) | written, lab |
| The Tier-2 stacks that actually run | [`compose/`](compose/) | **live** |
| Self-hosted CI | [`.gitea/workflows/`](.gitea/workflows/) | **live** |

## Stack — running today (Tier-2)

| Layer | Tool |
| --- | --- |
| Host | Debian, bare metal (`airbase`) |
| Orchestration | Docker Compose |
| Reverse proxy / TLS | Nginx Proxy Manager + Let's Encrypt |
| CI/CD | Gitea Actions, self-hosted runner on `airbase` |
| Updates | Watchtower (automated image updates) |
| Networking | WireGuard / gluetun, segmented LAN |

The Tier-1 target stack (k3s, Cilium, Flux, OpenTofu, …) is listed in
"What I'm building" above and detailed in [`docs/architecture.md`](docs/architecture.md) —
kept out of this table on purpose, because that table is what runs.

## Repo layout

```
homelab/
├── docs/ Architecture, ADRs, runbooks (design + reasoning)
├── terraform/ OpenTofu — Hetzner, Cloudflare, Backblaze (written, lab)
├── ansible/ Roles + playbooks (written, lab)
├── kubernetes/
│ ├── flux-system/ Flux components (lab)
│ ├── infrastructure/ Controllers, storage, observability, identity (lab)
│ └── apps/ Tier-1 workload manifests (lab)
├── compose/ Tier-2 Docker Compose stacks — what actually runs
├── scripts/ bootstrap, sops helpers
├── .gitea/workflows/ CI on my self-hosted Gitea (live)
└── .github/workflows/ no-op stubs (mirror only — Gitea is the source)
```

## Live links

- Production search engine: [loogi.ch](https://loogi.ch) — runs on Tier-2
- LOOGI source: [github.com/psimaker/loogi](https://github.com/psimaker/loogi)
- Canonical code: self-hosted Gitea *(private)* · this is the public mirror

## About

I'm a career-changer moving into DevOps / Platform Engineering, based in central
Switzerland and looking for a junior role (on-site or hybrid). Five years of
hands-on self-hosting, a merged Nextcloud Server contribution (PR #59317, backported
to two stable releases), and the CKA in preparation. If this repo caught your eye,
reach me via my [GitHub profile](https://github.com/psimaker).

## License

[MIT](LICENSE).