Skip to content

Best Practices

Tips, limitations, and recommendations for using Compose Farm effectively.

Limitations

No Cross-Host Networking

Compose Farm moves containers between hosts but does not provide cross-host networking. Docker's internal DNS and networks don't span hosts.

What breaks when you move a stack:

Feature Works? Why
http://redis:6379 No Docker DNS doesn't cross hosts
Docker network names No Networks are per-host
DATABASE_URL=postgres://db:5432 No Container name won't resolve
Host IP addresses Yes Use 192.168.1.10:5432

What Compose Farm Doesn't Do

  • No overlay networking (use Swarm/Kubernetes)
  • No service discovery across hosts
  • No automatic dependency tracking between compose files
  • No health checks or restart policies beyond Docker's
  • No secrets management beyond Docker's

Stack Organization

Keep Dependencies Together

If services talk to each other, keep them in the same compose file on the same host:

# /opt/compose/myapp/docker-compose.yml
services:
  app:
    image: myapp
    depends_on:
      - db
      - redis

  db:
    image: postgres

  redis:
    image: redis
# compose-farm.yaml
stacks:
  myapp: nuc  # All three containers stay together

Separate Standalone Stacks

Stacks whose services don't talk to other containers can be anywhere:

stacks:
  # These can run on any host
  plex: nuc
  jellyfin: hp
  homeassistant: nas

  # These should stay together
  myapp: nuc  # includes app + db + redis

Cross-Host Communication

If services MUST communicate across hosts, publish ports:

# Instead of
DATABASE_URL=postgres://db:5432

# Use
DATABASE_URL=postgres://192.168.1.10:5432
# And publish the port
services:
  db:
    ports:
      - "5432:5432"

Multi-Host Stacks

When to Use all

Use all for stacks that need local access to each host:

stacks:
  # Need Docker socket
  dozzle: all          # Log viewer
  portainer-agent: all  # Portainer agents
  autokuma: all        # Auto-creates monitors

  # Need host metrics
  node-exporter: all   # Prometheus metrics
  promtail: all        # Log shipping

Host-Specific Lists

For stacks on specific hosts only:

stacks:
  # Only on compute nodes
  gitlab-runner: [nuc, hp]

  # Only on storage nodes
  minio: [nas-1, nas-2]

Migration Safety

Pre-flight Checks

Before migrating, Compose Farm verifies: - Compose file is accessible on new host - Required mounts exist on new host - Required networks exist on new host

Data Considerations

Compose Farm doesn't move data. Ensure:

  1. Shared storage: Data volumes on NFS/shared storage
  2. External databases: Data in external DB, not container
  3. Backup first: Always backup before migration

Safe Migration Pattern

# 1. Preview changes
cf apply --dry-run

# 2. Verify target host can run the stack
cf check myservice

# 3. Apply changes
cf apply

State Management

When to Refresh

Run cf refresh after: - Manual docker compose commands - Container restarts - Host reboots - Any changes outside Compose Farm

cf refresh --dry-run  # Preview
cf refresh            # Sync

State Conflicts

If state doesn't match reality:

# See what's actually running
cf refresh --dry-run

# Sync state
cf refresh

# Then apply config
cf apply

Shared Storage

NFS Best Practices

# Mount options for Docker compatibility
nas:/compose /opt/compose nfs rw,hard,intr,rsize=8192,wsize=8192 0 0

Directory Ownership

Ensure consistent UID/GID across hosts:

services:
  myapp:
    environment:
      - PUID=1000
      - PGID=1000

Config vs Data

Keep config and data separate:

/opt/compose/          # Shared: compose files + config
├── plex/
│   ├── docker-compose.yml
│   └── config/        # Small config files OK

/mnt/data/             # Shared: large media files
├── movies/
├── tv/
└── music/

/opt/appdata/          # Local: per-host app data
├── plex/
└── sonarr/

Performance

Parallel Operations

Compose Farm runs operations in parallel. For large deployments:

# Good: parallel by default
cf up --all

# Avoid: sequential updates when possible
for svc in plex sonarr radarr; do
  cf update $svc
done

SSH Connection Reuse

SSH connections are reused within a command. For many operations:

# One command, one connection per host
cf update --all

# Multiple commands, multiple connections (slower)
cf update plex && cf update sonarr && cf update radarr

Traefik Setup

Stack Placement

Put Traefik on a reliable host:

stacks:
  traefik: nuc  # Primary host with good uptime

Same-Host Stacks

Stacks on the same host as Traefik use Docker provider:

traefik_stack: traefik

stacks:
  traefik: nuc
  portainer: nuc   # Docker provider handles this
  plex: hp         # File provider handles this

Middleware in Separate File

Define middlewares outside Compose Farm's generated file:

# /opt/traefik/dynamic.d/middlewares.yml
http:
  middlewares:
    redirect-https:
      redirectScheme:
        scheme: https

Backup Strategy

What to Backup

Item Location Method
Compose Farm config ~/.config/compose-farm/ Git or copy
Compose files /opt/compose/ Git
State file ~/.config/compose-farm/state.yaml Optional (can refresh)
App data /opt/appdata/ Backup solution

Disaster Recovery

# Restore config
cp backup/compose-farm.yaml ~/.config/compose-farm/

# Refresh state from running containers
cf refresh

# Or start fresh
cf apply

Troubleshooting

Common Issues

Stack won't start:

cf check myservice      # Verify mounts/networks
cf logs myservice       # Check container logs

Migration fails:

cf check myservice      # Verify new host is ready
cf init-network newhost # Create network if missing

State out of sync:

cf refresh --dry-run    # See differences
cf refresh              # Sync state

SSH issues:

cf ssh status           # Check key status
cf ssh setup            # Re-setup keys

Security Considerations

SSH Keys

  • Use dedicated SSH key for Compose Farm
  • Limit key to specific hosts if possible
  • Don't store keys in Docker images

Network Exposure

  • Published ports are accessible from network
  • Use firewalls for sensitive services
  • Consider VPN for cross-host communication

Secrets

  • Don't commit .env files with secrets
  • Use Docker secrets or external secret management
  • Avoid secrets in compose file labels

Comparison: When to Use Alternatives

Scenario Solution
2-10 hosts, static stacks Compose Farm
Cross-host container networking Docker Swarm
Auto-scaling, self-healing Kubernetes
Infrastructure as code Ansible + Compose Farm
High availability requirements Kubernetes or Swarm