README: redesign as architecture-first portfolio landing page
Replaces the bio-first README with a single-page overview covering every system in the homelab (secrets/PKI, SSO, firewall, observability, security monitoring, orchestration, notifications, registry/build, Dashy SOC board, cron scheduler, content pipeline, IaC, disaster recovery) plus a sanitized architecture diagram, linking out to a full docs/ write-up for each. Bio/social links moved to the bottom.
This commit is contained in:
1 file changed
+122
-55
@@ -1,59 +1,132 @@
|
||||
# 👋 Hi there — I’m @thesabear
|
||||
# thesabear's Homelab
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
A real, multi-host homelab run as a production-grade platform — not a pile of `docker run` commands. A Proxmox hypervisor cluster hosts a fleet of hardened VMs/LXCs; a self-hosted Vault cluster issues PKI certs and distributes secrets to every consumer; a dual-zone reverse-proxy design (one zone for browsers, one for service-to-service traffic) sits behind SSO; Kestra-driven automation handles fleet maintenance on a schedule with a human approval gate; and a self-built SOC stack (Wazuh + Grafana + a custom dashboard) watches all of it.
|
||||
|
||||
I’m a curious, self-taught technologist who runs a real, multi-host homelab as a production-grade playground: a Proxmox hypervisor cluster hosting a fleet of VMs/LXCs, a two-zone Caddy reverse-proxy design fronted by Authentik SSO, self-hosted Gitea with Ansible-driven scheduled maintenance, and Terraform+Packer provisioning for bootstrapping new hosts from hardened, minimal images. What started as a hobby project has grown into a full-on journey into DevOps, automation, infrastructure, and security.
|
||||
This repo is a sanitized showcase of the systems behind that platform — the actual engineering decisions and tradeoffs, not just a list of installed apps. Every real IP, hostname, and internal domain has been stripped or genericized throughout.
|
||||
|
||||
My long-term goal is to build a career in IT — specifically in environments where learning never stops and innovation is part of the culture.
|
||||
## Architecture at a glance
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Internet(["Internet"])
|
||||
Edge["Edge Firewall<br/>NAT · public reverse proxy · NTP · DHCP"]
|
||||
LAN["LAN"]
|
||||
DNS["Internal DNS<br/>two zones: browser-facing / service-to-service"]
|
||||
Vault["Vault<br/>PKI + secret store"]
|
||||
|
||||
Apps["App Host (LXC)<br/>~40 Docker Compose stacks"]
|
||||
InternalProxy["Internal reverse-proxy zone<br/>app-to-app HTTPS"]
|
||||
SSO["SSO / forward-auth"]
|
||||
|
||||
FileServer["File Server<br/>NFS · SMB"]
|
||||
Automation["Automation VM<br/>Git hosting · orchestration"]
|
||||
EdgeProxy["User-facing reverse proxy<br/>mTLS enforced"]
|
||||
Monitoring["Monitoring<br/>metrics · logs"]
|
||||
SecMonitoring["Security Monitoring<br/>SOC stack"]
|
||||
|
||||
Internet --> Edge --> LAN
|
||||
LAN --> DNS
|
||||
LAN --> Vault
|
||||
DNS --> Vault
|
||||
|
||||
Vault --> Apps
|
||||
LAN --> FileServer
|
||||
DNS --> FileServer
|
||||
Vault --> Automation
|
||||
LAN --> Automation
|
||||
|
||||
Apps --> InternalProxy
|
||||
Apps --> SSO
|
||||
|
||||
Vault --> EdgeProxy
|
||||
DNS --> EdgeProxy
|
||||
Apps -. proxied by .-> EdgeProxy
|
||||
SSO -. auth gate via .-> EdgeProxy
|
||||
|
||||
Apps -. reports to .-> Monitoring
|
||||
Automation -. reports to .-> Monitoring
|
||||
FileServer -. reports to .-> Monitoring
|
||||
EdgeProxy -. reports to .-> Monitoring
|
||||
|
||||
Apps -. reports to .-> SecMonitoring
|
||||
Automation -. reports to .-> SecMonitoring
|
||||
FileServer -. reports to .-> SecMonitoring
|
||||
EdgeProxy -. reports to .-> SecMonitoring
|
||||
```
|
||||
|
||||
Full traffic-law breakdown (ingress, east-west, secrets, DNS, observability, notifications, CI/CD, and management planes, each with its own failure behavior): [docs/architecture-overview.md](docs/architecture-overview.md).
|
||||
|
||||
## Systems
|
||||
|
||||
### 🔐 Secrets & PKI
|
||||
One Vault cluster serves as both the internal certificate authority and the secret store — no separate PKI tool bolted on. It replaced an earlier plaintext-`.env`-in-git secrets model with AppRole-based Vault Agent distribution: every consuming host authenticates itself and renders secrets locally, nothing calls the Vault API directly. A non-expiring root token is tracked as the single biggest known risk, ranked and reasoned about rather than ignored.
|
||||
→ [docs/secrets-and-pki.md](docs/secrets-and-pki.md)
|
||||
|
||||
### 🔑 Secret Distribution Model
|
||||
Four distinct flows — certificate issuance, per-app secret rendering, config-file distribution, and admin/provisioning-time secrets — each with an explicit contract for what happens if it fails. Two genuinely different secret mechanisms exist side by side on purpose, rather than forcing every use case through one system.
|
||||
→ [docs/secret-distribution.md](docs/secret-distribution.md)
|
||||
|
||||
### 🪪 SSO & Identity
|
||||
Every app registers against the SSO provider twice — once per reverse-proxy zone — because authentication always happens on the user-facing zone even when the app itself lives on the internal one. A real platform limitation is documented rather than papered over: the SSO provider's LDAP outpost can't do search-then-bind auth for superuser accounts, so that path uses header-based forward-auth instead. Git automation follows least privilege — a scoped bot account with write access replaces routing CI through an admin identity.
|
||||
→ [docs/sso-and-identity.md](docs/sso-and-identity.md)
|
||||
|
||||
### 🧱 Firewall & Network Segmentation
|
||||
No blanket "anything on the LAN can talk to anything else on the LAN" rule. Every real service-to-service flow gets its own explicit allow rule; everything else is logged and dropped. Firewall objects are managed through named group aliases, not by hand-editing raw addresses into every rule. A real, documented gap: container traffic bypasses the host firewall entirely, so per-host firewall rules only actually protect native, non-containerized services.
|
||||
→ [docs/firewall-and-network.md](docs/firewall-and-network.md)
|
||||
|
||||
### 🌐 DNS
|
||||
Two separate internal DNS zones by design — one for browser-facing apps (mutual TLS enforced), one for service-to-service traffic — deliberately never conflated. A later audit caught and corrected real documentation drift: an old note claimed an external DNS forwarder was in use that, in practice, wasn't.
|
||||
→ [docs/dns-naming.md](docs/dns-naming.md)
|
||||
|
||||
### 📈 Observability
|
||||
Metrics are pushed, not scraped — a deliberate choice made to avoid punching scrape-target holes through the firewall model above. The collection agent runs as a native systemd service on every host (not a container) and is installed by a compliance-tagged automation role that self-heals on drift, not just applied once at setup.
|
||||
→ [docs/observability.md](docs/observability.md)
|
||||
|
||||
### 🛡️ Security Monitoring
|
||||
A curated "known-alert" runbook exists specifically so routine noise doesn't get re-investigated from scratch every time it fires — every entry documents its actual root cause. Compliance hardening is rolled out fleet-wide with deliberate, justified exceptions (a control that simply can't apply inside a container gets skipped there, not blanket-forced), and the automated security benchmark tool runs natively after hitting a real binary-compatibility wall with its own official container image.
|
||||
→ [docs/security-monitoring.md](docs/security-monitoring.md)
|
||||
|
||||
### 🔁 Orchestration
|
||||
Thirteen scheduled flows handle fleet maintenance end to end, built around a check → pause → require human approval → apply pattern instead of blind automatic changes. Different flows deliberately authenticate as different service identities depending on what they need to touch locally on the control node.
|
||||
→ [docs/orchestration.md](docs/orchestration.md)
|
||||
|
||||
### 🔔 Notifications
|
||||
Two independent paths — a message-queue branch and an HTTP webhook branch — both converge on one automation flow and a shared formatter, so every app's alert reads the same regardless of source. Documented honestly rather than hidden: a decommissioned app's routing code is still present, and a credential that's supposed to live in one place is known to actually be synced across three.
|
||||
→ [docs/notifications.md](docs/notifications.md)
|
||||
|
||||
### 📦 Self-Hosted Registry & Build Pipeline
|
||||
Runs on the self-hosted Git server's own built-in container registry — no separate registry service to operate. Rebuilds trigger on a weekly schedule against upstream image digests rather than on every push, with a cheap digest check run first before committing to a full rebuild.
|
||||
→ [docs/registry-and-build.md](docs/registry-and-build.md)
|
||||
|
||||
### 🖥️ Dashy SOC Board
|
||||
One dashboard aggregates roughly a dozen distinct data sources — security alerts, logs, metrics, CI status, secrets health, DNS, backups, and more — into a single glanceable board. Acknowledgement state lives entirely client-side, no backend required.
|
||||
→ [docs/dashy-soc-board.md](docs/dashy-soc-board.md)
|
||||
|
||||
### ⏱️ Cron Scheduler
|
||||
Every scheduled job across the fleet is tracked in one inventory and visualized as a load heatmap, weighted by actual resource impact rather than raw job count.
|
||||
→ [docs/cron-scheduler.md](docs/cron-scheduler.md)
|
||||
|
||||
### 📝 Content Pipeline
|
||||
An in-progress pipeline connecting a structured content tracker through an automation tool out to a blog and file storage — documented honestly as unfinished rather than presented as done.
|
||||
→ [docs/content-pipeline.md](docs/content-pipeline.md)
|
||||
|
||||
### 🏗️ Infrastructure as Code
|
||||
Three tools, three responsibilities: image builds, provisioning, and configuration are kept as separate layers instead of one monolithic script.
|
||||
→ [docs/iac-pipeline.md](docs/iac-pipeline.md)
|
||||
|
||||
### 🧯 Disaster Recovery & Upgrades
|
||||
Three independent recovery layers — infrastructure-as-code, VM/LXC-level backups, and application-data backups — each cover a different kind of loss, and a real known gap (one data pool covered by neither) is documented rather than assumed handled. OS-level and application-level upgrades are deliberately decoupled systems; they don't share a rolling-batch mechanism, because doing so would let one host's expected no-op result silently abort every other host's run.
|
||||
→ [docs/disaster-recovery.md](docs/disaster-recovery.md)
|
||||
|
||||
## What's running
|
||||
|
||||
~55 Docker Compose stacks, grouped by purpose rather than by which host happens to run them — see [`stacks/`](stacks/): identity & security, platform/infra, media, productivity, and dev tools.
|
||||
|
||||
---
|
||||
|
||||
## 👀 What I’m Exploring
|
||||
I use my homelab as a real-world playground to deepen my understanding of core IT concepts. Some of the areas I’m actively exploring include:
|
||||
## About me
|
||||
|
||||
- Infrastructure-as-Code: provisioning and hardening hosts from scratch with Terraform + Packer + Ansible
|
||||
- Reverse-proxy architecture and identity: a dual-zone Caddy setup (internal service-to-service vs. user-facing) fronted by Authentik forward-auth
|
||||
- Workflow automation: Ansible for scheduled fleet maintenance, Kestra and n8n for everything else
|
||||
- Monitoring, observability, and resilient service design
|
||||
|
||||
Each project teaches me something new, and everything I learn pushes me further toward becoming a well-rounded IT/DevOps engineer.
|
||||
|
||||
---
|
||||
|
||||
## 🌱 What I’m Learning Right Now
|
||||
I’m currently focused on:
|
||||
|
||||
- Refining the Ansible roles and playbooks that keep the fleet patched and consistent
|
||||
- Tightening the Caddy/Authentik reverse-proxy and SSO design as new services get added
|
||||
- Running my own self-hosted Gitea instead of relying on external platforms
|
||||
- Improving scripting skills — Python and Bash are next on my list
|
||||
|
||||
I enjoy understanding not just how something works, but how to automate it, secure it, and integrate it cleanly into a larger system.
|
||||
|
||||
---
|
||||
|
||||
## ⚡ Fun Fact
|
||||
I’m entirely self-taught. Every tool, trick, concept, and workflow in my repos is something I learned by doing — from reading docs to breaking my lab at 2 a.m. and fixing it again.
|
||||
|
||||
---
|
||||
|
||||
## 📁 What You’ll Find in This Repository
|
||||
This repo is a sanitized mirror of the homelab I actually run day to day, organized by where each piece lives:
|
||||
|
||||
- `rocky-docker-lxc/` — the main application host: ~38 Docker Compose stacks (media, productivity, dev tools, databases)
|
||||
- `caddy-vm/` — the user-facing reverse proxy (Caddy + mTLS + Authentik forward-auth) and Hawser, its Dockhand connector agent
|
||||
- `monitoring-vm/` — Grafana, Prometheus, and Loki
|
||||
- `automation/` — the automation VM, which runs three separate repos side by side: `ansible/` (scheduled fleet maintenance), `automation-vm/` (Gitea, Kestra, n8n, NocoDB, Postiz, Node-RED, MQTT), and `iac/` (Terraform + Packer + provisioning Ansible)
|
||||
- `Proxmox/` — cheat-sheets and notes on the underlying hypervisor cluster
|
||||
|
||||
Real IPs, ports, credentials, and internal PKI details are stripped throughout — the goal is to show the actual architecture and how the pieces tie together, not to hand out a working blueprint of my network.
|
||||
|
||||
---
|
||||
|
||||
### 🚀 Let’s Connect
|
||||
Self-taught, building toward a career in IT/DevOps — everything in this repo is something I learned by doing, from reading docs to breaking my own lab and fixing it again.
|
||||
|
||||
[](https://www.linkedin.com/in/michael-surgey)
|
||||
[](https://x.com/nomadianation)
|
||||
@@ -61,9 +134,3 @@ Real IPs, ports, credentials, and internal PKI details are stripped throughout
|
||||
[](https://www.tiktok.com/@nomadianation)
|
||||
[](https://www.youtube.com/@nomadianation)
|
||||
[](https://nomadianation.thesabear.net/)
|
||||
|
||||
|
||||
<!---
|
||||
thesabear/thesabear is a ✨ special ✨ repository because its `README.md` (this file) appears on your GitHub profile.
|
||||
You can click the Preview link to take a look at your changes.
|
||||
--->
|
||||
Reference in new issue
Block a user