# VeilBrowser single-host deployment (evaluation / small fleets).
#
# Docs:  https://veilbrowser.net/docs/self-hosting/installation#deployment-templates
# Fetch: https://veilbrowser.net/deploy/compose/single-host.yaml
#
# Runs the whole stack on one box: the cluster-manager (LB + release origin),
# one cluster-mode worker, and an updater agent for drain-then-roll updates.
# For real fleets, run cluster-manager on its own box and scale workers with
# the k8s manifests or by adding more worker hosts.
#
#   curl -fsSL https://veilbrowser.net/deploy/compose/single-host.yaml -o single-host.yaml
#   curl -fsSL https://veilbrowser.net/deploy/compose/env.example -o .env
#   docker compose -f single-host.yaml up -d
#
# Images come from the license gate, which authorizes by PATH: your lowercased
# org key is the first path segment and there is no `docker login`. Set
# VEIL_ORG_KEY_LOWER (and VEIL_KEY) in .env — compose stops with the message
# below if you don't.
#
# Then point Puppeteer/Playwright at:  wss://<host>/launch?env={"VEIL_KEY":"<orgKey>", ...}

name: veil

services:
  cluster-manager:
    image: ${VEIL_REGISTRY_HOST:-registry.veilbrowser.net}/${VEIL_ORG_KEY_LOWER:?set VEIL_ORG_KEY_LOWER in .env (your org key, lowercased)}/cluster-manager:${VEIL_CLUSTER_MANAGER_TAG:-latest}
    restart: unless-stopped
    environment:
      # Both optional (zero-config): the auth secret auto-generates + persists
      # on first boot, and the admin is created in the first-run wizard.
      CLUSTER_MANAGER_ADMIN_PASSWORD: ${CLUSTER_MANAGER_ADMIN_PASSWORD:-}
      CLUSTER_MANAGER_AUTH_SECRET: ${CLUSTER_MANAGER_AUTH_SECRET:-}
      # The manager derives the registry its update check queries from these
      # two, landing on the same gate path the images above are pulled from.
      # Set VEIL_UPDATE_REGISTRY only to point that check somewhere else.
      VEIL_KEY: ${VEIL_KEY:?set VEIL_KEY}
      VEIL_REGISTRY_HOST: ${VEIL_REGISTRY_HOST:-registry.veilbrowser.net}
      RELEASE_CHANNEL: ${RELEASE_CHANNEL:-stable}
      CM_UPDATER_AGENT_URL: http://cm-updater:3999
      CM_UPDATER_AGENT_TOKEN: ${AGENT_TOKEN:?set AGENT_TOKEN}
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - cm-state:/srv/cluster-manager
      - cm-webroot:/var/www/release
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:4180/api/system/version"]
      interval: 30s
      timeout: 5s
      retries: 3

  worker:
    image: ${VEIL_REGISTRY_HOST:-registry.veilbrowser.net}/${VEIL_ORG_KEY_LOWER:?set VEIL_ORG_KEY_LOWER in .env (your org key, lowercased)}/local-api:${WORKER_IMAGE_TAG:-latest}
    restart: unless-stopped
    privileged: true # chromium sandbox (or use the seccomp profile + SYS_ADMIN)
    tmpfs:
      - /tmp:size=2g,mode=1777
    shm_size: 1g
    environment:
      API_KEY: ${API_KEY:?set API_KEY}
      VEIL_KEY: ${VEIL_KEY:?set VEIL_KEY} # org key for saas-api authorize
      VEIL_WORKER_ID: worker-1
      SAAS_API_URL: ${SAAS_API_URL:-https://api.veilbrowser.net}
      RELEASE_ORIGIN_URL: http://cluster-manager
      VEIL_BOOTSTRAP_RELEASES: "1"
      VEIL_MAX_BROWSERS: ${VEIL_MAX_BROWSERS:-0}
      VEIL_AUTO_CLOSE: ${VEIL_AUTO_CLOSE:-false}
      VEIL_IDLE_BROWSER_TIMEOUT: ${VEIL_IDLE_BROWSER_TIMEOUT:-0}
    volumes:
      - veil-install:/var/veil/install
    depends_on:
      - cluster-manager
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:38923/health"]
      interval: 30s
      timeout: 5s
      retries: 3

  # Updater agent for the cluster-manager container (self-update target). A
  # container cannot pull and recreate itself, so the manager delegates here when
  # you click Update.
  #
  # This replaced a watchtower profile that did the same job unattended.
  # Watchtower is archived upstream, and it recreates a container from the
  # RUNNING container's config rather than from compose — so a release that adds
  # an env var would pull the image and then boot with the old configuration.
  cm-updater:
    image: ${VEIL_REGISTRY_HOST:-registry.veilbrowser.net}/${VEIL_ORG_KEY_LOWER:?set VEIL_ORG_KEY_LOWER in .env (your org key, lowercased)}/updater-agent:${AGENT_TAG:-latest}
    restart: unless-stopped
    environment:
      AGENT_TOKEN: ${AGENT_TOKEN:?set AGENT_TOKEN}
      COMPOSE_PROJECT: veil
      COMPOSE_FILE: /work/single-host.yaml
      COMPOSE_SERVICE: cluster-manager
      # Persists the new tag, so a later `up -d` does not silently roll back to
      # the tag still written in .env.
      AGENT_ENV_FILE: /work/.env
      TAG_ENV_KEY: VEIL_CLUSTER_MANAGER_TAG
      WORKER_HEALTH_URL: http://cluster-manager:4180/api/system/version
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      # compose resolves ${...} from the .env beside the file, so mount both.
      - ./single-host.yaml:/work/single-host.yaml:ro
      - ./.env:/work/.env

volumes:
  cm-state:
  cm-webroot:
  veil-install:
