A collection of Docker Compose services for my homelab infrastructure, designed to place service containers on a Tailscale network without requiring a dedicated host for each service.
- Docker Engine
- Access to CIFS file share on blob
- Tailscale network (for sidecar containers)
Many services in this repository use the "sidecar" pattern to expose them on the Tailscale network. Each service that needs to be accessible over Tailscale imports the common sidecar-compose.yaml configuration, which:
- Adds a Tailscale container to the service stack
- Connects the container to my tailnet using an auth key
- Optionally exposes the service using Tailscale Serve
- Optionally enables Tailscale Funnel for external access
To use a sidecar with your service:
# Import the sidecar configuration
include:
- ../sidecar-compose.yaml
services:
# Your regular service definition
myservice:
image: example/service:latest
network_mode: "service:sidecar" # Share the network namespace
# ...
# Extend the sidecar to connect to your service
sidecar:
extends:
service: .sidecar
environment:
- TS_AUTH_KEY=${TS_AUTH_KEY}
- TS_SERVE_PORT=8080 # Port your service listens on
# - TS_FUNNEL=yes # Uncomment to enable public access
- Radarr: Movie management, connects to transmission and media storage
- Sonarr: TV show management
- Lidarr: Music management, connects to transmission and media storage
- Readarr: E-book and audiobook management
- Whisparr: Adult content management
- Jackett: Torrent site proxy/indexer
- Tautulli: Plex server statistics and monitoring
- FlareSolverr: Proxy server to bypass Cloudflare protection
- Calibre: E-book management system
- Calibre-Web: Web interface for Calibre library
- YACReader: Comic/manga reader and library manager
- Immich: Self-hosted photo and video backup solution
- ArchiveBox: Self-hosted web archive solution
- ChangeDetection: Monitor website changes
- Cobalt: YouTube and media downloader
- Pocket-ID: Self-hosted authentication server
- BreezeWiki: Privacy-focused wiki proxy
- Miniflux: RSS feed reader
- Tandoor: Recipe management system
- Prometheus: Metrics collection and storage
- Metrics: Collection of Prometheus exporters:
- Blackbox Exporter: Probes endpoints over HTTP, HTTPS, DNS, TCP and ICMP
- Plex Exporter: Monitors Plex Media Server metrics
- SNMP Exporter: Collects metrics from SNMP-enabled devices
- Synology Monitor: Monitors Synology NAS systems
- UDM Poller: Collects metrics from Ubiquiti UniFi devices
- OpenObserve: Log management and analytics
- Victoria-Logs: High-performance logs storage
- Loki: Log aggregation system
- Shop-Prometheus: Separate Prometheus instance for shop monitoring
- Atuin: Shell history sync server
- Hoarder: Data collection service
- SickChill: TV show management (legacy)
- Maybe: Personal finance management
- Watchtower: Automatic container updates
Most containers require a 64-bit architecture. While some can run on 32-bit ARM, many modern containers require 64-bit ARM or x86_64. Services are typically deployed across multiple hosts:
- NUC (bitbucket): Primary host for resource-intensive services
- NUC (prime): Primary host for video and AI-using services
- Synology NAS (blob): Storage-intensive services
This repository includes:
- Ansible playbooks for deployment automation
- Justfile with common tasks for service management
- Pre-commit hooks for code quality
- GitHub Actions for container builds
Services are deployed per host with playbook-ops-containers.yml. The list of
services for each host lives in host_vars/<host>.yml; each entry supports:
name— service directory name (required)compose_file— compose filename (defaultcompose.yml)path— service directory, if different fromnameup— set tofalseto bring the service down instead of up (defaulttrue)
# Deploy all services for a host
ansible-playbook playbook-ops-containers.yml --limit blob
# Preview changes without touching the host
ansible-playbook playbook-ops-containers.yml --limit blob --check
Use -e service=NAME to act on just one service (the run fails fast if the name
isn't defined for that host):
ansible-playbook playbook-ops-containers.yml --limit blob -e service=minio
Image pulls use each compose file's own policy by default. Pass -e pull=true
to pull images before bringing services up. Unlike up, pulling runs for real
even under --check, so you can refresh images without otherwise touching the
host:
ansible-playbook playbook-ops-containers.yml --limit blob -e pull=true
# combine with a single service
ansible-playbook playbook-ops-containers.yml --limit blob -e service=prometheus -e pull=true
# pull images for real, but don't bring anything up or down
ansible-playbook playbook-ops-containers.yml --limit blob -e pull_only=true
Pulling only applies to services that are being brought up (up not false).