diff --git a/.env.selfhost.example b/.env.selfhost.example new file mode 100644 index 0000000000..1b5905b0a0 --- /dev/null +++ b/.env.selfhost.example @@ -0,0 +1,89 @@ +# Gittensory self-host — focused starter env (#1938) +# +# This is the SHORT path: the required secrets plus a conservative first-boot config, with nothing +# about the Cloudflare Worker deploy. Copy it to `.env` (gitignored) and fill in the placeholders. +# +# cp .env.selfhost.example .env +# +# For the EXHAUSTIVE list of every self-host env var (optional services, observability, backup, +# every AI provider) see `.env.example`'s "Self-host (Docker) — runtime config" section, or the +# generated reference table at https://gittensory.aethereal.dev/docs/self-hosting-configuration. +# Every value below is a SAMPLE placeholder — never commit real secrets. + +# ============================================================================= +# 1. Required secrets — the app will not start without these +# ============================================================================= +GITHUB_APP_ID=123456 +GITHUB_APP_SLUG=my-gittensory-app +GITHUB_APP_PRIVATE_KEY_FILE=/run/secrets/github-app-private-key.pem # or GITHUB_APP_PRIVATE_KEY= inline +GITHUB_WEBHOOK_SECRET=change-this-long-random-value +GITTENSOR_REGISTRY_URL=https://example.invalid/registry.json +GITTENSORY_API_TOKEN=change-this-32-byte-random-token +GITTENSORY_MCP_TOKEN=change-this-32-byte-random-token +INTERNAL_JOB_TOKEN=change-this-32-byte-random-token + +# REQUIRED once, for the first-run /setup wizard that creates the GitHub App manifest. Not needed +# after the App credentials above are filled in. +PUBLIC_API_ORIGIN=https://reviews.example.com +SELFHOST_SETUP_TOKEN=change-this-long-random-value + +# REQUIRED for control-panel access. Comma/whitespace-separated GitHub logins. FAIL-CLOSED: unset +# means nobody (not even you) can sign into the dashboard. +ADMIN_GITHUB_LOGINS=your-github-login + +# ============================================================================= +# 2. Storage — sane defaults, no action needed for a trial/single-node instance +# ============================================================================= +# SQLite is the default database (this file on the mounted data volume; migrations auto-apply). +# It's fine for a single maintainer instance. Move to Postgres (--profile postgres, see +# .env.example) once you're running multiple instances or a serious volume of repos. +DATABASE_PATH=/data/gittensory.sqlite + +# Redis is REQUIRED and starts automatically with the default compose stack (webhook dedup, rate +# limiting, the GitHub GET-response cache). Only override this if you're pointing at an external +# Redis instead of the bundled container. +REDIS_URL=redis://redis:6379 + +# ============================================================================= +# 3. Start conservative — leave AI, RAG, and REES off until webhook delivery and the +# deterministic review are working (see the Quickstart "boot the stack" step) +# ============================================================================= +SELFHOST_DEPLOYMENT_MODE=dry-run +GITTENSORY_REVIEW_REPOS=owner/repo +GITTENSORY_REVIEW_UNIFIED_COMMENT=true +GITTENSORY_REVIEW_SAFETY=true +GITTENSORY_REVIEW_GROUNDING=true +GITTENSORY_REVIEW_RAG=false +GITTENSORY_REVIEW_ENRICHMENT=false + +# ============================================================================= +# 4. AI provider — pick ONE block below and uncomment it (deterministic-only review if you skip +# this section entirely). See /docs/self-hosting-ai-providers for the full reference. +# ============================================================================= + +# --- Claude Code only (subscription) ----------------------------------------- +# AI_PROVIDER=claude-code +# CLAUDE_CODE_OAUTH_TOKEN= # from `claude setup-token` + +# --- Codex only (ChatGPT subscription) ---------------------------------------- +# Codex is fail-closed by default for self-host PR review (its OAuth credential lives on the same +# filesystem prompt-influenced reviews can read) -- the explicit opt-in below is required, and you +# must mount your Codex auth at /data/codex (the image exposes it as ~/.codex). +# AI_PROVIDER=codex +# GITTENSORY_ENABLE_UNSAFE_CODEX_REVIEWER=1 + +# --- Both, synthesized into one decision -------------------------------------- +# AI_PROVIDER=claude-code,codex +# AI_COMBINE=synthesis +# CLAUDE_CODE_OAUTH_TOKEN= +# GITTENSORY_ENABLE_UNSAFE_CODEX_REVIEWER=1 + +# ============================================================================= +# 5. Telemetry — informational only, no action needed +# ============================================================================= +# Running this image contributes anonymized gate-calibration data (verdict, outcome, cycle time -- +# never repo/PR names, code, or logins) to gittensory's central collector once your App is +# configured -- this starts automatically, it's the self-hosting contract, not a flag you turn on. +# The one way to disable it is the explicit air-gap flag below; see .env.example's Orb section for +# full privacy detail. +# ORB_AIR_GAP=true # air-gapped/OFFLINE deployments only: compute locally, never send diff --git a/.gitignore b/.gitignore index 40c67d7c18..c9e78ab791 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ output/ .env .env.* !.env.example +!.env.selfhost.example docker-compose.override.yml !docker-compose.override.yml.example *.local diff --git a/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx b/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx index 7bfe69fc01..4f73446716 100644 --- a/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx +++ b/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx @@ -33,6 +33,12 @@ function SelfHostingConfiguration() { title="Configuration" description="The self-host configuration model: deployment env, private per-repo policy, feature flags, and review modes." > +

