name: drivervault-aio

# Single all-in-one container: PocketBase + API Server + Web App (nginx).
# The build context is the project root so the Dockerfile can reach both
# "API Server/" and "Web App/". Copy .env.example to .env before starting.

services:
  drivervault:
    build:
      # Project root (one level up from this compose file).
      context: ..
      dockerfile: Docker-AIO/Dockerfile
      args:
        # Empty -> bundle uses same-origin "/api", proxied internally by nginx.
        - VITE_API_BASE=${VITE_API_BASE:-}
        # Bare name = pass through only when set in the environment, so an unset
        # PB_VERSION leaves the Dockerfile pin in place instead of overriding it
        # with an empty string (which would resolve "latest" at build time).
        - PB_VERSION
    image: drivervault-aio
    container_name: drivervault-aio
    restart: unless-stopped
    environment:
      # Superuser (also used by the API Server to authenticate to PocketBase).
      PB_ADMIN_EMAIL: "${PB_ADMIN_EMAIL:?set PB_ADMIN_EMAIL in .env}"
      PB_ADMIN_PASSWORD: "${PB_ADMIN_PASSWORD:?set PB_ADMIN_PASSWORD in .env}"
      # Match CORS to the web origin (only used if a browser calls the API directly).
      CORS_ALLOW_ORIGINS: "${CORS_ALLOW_ORIGINS:-http://localhost:8090}"
      # Probed by the panel status page. nginx serves the Web App on port 80
      # inside this container, so plain localhost:8090 would never answer.
      # Override WEBAPP_URL in .env to make a change from the panel's Web App
      # screen permanent; the panel alone only holds it for the container's life.
      WEBAPP_URL: "${WEBAPP_URL:-http://127.0.0.1:80}"
      # Schema + super-admin bootstrap (idempotent). Leave this ON: a release can
      # add collections or fields the server needs, and a stack that skips the
      # bootstrap never gets them. The API Server self-heals exactly one thing —
      # app_settings, the collection holding the plugin settings, which it
      # creates on demand because it cannot serve the plugin panel without it.
      # Every other schema change still depends on this flag. Turn it off only
      # for a database you know already matches the release.
      PB_BOOTSTRAP: "${PB_BOOTSTRAP:-true}"
      DRIVERVAULT_SUPERADMIN_EMAIL: "${DRIVERVAULT_SUPERADMIN_EMAIL:-}"
      DRIVERVAULT_SUPERADMIN_PASSWORD: "${DRIVERVAULT_SUPERADMIN_PASSWORD:-}"
      DRIVERVAULT_SUPERADMIN_NAME: "${DRIVERVAULT_SUPERADMIN_NAME:-Administrator}"
      # OCPP charger control (Anker Solix). This image serves plain HTTP, so a
      # charger can only connect when TLS is terminated in front of it (set
      # OCPP_PUBLIC_URL to the public wss:// base) — or, on a trusted network,
      # with OCPP_REQUIRE_TLS=false.
      OCPP_REQUIRE_TLS: "${OCPP_REQUIRE_TLS:-true}"
      OCPP_PUBLIC_URL: "${OCPP_PUBLIC_URL:-}"
    ports:
      - "${WEB_PORT:-8090}:80"    # Web App
      - "${PB_PORT:-8070}:8070"   # PocketBase admin UI / API
      - "${API_PORT:-8080}:8080"  # API Server + panel (root /) + /ocpp/{serial}
    volumes:
      # The only volume: the API Server keeps no state on disk, so everything
      # it owns — plugin settings included — lives in the database.
      - pb_data:/pb/pb_data
    healthcheck:
      # All three processes must answer. Declared here as well as in the image so
      # the check is visible, and works against an older pulled image.
      test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8070/api/health >/dev/null && wget -qO- http://127.0.0.1:8080/healthz >/dev/null && wget -qO- http://127.0.0.1:80/healthz >/dev/null || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 60s

volumes:
  pb_data:
