services: familiar: # Pull the image published to Gitea by .gitea/workflows/docker.yml. # Override the tag via .env: FAMILIAR_IMAGE (:latest / :main for prod, :dev # for the dev channel). `docker compose build` still rebuilds it locally. image: ${FAMILIAR_IMAGE:-git.hiddenden.cafe/hiddenden/familiar:latest} build: context: . dockerfile: docker/Dockerfile container_name: familiar restart: unless-stopped env_file: - .env environment: FAMILIAR_TRANSPORT: http FAMILIAR_HTTP_HOST: 0.0.0.0 FAMILIAR_HTTP_PORT: "8000" FAMILIAR_HTTP_PATH: ${FAMILIAR_HTTP_PATH:-/mcp} FAMILIAR_DATA_DIR: /data # Bearer token that clients must send as `Authorization: Bearer `. # REQUIRED here — binding 0.0.0.0 without it makes the server refuse to start. FAMILIAR_HTTP_AUTH_TOKEN: ${FAMILIAR_HTTP_AUTH_TOKEN:?set FAMILIAR_HTTP_AUTH_TOKEN in .env} # Public instance: keep writes off unless you consciously opt in. FAMILIAR_ENABLE_WRITES: ${FAMILIAR_ENABLE_WRITES:-false} # The encrypted token store (token.enc + key), audit log, and write toggle # live under /data. Run `familiar login` once on a machine with a browser, # then point this at that data dir (or copy token.enc + key into ./data). volumes: - ${FAMILIAR_DATA_DIR_HOST:-./data}:/data # Not published to the host — only reachable on the internal proxy network. expose: - "8000" read_only: true tmpfs: - /tmp security_opt: - no-new-privileges:true cap_drop: - ALL user: "1000:1000" networks: - proxy healthcheck: test: [ "CMD", "python", "-c", "import httpx; httpx.get('http://127.0.0.1:8000/healthz', timeout=5).raise_for_status()", ] interval: 30s timeout: 10s retries: 3 start_period: 10s labels: # --- Traefik TLS termination (Let's Encrypt) -------------------------- # # Enable if your reverse proxy is Traefik on the external `proxy` network. # Set FAMILIAR_DOMAIN and TRAEFIK_CERTRESOLVER in .env. traefik.enable: "true" traefik.docker.network: proxy traefik.http.routers.familiar.rule: Host(`${FAMILIAR_DOMAIN:-familiar.example.com}`) traefik.http.routers.familiar.entrypoints: websecure traefik.http.routers.familiar.tls: "true" traefik.http.routers.familiar.tls.certresolver: ${TRAEFIK_CERTRESOLVER:-letsencrypt} traefik.http.services.familiar.loadbalancer.server.port: "8000" networks: # Shared reverse-proxy network (Traefik/Caddy). Create once with: # docker network create proxy proxy: external: true