docs/Using Flareo/Generate compose files

Generate compose files

flareo compose <slug> emits a docker-compose.yaml with the image pinned to the current verified digest, plus sensible defaults for ports, volumes, and health checks.

Usage

flareo compose vaultwarden > docker-compose.yaml
flareo compose gitea --port 3001 --domain git.example.com -o docker-compose.yaml
flareo compose paperless-ngx --with-caddy > docker-compose.yaml

By default the command writes the compose file to stdout so you can pipe it wherever you want. Use -o / --output to write directly to a file.

What it generates

  • image: pinned to public.ecr.aws/flareo/<slug>@sha256:<current-digest>
  • a named volume for persistent data (module-specific path)
  • port bound to 127.0.0.1:<suggested-port>:<container-port>
  • restart: unless-stopped
  • environment variables with documented defaults (module-specific)
  • sidecar services for modules that need them (Linkwarden's Postgres, Paperless-ngx's Redis)
  • with --with-caddy, an additional Caddy reverse-proxy service plus a Caddyfile snippet in comments

If the module's current status is not verified, the command still generates the file but prints a loud warning on stderr so you notice before deploying.

Options

FlagEffect
--port <N>Override the default host port
--domain <d>Fill environment variables like NEXTAUTH_URL
-o, --output <path>Write to a file instead of stdout
--with-caddyAdd a Caddy reverse-proxy service

What the output looks like

Running flareo compose vaultwarden --domain vw.example.com produces something like:

# Vaultwarden v1.30.3 — docker-compose.yaml
# Generated by flareo compose vaultwarden on 2026-04-23
#
# Image pinned by digest. To upgrade, run:
#   flareo compose vaultwarden > docker-compose.yaml
# and diff against this file.
#
# Set SIGNUPS_ALLOWED=true temporarily to create the first admin user.

services:
  vaultwarden:
    image: public.ecr.aws/flareo/vaultwarden@sha256:abc123...
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"
    environment:
      DOMAIN: "https://vw.example.com"
      SIGNUPS_ALLOWED: "false"
      WEBSOCKET_ENABLED: "true"
    volumes:
      - vaultwarden_data:/data

volumes:
  vaultwarden_data:

Save that to docker-compose.yaml and run docker compose up -d. The digest is baked in; you'll never accidentally upgrade unless you regenerate.

Why digest, not tag

If you write image: public.ecr.aws/flareo/vaultwarden:latest, you get a moving target. The next time Docker pulls the image, it might be a different build with different CVE exposure, a different upstream version, different defaults.

Writing image: public.ecr.aws/flareo/vaultwarden@sha256:abc123... pins you to one exact byte sequence. You upgrade on your schedule by changing the digest, not on ours by leaving :latest in a running deployment.

Next steps