+ This page is the exhaustive reference. For the short path — the required secrets plus a + conservative first-boot config — start with .env.selfhost.example in{" "} + Quickstart instead. +

+

Config layers

1. Copy the sample env

- The sample env contains placeholders only. Keep your real .env out of git and - prefer mounted secret files for multiline values like the GitHub App private key. + .env.selfhost.example is the short path: required secrets plus a conservative + first-boot config, with nothing about the Cloudflare Worker deploy. Copy it and fill in the + placeholders — keep your real .env out of git and prefer mounted secret files + for multiline values like the GitHub App private key.

+ + .env.selfhost.example already ships a conservative starting config —{" "} + dry-run mode, a small repo allowlist, unified comments, safety, and grounding, + with AI, RAG, and REES left off. Switch to live only after webhook delivery, logs, and + review output match expectations. For every optional env var (observability, backup, + additional AI providers) see .env.example's self-host section or the{" "} + generated reference table. + -

2. Start conservative

+

2. Choose your AI provider (optional)

- Begin with a small allowlist, unified comments, safety, and grounding. Leave AI, RAG, and - REES off until webhook delivery and deterministic review are working. + Skip this step for a fully deterministic review (no AI). Otherwise uncomment ONE of the + three blocks below in .env.selfhost.example — they're mutually exclusive, each + sets its own AI_PROVIDER. The self-host image bundles both CLIs by default; + credentials and provider choice are runtime-only.

- - dry-run computes reviews but suppresses writes. Switch to live only after - webhook delivery, logs, and review output match expectations. + + + + Codex stores its OAuth credential in auth.json on the same filesystem that + prompt-influenced reviews can read, so it requires explicit opt-in ( + GITTENSORY_ENABLE_UNSAFE_CODEX_REVIEWER=1) and a mounted{" "} + /data/codex auth volume. Claude Code has no equivalent restriction. See{" "} + AI providers for the full reference.

3. Boot the stack

+

+ Recommended: pull the published image. No local build, no Node toolchain — + the script pulls, restarts, and waits for the health check to pass. +

+

+ Pin a specific release instead of :latest, or point at your own registry: +

+ + + Contributors and anyone customizing the Dockerfile can still build locally —{" "} + docker compose up -d --build builds the gittensory service from + the checkout instead of pulling a published image. Everything else in this quickstart (env, + health checks, GitHub App) is identical either way. + +

+ A cold first boot on SQLite commonly logs a one-time{" "} + selfhost_migrations_applied burst and a brief Redis connection retry while the + sidecar finishes starting — both are expected and stop once the stack is warm. Anything else + that looks wrong, or a /ready that stays unhealthy past a couple minutes, is + covered in Troubleshooting. +

After the deterministic path is stable, continue with{" "} Configuration and then layer in AI, REES, or RAG deliberately.

+ +

Defaults at a glance

+

+ Nothing below needs a flag to start; everything past the first row needs an explicit{" "} + --profile (combine freely) or an explicit AI_PROVIDER. +

+ + + Orb fleet-calibration telemetry (verdict, outcome, cycle time — never repo names, code, or + logins) starts automatically once your GitHub App is configured — this is the self-hosting + contract, not a flag you turn on. The one way to disable it is the explicit air-gap flag: + set ORB_AIR_GAP=true for an instance that sends nothing. + ); } diff --git a/docker-compose.yml b/docker-compose.yml index b69db76494..2d901e58d5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,12 @@ -# One-command self-host for gittensory (#980): docker compose up --build +# Self-host for gittensory (#980). Two ways to boot the `gittensory` service — everything else in +# this compose file (profiles, env, health checks) is identical either way: # -# SECRETS: copy .env.example → .env, fill in your GitHub App credentials and any optional secrets. -# The file is gitignored. Every value below is a sample placeholder — never commit real secrets. +# RECOMMENDED: ./scripts/deploy-selfhost-image.sh # pulls the published image, no local build +# Building from source: docker compose up --build # for contributors / custom Dockerfile changes +# +# SECRETS: copy .env.selfhost.example → .env (the focused self-host starter) or .env.example → .env +# (the exhaustive reference) and fill in your GitHub App credentials and any optional secrets. The +# file is gitignored. Every value in either sample is a placeholder — never commit real secrets. # # PROFILES — activate optional services by passing --profile (combine freely): # @@ -17,7 +22,8 @@ # --profile runners GitHub Actions self-hosted runner # # Examples: -# docker compose up --build # SQLite + Redis, no external AI +# ./scripts/deploy-selfhost-image.sh # SQLite + Redis, published image +# docker compose up --build # SQLite + Redis, build from source # docker compose --profile postgres --profile caddy up -d # Postgres + HTTPS # docker compose --profile observability up -d # metrics + logs + dashboards # docker compose --profile tailscale --profile runners up -d # tailnet + CI runners