-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy path.env.example
More file actions
275 lines (241 loc) · 14.6 KB
/
Copy path.env.example
File metadata and controls
275 lines (241 loc) · 14.6 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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# Environment configuration for HyCanvas (Go backend + Next.js frontend).
# Every value below is read by the Go service (cmd/api) unless noted as
# frontend/compose-only. Copy to .env and edit.
# Database (PostgreSQL). Used as-is for non-docker dev AND by the published-image
# docker-compose.yml, which ships NO bundled Postgres and connects to this URL (or
# EXTERNAL_DATABASE_URL) directly. For that compose, set a reachable host: inside a
# container localhost is the container itself, so use host.docker.internal for a DB
# on your machine, or a managed endpoint.
DATABASE_URL="postgresql://postgres:password@localhost:5432/hycanvas?schema=public"
# Credentials for the BUNDLED Postgres container in docker-compose.prod.yml (build
# from source) and docker-compose.dev.yml (local dev); those files assemble the
# in-network db URL from these. The published-image docker-compose.yml has no db
# service and ignores them.
POSTGRES_USER="postgres"
POSTGRES_PASSWORD="password"
POSTGRES_DB="hycanvas"
# --- Docker compose: bundled vs external database ---
# The published-image docker-compose.yml is EXTERNAL-only: point DATABASE_URL
# (above) or EXTERNAL_DATABASE_URL at your managed Postgres; it ships no db
# container. Only the build-from-source docker-compose.prod.yml runs a BUNDLED
# Postgres, gated by this profile ("bundled" starts it; "" uses external). (Redis
# is not required: the Go backend runs background work inline.)
COMPOSE_PROFILES="bundled"
# EXTERNAL managed Postgres (required by the published-image compose; an optional
# override for the others):
# EXTERNAL_DATABASE_URL="postgresql://user:pass@your-db-host:5432/hycanvas?schema=public"
# Host port docker compose publishes the app on (maps to the container's :8005).
# Required by docker-compose.yml (it has no default); set it, e.g. 8005.
APP_PORT=8005
# development | production. In production: session cookies are Secure, the dev
# mail outbox + permissive localhost CORS are disabled, and AI provider base URLs
# must be https.
NODE_ENV="development"
# Override whether session cookies carry the Secure flag (otherwise it follows
# NODE_ENV: on in production). A production self-host served over plain http
# (localhost / LAN / a VPS before TLS) MUST set this "false", or the browser drops
# the cookie and login silently fails. Set "true" only when served over https (or
# behind a TLS-terminating reverse proxy). The docker-compose files set it "false"
# for the http://localhost quick start.
# COOKIE_SECURE="false"
# Application port. The Go binary serves the API (/api/v1), the realtime WebSocket
# (/realtime), and (in a dist build) the exported frontend, all on this port.
# GO_API_PORT is accepted as a fallback alias.
PORT=8005
# Interface to listen on. Empty binds all interfaces; behind a reverse proxy on
# the same host, bind only the loopback so the app is reachable through the
# proxy alone (set APP_URL to the external domain the proxy serves).
# BIND_HOST="127.0.0.1"
# Apply pending SQL migrations on boot (default true). Set "false" to manage
# migrations out of band (npm run db:migrate runs them explicitly).
DB_AUTO_MIGRATE="true"
# Tolerate a database that is still starting up when the API boots (common right
# after a host reboot, when this process races Postgres). The initial connect is
# retried DB_CONNECT_ATTEMPTS times, waiting DB_CONNECT_RETRY_DELAY between tries,
# before giving up. Defaults (12 x 5s) cover a typical cold start; raise the
# attempts for a database that replays a large WAL after an unclean shutdown.
# DB_CONNECT_ATTEMPTS="12"
# DB_CONNECT_RETRY_DELAY="5s"
# Directory of the exported Next.js frontend for the binary to serve. The dist
# bundle sets this to ./public; in dev the frontend runs separately (next dev),
# so leave it blank to serve the API only.
# PUBLIC_DIR=""
# Frontend dev origin. Used for credentialed CORS in dev (the frontend on :3000
# calls the API on :8005 with cookies). In production the binary serves the
# frontend same-origin, so CORS is not applied.
FRONTEND_URL="http://localhost:3000"
# JWT signing secret for access/refresh sessions. REQUIRED: the API refuses to
# start without it. Use a strong, random value, e.g. `openssl rand -hex 32`.
JWT_SECRET=""
# Encryption key for secrets at rest: per-workspace AI provider keys and the MFA
# TOTP secret (AES-256-GCM). Falls back to JWT_SECRET when unset.
# AI_SECRET=""
# Public base URL of the web app, used to build the links in outbound email
# (verify email, password reset, magic link). In single-process dev the backend
# serves the app, so this points at the backend.
APP_URL="http://localhost:8005"
# NOTE: email delivery is not wired (no SMTP). Verify-email / password-reset /
# magic-link tokens are minted and the links are captured in an in-memory dev
# outbox, readable at GET /api/v1/auth/dev/outbox (non-production only).
# Social sign-in (generic OIDC). Optional: the "Continue with ..." button shows
# only when ISSUER + CLIENT_ID + CLIENT_SECRET are all set. Works with any OIDC
# provider (Google: https://accounts.google.com, plus Microsoft/Okta/Auth0/...).
# Register an OAuth app there and set the redirect/callback URL to
# {APP_URL}/api/v1/auth/oidc/callback (or override with OIDC_REDIRECT_URI).
# OIDC_ISSUER must be https (the client_secret is sent to its token endpoint);
# http is allowed only for a localhost dev IdP, otherwise SSO stays disabled.
OIDC_ISSUER=""
OIDC_CLIENT_ID=""
OIDC_CLIENT_SECRET=""
# Optional overrides:
# OIDC_REDIRECT_URI="http://localhost:8005/api/v1/auth/oidc/callback"
# OIDC_SCOPES="openid email profile"
# OIDC_LABEL="Google"
# OIDC_ALLOWED_EMAIL_DOMAINS: comma-separated domains the IdP is authoritative for.
# When set, SSO only auto-links/creates accounts for these domains, and only then
# will it link an SSO identity to an EXISTING password account (you vouch that the
# IdP owns the email). Leave unset to allow any verified email to create/sign in
# to SSO-native accounts, but never silently link to a password account.
# OIDC_ALLOWED_EMAIL_DOMAINS="yourcompany.com"
# Auth methods (optional). Each sign-in method has an independent login and
# signup toggle; the sign-in page shows only what is enabled. Values are "true"
# or "false"; anything else keeps the default. Defaults preserve prior behavior,
# so an existing install is unchanged if you set none of these.
# AUTH_PASSWORD_LOGIN_ENABLED default true email + password sign-in
# AUTH_PASSWORD_SIGNUP_ENABLED default true create an account with a password
# AUTH_MAGICLINK_LOGIN_ENABLED default true emailed sign-in link (existing account)
# AUTH_MAGICLINK_SIGNUP_ENABLED default false emailed link that creates a new account
# AUTH_OIDC_LOGIN_ENABLED default true SSO sign-in (needs OIDC_* above)
# AUTH_OIDC_SIGNUP_ENABLED default true SSO creates a new account on first login
# OIDC toggles do nothing unless OIDC is configured. If a config would leave no
# usable login method, the server keeps password login on and logs a warning, so
# you cannot lock yourself out.
# OIDC-only (no password, no magic-link; SSO creates and signs in):
# AUTH_PASSWORD_LOGIN_ENABLED="false"
# AUTH_PASSWORD_SIGNUP_ENABLED="false"
# AUTH_MAGICLINK_LOGIN_ENABLED="false"
# CAPTCHA on the auth forms (optional). Protects login, signup, password-reset
# request, and magic-link request from automated abuse. Off unless a provider is
# set. CAPTCHA_PROVIDER is "turnstile" (Cloudflare) or "recaptcha" (Google, v2 or
# v3). Get the site + secret keys from the provider's dashboard. Fail-closed: if
# the provider is unreachable, the gated forms reject, so a solved challenge is
# always required once enabled. A provider set without both keys is treated as
# disabled (logged), so a half-configuration never locks users out.
CAPTCHA_PROVIDER=""
CAPTCHA_SITE_KEY=""
CAPTCHA_SECRET_KEY=""
# reCAPTCHA v3 only: minimum score (0..1) to pass (default 0.5). Turnstile and
# reCAPTCHA v2 ignore it.
# CAPTCHA_MIN_SCORE="0.5"
# Google Analytics (optional). Set your GA4 measurement id and the server injects
# the gtag.js snippet into every served HTML page at runtime (no rebuild needed).
# Empty (the default) means no analytics, so a self-hosted instance is
# tracking-free unless you opt in.
GOOGLE_ANALYTICS_ID=""
# Web push notifications. Optional: web push is enabled only when
# BOTH keys are set; otherwise the channel is a no-op (in-app notifications still
# work). Generate a key pair with: npx web-push generate-vapid-keys
VAPID_PUBLIC_KEY=""
VAPID_PRIVATE_KEY=""
VAPID_SUBJECT="mailto:admin@localhost"
# Storage driver: "local" (default) or "s3". When left blank, S3 is used
# automatically if S3_ENDPOINT + the S3 credentials below are set, otherwise
# local. A misconfigured S3 fails loudly on boot (it never silently drops blobs).
# IMPORTANT: LOCAL_STORAGE_PATH resolves relative to the process working dir. The
# dist bundle runs from dist/, so a relative path there points at dist/.data and
# will NOT see data written by the dev server (cwd = repo root). Use an ABSOLUTE
# path so dev and the bundle share the same storage.
STORAGE_DRIVER="local"
LOCAL_STORAGE_PATH=".data/storage"
# Object storage (S3-compatible: AWS S3, MinIO, etc.). To use it, set
# STORAGE_DRIVER="s3" (or leave it blank) and fill these in. The bucket is
# created automatically if it does not exist. For MinIO (or any non-AWS
# endpoint) include the scheme in S3_ENDPOINT and set S3_FORCE_PATH_STYLE="true".
# S3_ENDPOINT="https://s3.amazonaws.com" # MinIO example: "http://minio:9000"
# S3_REGION="us-east-1"
# S3_BUCKET="hycanvas"
# S3_ACCESS_KEY_ID=""
# S3_SECRET_ACCESS_KEY=""
# S3_FORCE_PATH_STYLE="true"
# Direct uploads (OPTIONAL, S3/MinIO only). When enabled, browsers upload file
# bytes straight to the bucket via presigned POSTs, bypassing the API and its
# reverse proxy (no client_max_body_size to tune, no base64 overhead). Opt-in
# because the bucket needs a CORS rule first (see README "Uploads and object
# storage"). Off (the default), uploads stream through the API instead, which
# needs no storage-side setup.
# S3_DIRECT_UPLOADS="true"
# S3_PUBLIC_URL rewrites the presigned URL's origin when S3_ENDPOINT is not
# reachable from browsers (e.g. "http://minio:9000" inside docker-compose).
# Set it to the bucket endpoint as browsers see it.
# S3_PUBLIC_URL="https://s3.example.com"
# UPLOAD_SPOOL_DIR is where partially uploaded files accumulate while their
# chunks arrive (they are streamed into storage once whole, then removed).
# Defaults to a directory under the OS temp dir. Point it at a disk with room
# for the largest upload you allow, times the uploads you expect at once.
# UPLOAD_SPOOL_DIR="/var/lib/hycanvas/uploads"
# Realtime horizontal scaling (OPTIONAL). Unset/empty = a single gateway instance,
# in-memory relay (the default; correct for self-host and dev). Set REDIS_URL to
# run MULTIPLE gateway instances behind a load balancer: relay + awareness frames
# (Yjs sync, presence, join/leave) fan out across instances via Redis pub/sub, and
# the same Redis backs a cross-instance lock store so two instances never grant the
# same element and a crashed instance's locks auto-expire. A set-but-unreachable
# Redis fails loudly on boot (no silent split brain).
# NOTE: the Docker compose files force REDIS_URL empty on the app service, so a value
# set here is ignored under Docker; to enable it there, see DOCKER_SETUP.md.
# REDIS_URL="redis://localhost:6379/0"
# Uploads. BACKEND_PUBLIC_URL is the absolute base used to build asset
# content-delivery links (defaults to relative paths when unset).
# ASSET_QUOTA_BYTES caps per-workspace upload storage (bytes).
# USER_STORAGE_QUOTA_BYTES caps ONE USER's uploads globally, summed across all
# workspaces they upload into; unset or 0 = unlimited. Meant for public
# instances so a single account cannot fill the server by creating workspaces.
# Both caps apply independently.
# BACKEND_PUBLIC_URL="http://localhost:8005"
# ASSET_QUOTA_BYTES="5368709120"
# USER_STORAGE_QUOTA_BYTES="1073741824"
# FONTS_DIR points at a directory of font files the SERVER uses when it
# rasterizes a design for export (PNG, JPEG, PDF, video frames). This matters
# for non-Latin text: the font embedded in the binary covers Latin, Greek and
# Cyrillic only, so Hebrew, Arabic, Indic and CJK text exports BLANK unless a
# font covering those scripts is registered here. Files are .ttf or .otf named
# "Family-Weight.ttf" (weight optional, default 400), for example
# "NotoSansHebrew-400.ttf" or "NotoSansArabic-700.ttf". Every file is
# registered and used per glyph wherever the design's own font has no coverage.
# The server logs what it registered at startup, and warns once per character
# it still cannot draw.
# FONTS_DIR="/var/lib/hycanvas/fonts"
# LOCALES_DIR points at a directory of UI translation files, one per locale,
# named by its BCP 47 tag in lower case: fr.json, pt-br.json, ar.json. A file
# here OVERRIDES the copy built into the binary, so adding or correcting a
# language needs no rebuild. Keys come from the base catalog at
# frontend/src/locales/en.json; anything a file leaves out falls back to
# English, so a partial translation is useful immediately.
# Defaults to ./locales next to the binary when that directory exists, so
# usually there is nothing to set.
# LOCALES_DIR="/var/lib/hycanvas/locales"
# Transactional email (OPTIONAL). When SMTP_HOST is set, account emails
# (verify-email, welcome, password reset, magic link, workspace invite, design
# share) are sent for real; unset = they fall back to the in-memory dev outbox (inspect at
# GET /api/v1/auth/dev/outbox in dev). Port 465 (or SMTP_TLS=implicit) uses
# implicit TLS; otherwise STARTTLS. SMTP_FROM defaults to SMTP_USERNAME.
# SMTP_HOST="smtp.example.com"
# SMTP_PORT="587"
# SMTP_USERNAME="apikey-or-user"
# SMTP_PASSWORD="..."
# SMTP_FROM="no-reply@yourdomain.com"
# SMTP_FROM_NAME="HyCanvas"
# Live photo search queries the Openverse API (open-licensed photos, anonymous
# tier, no key needed). Set to "off" for air-gapped self-hosts; the bundled
# catalog keeps working without it.
# STOCK_PHOTO_PROVIDER="off"
# Live icon search queries the Iconify API (api.iconify.design, keyless,
# 200k+ open-source icons returned as editable inline SVG). Set to "off" for
# air-gapped self-hosts; the bundled icon catalog keeps working without it.
# STOCK_ICON_PROVIDER="off"
# Video export requires the ffmpeg binary on PATH (e.g. `brew install
# ffmpeg`). All other rendering (PNG/JPG/SVG/PDF) is pure Go, no system deps.
# AI is bring-your-own: providers + API keys are configured per workspace
# and stored encrypted in the database (AI_SECRET), not via process env.
# Frontend -> backend API base (frontend-only). In a dist build the frontend
# bakes /api (same-origin); in dev it targets the backend port directly.
NEXT_PUBLIC_BACKEND_URL="http://localhost:8005/api"