# Verdant — plug n' play via GHCR. No build needed: # # docker compose up -d # # Then open http://localhost:3113 (or your GARDEN_PORT). # # Optional: copy .env.example to .env to set the host port, the public URL, # or your Immich server details. Anything in .env is picked up automatically. # # To build the image locally instead of pulling, uncomment the `build:` line. services: garden: image: ghcr.io/elyld/verdant:latest # build: . container_name: verdant-garden-log restart: unless-stopped ports: - "${GARDEN_PORT:-3113}:8000" # Let the container reach services on the Docker host by hostname # (Linux needs this; Docker Desktop resolves it already). Used for # host.docker.internal URLs, e.g. Ollama or Immich on the same machine. extra_hosts: - "host.docker.internal:host-gateway" environment: GARDEN_DATA_DIR: /data GARDEN_UPLOAD_DIR: /uploads # Tunnel-ready (optional): set TUNNEL_MODE=true in your .env when Verdant # sits behind a Cloudflare Tunnel. Flips the secure preset: HSTS header, # /docs disabled, and the tunnel's proxy headers trusted so rate limiting # sees real client IPs. No behavior change when false (default). TUNNEL_MODE: ${TUNNEL_MODE:-false} GARDEN_DATABASE_URL: sqlite:////data/garden.db # Base URL used to resolve relative URLs in "Import from URL". # Set to your server's real address, e.g. https://photos.yourdomain.com GARDEN_PUBLIC_URL: ${GARDEN_PUBLIC_URL:-http://localhost:3113} # Immich integration (optional). Leave empty to keep it disabled. # If Verdant runs in Docker on the same machine as Immich, use # http://host.docker.internal:2283 so the container can reach your host. IMMICH_BASE_URL: ${IMMICH_BASE_URL:-} IMMICH_API_KEY: ${IMMICH_API_KEY:-} # Frost countdown (optional): your average first fall frost, YYYY-MM-DD. # Shows a small "days to first frost" pill in the header. FIRST_FROST_DATE: ${FIRST_FROST_DATE:-} volumes: # SQLite database file + uploaded images persist on the host. - ./data:/data - ./uploads:/uploads healthcheck: test: - CMD - python - -c - import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8000/api/health', timeout=4).status==200 else 1) interval: 30s timeout: 5s start_period: 10s retries: 3 # --- Cloudflare Tunnel (optional) --- # To reach Verdant from outside your LAN without opening any ports: # 1. In the Cloudflare dashboard: Zero Trust -> Networks -> Tunnels -> # create a tunnel, add a public hostname pointing at http://garden:8000. # Copy the tunnel token. # 2. Comment out the `ports:` block on the garden service above, so the app # is NOT on your LAN directly — only this tunnel container can reach it. # (Keep `ports:` if you want LAN access too; the tunnel still works, # but LAN clients bypass Cloudflare Access.) # 3. Put TUNNEL_TOKEN= and TUNNEL_MODE=true in your .env. # 4. Uncomment the service below and `docker compose up -d`. # 5. Add a Cloudflare Access policy (e.g. email one-time PIN) on the # hostname — that's the sign-on, handled by Cloudflare, not Verdant. # # cloudflared: # image: cloudflare/cloudflared:latest # container_name: verdant-tunnel # restart: unless-stopped # command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN} # depends_on: # - garden