Skip to content

Repository files navigation

🍚 arroz — my homelab

One box, 19 self-hosted services, no port forwarding: remote access is Tailscale only.

Docker Compose Caddy Tailscale AdGuard Home Komodo Python 19 services

This is the full config for the Linux box under my desk (hostname arroz, Portuguese for rice). It runs the stuff my family and I actually use every day: passwords, shopping lists, fitness tracking, location history, Spotify stats, a retro game library. It also runs a couple of things I wrote myself.

Every service is a small Docker Compose stack in its own folder. They all share one homelab network behind a single Caddy reverse proxy. Nothing is exposed to the public internet. At home I reach everything through local DNS names, and away from home I go through Tailscale.

Architecture

  • Two ways in, one proxy. Plain-HTTP *.homelab names for the LAN, resolved by AdGuard. Services that need HTTPS (Vaultwarden, the PWAs, OAuth callbacks) get their own port on the Tailscale hostname, using a real cert from tailscale cert.
  • Databases stay private. Postgres, MariaDB, Mongo and Redis only live on per-stack internal networks. Only the frontends join homelab.
  • Ops: Homepage is the dashboard, Komodo manages the stacks, WUD checks for image updates every morning, and Netdata watches the host.

Services

Service What it does here
Infra AdGuard Home Network-wide DNS, ad blocking and the *.homelab names
Caddy The one reverse proxy in front of everything
Homepage Dashboard with live widgets for every service
Komodo Web UI to deploy and manage the compose stacks
What's Up Docker Tells me when an image has a new version
Netdata Real-time host and container metrics
Family Vaultwarden Bitwarden-compatible password manager
KitchenOwl Shared grocery list and recipes
Dawarich Self-hosted Google Timeline replacement
SparkyFitness Nutrition and workout tracking
Home Assistant Home automation
Productivity ConvertX Convert any file to any format
Stirling PDF Every PDF tool you'd ever need
Excalidraw Whiteboard and diagrams
Obsidian LiveSync CouchDB backend syncing my Obsidian vault across devices
PR Review ⭐ Custom: static-analysis bot for my GitHub PRs
Fun Your Spotify Spotify Wrapped, but all year round
RomM Retro game library that plays in the browser
insta-bot ⭐ Custom: answers League of Legends invites in the group chat

Things I built

🔍 prreview/: self-hosted PR reviewer

A Python service that polls GitHub for open PRs and mirrors each repo. It runs ruff, bandit, semgrep plus a raw syntax check (YAML/JSON/XML) on the files the PR changes, separates findings on the lines it actually touched from the rest, and publishes an HTML report at prreview.homelab. It remembers the head SHA of every PR, so each push is analysed exactly once. The GitHub token goes through GIT_CONFIG_* env vars, never argv or a stored remote URL, so it never shows up in ps.

🎮 insta-bot/: "bora" as a service

My friends invite each other to play LoL in an Instagram group chat, and this bot answers for me. It drives a real headful Chrome under Xvfb with Playwright and watches the thread with a DOM MutationObserver. When someone sends an invite ("siga jogar?", "alguém rankeds?", "flex?") it replies with a random "bora", with a global cooldown and accent-insensitive wildcard triggers. It runs as a systemd timer during evening hours only, and a League-themed control panel behind Caddy basic auth handles on/off, dry-run, schedule, triggers and replies, all live without a restart.

💾 scripts/backup.sh: consistent backups the dumb way

It stops every container, tars the homelab folder, the Docker volumes and the certs from a throwaway Alpine container, then starts everything again. About 60 seconds of downtime buys a crash-consistent copy of every Postgres, Mongo and SQLite database, with zero per-service dump logic. It also warns about any new bind mount outside the backed-up paths.

Secrets

Nothing sensitive lives in this repo:

  • Every stack reads its credentials from a local .env, which is gitignored. Each one has a committed .env.example that lists the keys it needs.
  • Machine-specific values (my tailnet hostname and Tailscale IP) are env vars too: ${TS_HOST} in compose, {$TS_HOST} in the Caddyfile, {{HOMEPAGE_VAR_TS_HOST}} in Homepage.
  • App data (data/, databases, Home Assistant config, logs) is gitignored.

Layout

.
├── caddy/            Caddyfile + reverse proxy stack
├── <service>/        docker-compose.yml, .env.example, config (if any)
├── homepage/config/  dashboard: services, widgets, theme
├── prreview/         custom PR reviewer (Dockerfile + Python)
├── insta-bot/        custom Instagram bot (Python + systemd units + web panel)
└── scripts/          backup

Running a stack

docker network create homelab          # once
cd vaultwarden
cp .env.example .env && $EDITOR .env
docker compose up -d

For the Tailscale HTTPS ports, put the cert from tailscale cert <host> in /etc/caddy/certs/ and set TS_HOST in caddy/.env.


Built and broken at home by @Bebaz0.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages