This is my personal Raspberry Pi 5 homelab setup. It runs a bunch of self-hosted services that I actually use daily - everything from managing my ebook collection to tracking expenses and meal planning.
Note: This repo controls my actual running services, so while I'm happy to chat about the setup via issues, I probably won't accept pull requests since they'd mess with my stuff.
Here's what's actually running on the Pi:
Service | Purpose | Access |
---|---|---|
Homepage | Nice dashboard for everything | https://lab.teixe.es |
Caddy | Handles SSL and routing | Internal |
CoreDNS | Local DNS server | 172.20.10.254 |
Calibre Web Automated | My ebook library | Via Homepage |
Actual Budget | Track spending | Via Homepage |
KitchenOwl | Grocery lists and meal planning | Via Homepage |
Mealie | Recipe collection | Via Homepage |
AdventureLog | Track trips and hikes | Via Homepage |
OpenBooks | Book downloads from IRC | Via Homepage |
.
├── cloud-init/ # Raspberry Pi provisioning
│ ├── flash.sh # SD card imaging script
│ ├── user-data # Cloud-init configuration
│ └── network-config # Network setup
├── docker/ # Container orchestration
│ ├── docker-compose.yml # Main service definitions
│ └── config/ # Service-specific configurations
│ ├── caddy/ # Reverse proxy config
│ ├── coredns/ # DNS server config
│ ├── homepage/ # Dashboard configuration
│ └── adventurelog/ # Adventure tracking config
├── tailscale/ # VPN network configuration
│ └── policy.hujson # Tailnet ACL policy
├── .github/workflows/ # CI/CD automation
└── Justfile # Task automation recipes
- Just for running commands
- SOPS for managing secrets
- Docker & Docker Compose
- GPG for encryption
-
Flash the Pi
just flash /dev/sdX # Replace with your SD card device
-
Handle secrets
# If you have my keys, decrypt existing secrets: just decrypt # Otherwise create your own .env files and encrypt them: just encrypt
-
Start everything
just docker-up
Command | What it does |
---|---|
just |
Show all commands |
just flash /dev/sdX |
Make a bootable Pi SD card |
just encrypt |
Encrypt secrets |
just decrypt |
Decrypt secrets |
just fetch-updates |
Pull latest from git |
just docker-up |
Update everything and restart services |
I'm using macvlan so containers get real IP addresses that work with Tailscale:
- Network:
172.20.10.0/24
- Gateway:
172.20.10.1
- DNS:
172.20.10.254
(the CoreDNS container)
- All secrets are encrypted with SOPS before going into git
- Services talk to each other through Docker networks
- External access goes through Tailscale VPN
- Caddy handles SSL certificates automatically via Cloudflare
- GitHub Actions updates Tailscale rules and triggers deployments
- Docker restarts unhealthy containers
- Config lives in git, but you'll want to backup the data folders separately
# Check if compose file is valid
docker compose config
# See what's running
docker compose ps
# Watch logs
docker compose logs -f [service_name]
- Add it to
docker/docker-compose.yml
- Put config files in
docker/config/[service]/
- Add it to the Homepage dashboard
- Update Caddyfile if it needs external access
- Test deployment with
just docker-up
Since this controls my actual running infrastructure:
- Issues with questions or suggestions are totally fine
- Pull requests probably won't get merged since they'd break my stuff
- But feel free to fork it and make it your own!
MIT license - do whatever you want with it.