Repository navigation
Expand file tree
/
Copy path.env.example
More file actions
196 lines (170 loc) · 10.1 KB
/
Copy path.env.example
File metadata and controls
196 lines (170 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# =============================================================================
# CI-Hub Environment Configuration (template)
# =============================================================================
# Copy this file to the env file for your target, then fill in the REQUIRED
# values. Everything else has a sensible default and is only needed to override.
#
# cp .env.example .env.dev # source dev stack (pnpm run dev)
# cp .env.example .env.local # source local stack (pnpm run local)
# cp .env.example .env.prod # self-hosted production (pnpm start prod)
#
# Scope: this template is ONLY for the compose-based (source / self-hosted)
# stacks. The desktop app and the `cihub` CLI generate their own env file
# automatically and never read this one.
#
# Hub image: the compose stack here BUILDS the Hub from source (Dockerfile).
# Pulling a prebuilt image (registry vs. locally built) is handled by the
# desktop/CLI appliance via CI_HUB_IMAGE — not by this template.
# =============================================================================
# ---------------------------------------------------------------------------
# REQUIRED — you must set these
# ---------------------------------------------------------------------------
# Compose env file path. Must match the file you copied this to, and must be a
# real file (never let Docker auto-create a .env/ directory).
ENV_FILE=.env.dev
# Absolute host path for Docker volume mounts (state, repos, apps, logs, etc.)
ROOT_FOLDER_HOST=/path/to/your/data
# Database password (used by both the Postgres container and the backend)
POSTGRES_PASSWORD=<strong-password>
# Secret for signing JWT auth tokens
JWT_SECRET=<random-secret>
# Host LAN IP for local network access (0.0.0.0 binds all interfaces)
INTERNAL_IP=0.0.0.0
# Public domain — used for Traefik routing and tunnel config
DOMAIN=companionintelligence.com
# Companion Portal / cloud URL (device registration, app store, sync):
# production : https://hub.ci.computer
# dev cloud : https://hub.companionintelligence.com
CI_CLOUD_URL=https://hub.ci.computer
# ---------------------------------------------------------------------------
# OPTIONAL — sensible defaults, override only if needed
# ---------------------------------------------------------------------------
# NODE_ENV=production # production | development | staging
# LOG_LEVEL=info # debug | info | warn | error
# LOCAL=false # true to skip HTTPS requirements
# EXPERIMENTAL_INSECURE_COOKIE=false # true for HTTP-only dev setups
# DEVICE_ID= # set during device registration
# Hub version string. Injected automatically by docker-compose (which pins a
# default), by the desktop app, and by the CLI. Only set this if you run the
# backend directly WITHOUT compose (the env validator requires a value).
# CI_HUB_VERSION=0.2.27
# Local LAN domain for Traefik routing (apps reachable as e.g. jitsi.<LOCAL_DOMAIN>).
# Defaults to DOMAIN when unset.
# LOCAL_DOMAIN=
# Extra browser origins allowed to make CREDENTIALED requests to the API,
# comma-separated and matched exactly. The Hub already allows the Tauri webview,
# DOMAIN/LOCAL_DOMAIN, and the loopback port it is served from — set this only
# when you genuinely browse the Hub on another origin, e.g. after publishing it
# on a different host port than the container's API_PORT. It is not a wildcard:
# every installed app that publishes a host port serves a page on some
# http://localhost:<port>, and none of them belong here.
# CI_HUB_EXTRA_CORS_ORIGINS=http://localhost:8123,https://hub.example.test
# Server-side Portal URL when CI_CLOUD_URL is a browser-facing loopback
# (e.g. https://ci-portal.localhost). Used by the backend inside Docker to reach
# a Portal dev stack on the host. Defaults to host.docker.internal with TLS SNI.
# CI_PORTAL_INTERNAL_URL=http://host.docker.internal:8415
# --- Companion Memory app-connect (forward-auth secret) ---
# Shared HMAC secret the Hub uses to sign its server-to-server calls to the
# Companion Memory (CI-Server) app during the connect flow, and to sign the
# forward-auth identity header. Auto-generated from the Hub's own entropy on
# first boot (NEVER derived from JWT_SECRET) and injected into the ci-memory
# container automatically — so you normally never set this. Override only to
# pin a fixed value across a rebuild (must be a random string, not JWT_SECRET).
# CI_HUB_FORWARD_AUTH_SECRET=
# --- Reverse-proxy trust ---
# By default the Hub RESOLVES which hops may vouch for a client's address: the
# two edge hops below (cloudflared and the Tailscale sidecar, by their fixed
# addresses, never the whole edge subnet) and Traefik's own address, read from
# Docker every minute and whenever Traefik starts or stops. The same list
# reaches each app as HUB_TRUSTED_PROXY_CIDRS, and a running app that reads it
# is restarted when Traefik's address moves. Nothing on the LAN, in an app
# container or at a bridge gateway is ever trusted, so a forged X-Forwarded-For
# from there is ignored. Leave HUB_TRUST_PROXY unset unless you run your OWN proxy in front
# of Traefik: then give Express a trusted hop count (e.g. 1) or subnet/IP list
# (e.g. 172.16.0.0/12). Too broad a value lets a spoofed header appear
# internal. PROCESS-WIDE: it also affects req.ip/req.protocol in audit logs
# and SSO. An invalid value (e.g. "true") makes the Hub fail to start.
# HUB_TRUST_PROXY=
# The edge network's subnet, the range Docker may allocate from on it (only the
# network address and the gateway, so nothing joins without a fixed address),
# and the three fixed addresses. Change all five together, only if
# 10.128.0.0/29 collides with something you route to, then run
# `up -d --force-recreate traefik cloudflared hub-tailscale`: compose recreates
# the network but reconnects its members without their fixed addresses.
# HUB_EDGE_SUBNET=10.128.0.0/29
# HUB_EDGE_IP_RANGE=10.128.0.0/31
# HUB_EDGE_TRAEFIK_IP=10.128.0.2
# HUB_EDGE_CLOUDFLARED_IP=10.128.0.3
# HUB_EDGE_TAILSCALE_IP=10.128.0.4
# `tailscale serve` upstream for the sidecar; must be Traefik's edge address.
# TAILSCALE_SERVE_UPSTREAM=10.128.0.2:80
# --- Telemetry kill switches ---
# Error reporting is ON by default in distributed builds: a DSN is baked into the
# image at build time, so these are how an operator turns it off. Highest
# precedence first; each is checked at the point of sending, not just in the UI.
#
# CI_LOCAL_ONLY=true nothing leaves this machine, for any reason
# CI_TELEMETRY=off no error reporting; other local features unaffected
#
# The in-product switch is Settings -> General -> "Allow anonymous error
# monitoring" (stored as `allowErrorMonitoring` in state/settings.json). The env
# vars above override it, so a UI toggle cannot re-enable what the box owner
# turned off.
#
# What is collected when it is on: exceptions and stack traces, the device id,
# the Portal URL, the Hub image tag, and — on app failures — the failing app's
# URN and container logs. Not collected: cookies, request bodies, identity
# headers, the server hostname, or the client IP.
# CI_LOCAL_ONLY=
# CI_TELEMETRY=
# --- Sentry (optional error/crash reporting) ---
# SENTRY_ENV=production
# SENTRY_DSN=https://<backend-public-key>@o<org-id>.ingest.us.sentry.io/<backend-project-id>
# SENTRY_DESKTOP_DSN=https://<desktop-public-key>@o<org-id>.ingest.us.sentry.io/<desktop-project-id>
# VITE_SENTRY_DSN=https://<frontend-public-key>@o<org-id>.ingest.us.sentry.io/<frontend-project-id>
# Sampling is intentionally configurable: use 1.0 temporarily while verifying
# an installation, then lower production session/tracing volume as appropriate.
# VITE_SENTRY_TRACES_SAMPLE_RATE=0.1
# VITE_SENTRY_REPLAYS_SESSION_SAMPLE_RATE=0.1
# VITE_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE=1.0
# VITE_SENTRY_ENABLE_METRICS=true
# VITE_SENTRY_ENABLE_LOGS=true
# SENTRY_TRACES_SAMPLE_RATE=0.1
# SENTRY_PROFILES_SAMPLE_RATE=0.1
# SENTRY_ENABLE_METRICS=true
# SENTRY_ENABLE_LOGS=true
# --- Host Docker access (set automatically by init:host) ---
# Host docker group GID, needed for socket access when the Hub runs as non-root.
# DOCKER_GID=973
# --- GitHub Packages (required only when building the Hub image from source) ---
# pnpm install fetches @companionintelligence/tokens from npm.pkg.github.com.
# Needs a token with the read:packages scope; `gh auth token` works once you run
# `gh auth refresh -s read:packages`. Not needed when pulling a prebuilt image.
# NODE_AUTH_TOKEN=
# --- Build / platform (rarely needed; set automatically by Tauri/CLI) ---
# CI_HUB_CONTAINER_UID= # Hub container runs as this host user (defaults 1000:1000)
# CI_HUB_CONTAINER_GID=
# DOCKER_PLATFORM=linux/amd64 # e.g. linux/arm64 for Apple Silicon
# TARGETARCH=amd64
# HTTP_PORT=80
# HTTPS_PORT=443
# --- Tailscale sidecar (hub-tailscale): on by default via COMPOSE_PROFILES=private-vpn ---
# Opt out: PRIVATE_VPN_USER_DISABLED=true (then restart the stack).
# Pre-auth key from https://login.tailscale.com/admin/settings/keys
# TAILSCALE_AUTHKEY=tskey-auth-...
# Override `tailscale up` args (default advertises 172.18.0.0/16 for the Docker bridge):
# HUB_TAILSCALE_EXTRA_ARGS=--accept-routes --advertise-routes=172.18.0.0/16
# Legacy name still supported: HEADSCALE_PREAUTH_KEY (same as TAILSCALE_AUTHKEY).
# --- Hub Pool (multi-Hub inference pooling over the tailnet) ---
# All three are operator-of-the-box overrides that the in-product toggles cannot undo, and none is
# ever written back into this file by the Hub. Unset = pooling behaves normally. See docs/hub-pool.md.
# HUB_POOL_USER_DISABLED=true # leave the pool entirely; peers mark this node unreachable
# HUB_POOL_OUTBOUND_DISABLED=true # stop SENDING work to peers (they may still send work here)
# HUB_POOL_INBOUND_DISABLED=true # stop SERVING peers' work (this node keeps using them)
# --- Let's Encrypt / ACME ---
# Registration email written into traefik.yml at startup. If unset, a generic
# placeholder is used (cert issuance still works; expiry notices go here if set).
# ACME_EMAIL=you@example.com
# --- Everything else (DB host, RabbitMQ, container names, ports) ---
# is hardcoded in constants.ts / docker-compose.prod.yml and can still be
# overridden via env vars for backward compatibility.