Getting Started¶
This guide walks you through installing Compose Farm and setting up your first multi-host deployment.
Prerequisites¶
Before you begin, ensure you have:
- uv (recommended) or Python 3.11+
- SSH key-based authentication to your Docker hosts
- Docker and Docker Compose installed on all target hosts
- Shared storage for compose files (NFS, Syncthing, etc.)
Installation¶
One-liner (recommended)¶
This installs uv if needed, then installs compose-farm.
Using uv¶
If you already have uv installed:
Using pip¶
If you already have Python 3.11+ installed:
Using Docker¶
docker run --rm \
-v $SSH_AUTH_SOCK:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent \
-v ./compose-farm.yaml:/root/.config/compose-farm/compose-farm.yaml:ro \
ghcr.io/basnijholt/compose-farm up --all
Verify Installation¶
SSH Setup¶
Compose Farm uses SSH to run commands on remote hosts. You need passwordless SSH access.
Option 1: SSH Agent (default)¶
If you already have SSH keys loaded in your agent:
Option 2: Dedicated Key (recommended for Docker)¶
For persistent access when running in Docker:
This creates ~/.ssh/compose-farm/id_ed25519 and copies the public key to each host.
Shared Storage Setup¶
Compose files must be accessible at the same path on all hosts. Common approaches:
NFS Mount¶
# On each Docker host
sudo mount nas:/volume1/compose /opt/compose
# Or add to /etc/fstab
nas:/volume1/compose /opt/compose nfs defaults 0 0
Directory Structure¶
/opt/compose/ # compose_dir in config
├── plex/
│ └── docker-compose.yml
├── sonarr/
│ └── docker-compose.yml
├── radarr/
│ └── docker-compose.yml
└── jellyfin/
└── docker-compose.yml
Configuration¶
Create Config File¶
Create ~/.config/compose-farm/compose-farm.yaml:
Single host example¶
# Where compose files are located (one folder per stack)
compose_dir: /opt/stacks
hosts:
local: localhost
stacks:
plex: local
sonarr: local
radarr: local
Multi-host example¶
# Where compose files are located (same path on all hosts)
compose_dir: /opt/compose
# Define your Docker hosts
hosts:
nuc:
address: 192.168.1.10
user: docker # SSH user
hp:
address: 192.168.1.11
# user defaults to current user
# Map stacks to hosts
stacks:
plex: nuc
sonarr: nuc
radarr: hp
Each entry in stacks: maps to a folder under compose_dir that contains a compose file.
For cross-host HTTP routing, add Traefik labels and configure traefik_file (see Traefik Integration).
Validate Configuration¶
This validates syntax without SSH connections. For full validation:
First Commands¶
Check Status¶
Shows all configured stacks and their status.
Start All Stacks¶
Starts all stacks on their assigned hosts.
Start Specific Stacks¶
Apply Configuration¶
The most powerful command - reconciles reality with your config:
This will: 1. Start stacks in config but not running 2. Migrate stacks on wrong host 3. Stop stacks removed from config
Docker Network Setup¶
If your stacks use an external Docker network:
Default network: mynetwork with subnet 172.20.0.0/16
Example Workflow¶
1. Add a New Stack¶
Create the compose file:
# On any host (shared storage)
mkdir -p /opt/compose/prowlarr
cat > /opt/compose/prowlarr/docker-compose.yml << 'EOF'
services:
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
container_name: prowlarr
environment:
- PUID=1000
- PGID=1000
volumes:
- /opt/config/prowlarr:/config
ports:
- "9696:9696"
restart: unless-stopped
EOF
Add to config:
Start the stack:
2. Move a Stack to Another Host¶
Edit compose-farm.yaml:
Apply the change:
Or use apply to reconcile everything:
3. Update All Stacks¶
Next Steps¶
- Configuration Reference - All config options
- Commands Reference - Full CLI documentation
- Traefik Integration - Multi-host routing
- Best Practices - Tips and limitations