* restart: Match Docker Compose semantics Change `cf restart` from doing `down + up` to using `docker compose restart`, matching the Docker Compose command behavior. This provides command naming parity with Docker Compose. Users who want the old behavior can use `cf down mystack && cf up mystack`. - Update restart implementation to use `docker compose restart` - Remove traefik regeneration from restart (no longer recreates containers) - Update all documentation and help text - Remove restart from self-update SSH handling (no longer involves down) * web: Clarify Update tooltip uses 'recreate' not 'restart' Avoid confusion now that 'restart' means something different. * web: Fix Update All tooltip to use 'recreates'
Compose Farm Examples
Real-world examples demonstrating compose-farm patterns for multi-host Docker deployments.
Stacks
| Stack | Type | Demonstrates |
|---|---|---|
| traefik | Infrastructure | Reverse proxy, Let's Encrypt, file-provider |
| mealie | Single container | Traefik labels, resource limits, environment vars |
| uptime-kuma | Single container | Docker socket, user mapping, custom DNS |
| paperless-ngx | Multi-container | Redis + App stack (SQLite) |
| autokuma | Multi-host | Demonstrates all keyword (runs on every host) |
Key Patterns
External Network
All stacks connect to a shared external network for inter-service communication:
networks:
mynetwork:
external: true
Create it on each host with consistent settings:
compose-farm init-network --network mynetwork --subnet 172.20.0.0/16
Traefik Labels (Dual Routes)
Stacks expose two routes for different access patterns:
- HTTPS route (
websecureentrypoint): For your custom domain with Let's Encrypt TLS - HTTP route (
webentrypoint): For.localdomains on your LAN (no TLS needed)
This pattern allows accessing stacks via:
https://mealie.example.com- from anywhere, with TLShttp://mealie.local- from your local network, no TLS overhead
labels:
# HTTPS route for custom domain (e.g., mealie.example.com)
- traefik.enable=true
- traefik.http.routers.myapp.rule=Host(`myapp.${DOMAIN}`)
- traefik.http.routers.myapp.entrypoints=websecure
- traefik.http.services.myapp.loadbalancer.server.port=8080
# HTTP route for .local domain (e.g., myapp.local)
- traefik.http.routers.myapp-local.rule=Host(`myapp.local`)
- traefik.http.routers.myapp-local.entrypoints=web
Note:
.localdomains require local DNS (e.g., Pi-hole, Technitium) to resolve to your Traefik host.
Environment Variables
Each stack has a .env file for secrets and domain configuration.
Edit these files to set your domain and credentials:
# Example: set your domain
echo "DOMAIN=example.com" > mealie/.env
Variables like ${DOMAIN} are substituted at runtime by Docker Compose.
NFS Volume Mounts
All data is stored on shared NFS storage at /mnt/data/:
volumes:
- /mnt/data/myapp:/app/data
This allows stacks to migrate between hosts without data loss.
Multi-Host Stacks
Stacks that need to run on every host (e.g., monitoring agents):
# In compose-farm.yaml
stacks:
autokuma: all # Runs on every configured host
Multi-Container Stacks
Database-backed apps with multiple services:
services:
redis:
image: redis:7
app:
depends_on:
- redis
NFS + PostgreSQL Warning: PostgreSQL should NOT run on NFS storage due to fsync and file locking issues. Use SQLite (safe for single-writer on NFS) or keep PostgreSQL data on local volumes (non-migratable).
AutoKuma Labels (Optional)
The autokuma example demonstrates compose-farm's multi-host feature - running the same stack on all hosts using the all keyword. AutoKuma itself is not part of compose-farm; it's just a good example because it needs to run on every host to monitor local Docker containers.
AutoKuma automatically creates Uptime Kuma monitors from Docker labels:
labels:
- kuma.myapp.http.name=My App
- kuma.myapp.http.url=https://myapp.${DOMAIN}
Quick Start
cd examples
# 1. Create the shared network on all hosts
compose-farm init-network
# 2. Start Traefik first (the reverse proxy)
compose-farm up traefik
# 3. Start other stacks
compose-farm up mealie uptime-kuma
# 4. Check status
compose-farm ps
# 5. Generate Traefik file-provider config for cross-host routing
compose-farm traefik-file --all
# 6. View logs
compose-farm logs mealie
# 7. Stop everything
compose-farm down --all
Configuration
The compose-farm.yaml shows a multi-host setup:
- primary (192.168.1.10): Runs Traefik and heavy stacks
- secondary (192.168.1.11): Runs lighter stacks
- autokuma: Runs on ALL hosts to monitor local containers
When Traefik runs on primary and a stack runs on secondary, compose-farm
automatically generates file-provider config so Traefik can route to it.
Traefik File-Provider
When stacks run on different hosts than Traefik, use traefik-file to generate routing config:
# Generate config for all stacks
compose-farm traefik-file --all -o traefik/dynamic.d/compose-farm.yml
# Or configure auto-generation in compose-farm.yaml:
traefik_file: /opt/stacks/traefik/dynamic.d/compose-farm.yml
traefik_stack: traefik
With traefik_file configured, compose-farm automatically regenerates the config after up, down, and update commands.