Skip to content

funkekaiser/homestack

Repository files navigation

🏠 Homestack

A self-hosted homelab running on a single Lenovo ThinkCentre M720t, orchestrated entirely with Docker Compose and a thin make wrapper. Each service is an independent compose project; everything is reverse-proxied through Caddy with automatic TLS, monitored, and backed up offsite.

This is a public showcase of my homelab configuration. Secrets live in gitignored env files (templates are provided), and a few private services are omitted. Domains are shown as example.com — swap in your own.

✨ Highlights

  • No Caddyfile — reverse-proxy routing is configured purely via Docker labels using caddy-docker-proxy, with TLS via the Cloudflare DNS challenge (no exposed ports for certs).
  • One make target per servicemake up-caddy, make logs-adguard, make restart-homepage, … plus aggregates (make up, make pull, make status).
  • Clean data separation — compose files and small configs live in git; app state, databases, and media live outside the repo and are never committed.
  • Defense in depth — Tailscale for remote access, AdGuard Home for DNS-level filtering, CrowdSec for intrusion detection, minimal WAN exposure.
  • Offsite backups~/data is backed up daily to a Hetzner Storage Box via Borgmatic, with healthcheck pings.

🧱 Architecture

                         ┌─────────────┐
        Internet ───────▶│  Cloudflare │  (DNS + DNS-01 challenge)
                         └──────┬──────┘
                                │
                         ┌──────▼──────┐
                         │    Caddy    │  reverse proxy, automatic TLS
                         │ (labels →   │  *.example.com
                         │  upstreams) │
                         └──────┬──────┘
                  ┌─────────────┼───────────────┐
            ┌─────▼────┐  ┌─────▼─────┐   ┌──────▼──────┐
            │  media   │  │ homepage  │   │  adguard…   │  + many more
            │  (Plex)  │  │ dashboard │   │  (LAN IP)   │
            └──────────┘  └───────────┘   └─────────────┘

  Remote access via Tailscale · Intrusion detection via CrowdSec

Networking

Network Type Purpose
proxy_network bridge 172.20.0.0/16 Service ↔ Caddy reachability
lan_macvlan macvlan 192.168.0.240/28 AdGuard gets a real LAN IP
network_mode: host Tailscale, CrowdSec, Home Assistant, Samba

📦 Services

Service Role
Caddy Reverse proxy + automatic TLS (label-driven, no Caddyfile)
Tailscale Mesh VPN for remote access
AdGuard Home Network-wide DNS + ad/tracker blocking (primary + Pi replica)
Plex (media/) Media server with hardware transcoding (Intel Quick Sync)
Homepage Single-pane dashboard with live service widgets
Uptime Kuma Uptime/status monitoring
Glances Host system metrics
Scrutiny Disk S.M.A.R.T. health monitoring
CrowdSec Crowd-sourced intrusion detection + firewall bouncer
Borgmatic Encrypted, deduplicated offsite backups
Diun Docker image update notifications
Samba SMB file sharing + Time Machine target
Home Assistant Home automation
Bitcoin node Pruned Bitcoin full node
Snowflake Tor Snowflake proxy (censorship circumvention)
Minecraft / V Rising Game servers (manual start)

🗂️ Repo layout

homelab/
├── Makefile              ← orchestration (one project per service)
├── .env.common           ← shared non-secret constants (TZ, PUID, PGID) — committed
├── .env.example          ← template for gitignored .env (external secrets)
├── .env.secrets.example  ← template for gitignored .env.secrets
├── SETUP.md              ← OS-level bootstrap notes
└── <service>/
    ├── compose.yaml      ← the service definition
    └── config/           ← small bind-mounted configs (where applicable)

App data (~/data/<service>/), media, and downloads live outside the repo and are intentionally not committed.

🚀 Getting started

# 1. Provide secrets (never committed)
cp .env.example .env                 && $EDITOR .env
cp .env.secrets.example .env.secrets && $EDITOR .env.secrets

# 2. Bring everything up (creates Docker networks first)
make up

# Per-service control
make up-caddy        # start one service
make logs-adguard    # tail logs
make restart-homepage
make status          # list running containers
make help            # all targets

🔐 Secrets & data — what's in git and what isn't

What Where In git?
Compose files + small configs <service>/
Shared non-secret constants .env.common
External secrets (Cloudflare token, app credentials) .env ❌ gitignored
High-sensitivity secrets (backup passphrase) .env.secrets ❌ gitignored
App runtime data (DBs, caches, metadata) ~/data/<service>/
Media & downloads /mnt/storage/

🖥️ Hardware

  • Server: Lenovo ThinkCentre M720t — Intel UHD 630 (Quick Sync hardware transcoding), MergerFS storage pool across multiple drives.
  • Backup DNS: Raspberry Pi running a second AdGuard Home instance.

Generated as a sanitized public mirror of a private homelab repo.

About

Self-hosted homelab: independent Docker Compose stacks orchestrated with make, reverse-proxied by Caddy with automatic TLS, monitored, and backed up offsite.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors