-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.env.example
More file actions
274 lines (259 loc) · 16.4 KB
/
Copy path.env.example
File metadata and controls
274 lines (259 loc) · 16.4 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
# ─────────────────────────────────────────────────────────────────────────────
# Where this file goes: the workspace root, as `.env` — beside this one.
# ─────────────────────────────────────────────────────────────────────────────
# cp .env.example .env
#
# One file, read by all three programs: the web app, the operator CLI
# (`pnpm community …`) and the worker. It used to have to live in `apps/community/`
# because that is where Next looks, which left the CLI reading nothing — so
# `pnpm community migrate` would report success having migrated fixture mode.
#
# `.env.local` is read first if present and wins where the two overlap; a real
# environment variable beats both, so CI, Docker and the e2e suite are never
# affected by whatever is in a checkout. Nothing here is loaded by the test
# suite.
#
# ─────────────────────────────────────────────────────────────────────────────
# Data source
# ─────────────────────────────────────────────────────────────────────────────
# fixture = deterministic in-memory repositories (no database required).
# This is the default when DATABASE_URL is unset, and is what the test
# suite and local development use.
# postgres = Drizzle + postgres.js against DATABASE_URL.
DATA_SOURCE=fixture
# For local development against a real database, `docker/compose.dev.yml` starts
# one on port 55432 with a **named** volume, so the board survives the container
# being recreated:
#
# docker compose -f docker/compose.dev.yml up -d
# pnpm community migrate
#
# DATA_SOURCE=postgres
# DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:55432/community_test
#
# ─────────────────────────────────────────────────────────────────────────────
# !! READ THIS BEFORE SETTING DATABASE_URL !!
# ─────────────────────────────────────────────────────────────────────────────
# Your own Postgres, with a fixed number of processes in front of it, needs
# nothing special. That is what docker/compose.yml gives you and what
# docs/self-hosting.md walks through.
#
# Pointing at a MANAGED database instead? Use the TRANSACTION-MODE POOLER
# connection string, not the direct one. Those providers scale processes up
# behind your back; a direct connection means one Postgres backend per
# concurrent request, a traffic spike exhausts max_connections, and the whole
# board goes down with "too many clients already". The pooler multiplexes them.
#
# Because transaction-mode pooling does not support prepared statements, the
# client is configured with `prepare: false` and a small pool (3 by default,
# DATABASE_POOL_MAX below to change it, capped at 20). Do not "optimise" those
# values — see packages/db/src/client.ts for the reasoning.
#
# Neon: ...-pooler.REGION.aws.neon.tech/db (note the -pooler host)
# Supabase: ...pooler.supabase.com:6543/postgres (port 6543, NOT 5432)
#
# DATABASE_URL=postgresql://user:password@host-pooler.example.com:6543/forum?sslmode=require
# Connections per process. The default of 3 is deliberate — see the pooling
# note above before raising it.
# DATABASE_POOL_MAX=3
# Migrations take a session-level advisory lock, which transaction-mode poolers
# cannot hold. On a managed database, point this at the DIRECT (non-pooler)
# connection string; the migration runner prefers it over DATABASE_URL.
# DIRECT_DATABASE_URL=
# ─────────────────────────────────────────────────────────────────────────────
# Secrets — generate with: openssl rand -base64 48
# ─────────────────────────────────────────────────────────────────────────────
# Signs the unsubscribe links in outgoing mail. Sessions do NOT depend on it —
# they are random tokens stored hashed in the database — so rotating it signs
# nobody out; what it breaks is the unsubscribe link in every message already
# sent.
AUTH_SECRET=
# Shared secret for /api/system/tick, which answers GET and POST alike. The
# cron caller presents it as "Authorization: Bearer <TICK_SECRET>", or as an
# "X-Tick-Secret" header. It is not read from the query string.
TICK_SECRET=
# Only read by docker/compose.yml, which interpolates it into the database's
# own password. Hex rather than base64, deliberately: `/` or `+` in a password
# breaks the postgres:// URL it is spliced into.
# Generate with: openssl rand -hex 32
# POSTGRES_PASSWORD=
# Only read by the compose files: each long-running container's memory and CPU
# ceiling. The defaults suit a small VPS; a larger machine raises them here, so
# the compose file itself is never edited and an upgrade's `git checkout` has
# nothing of yours to collide with — see docs/self-hosting.md § Start it.
# WEB_MEM_LIMIT=1g
# WEB_CPUS=2
# POSTGRES_MEM_LIMIT=1g
# POSTGRES_CPUS=1
# WORKER_MEM_LIMIT=768m
# WORKER_CPUS=1
# REDIS_MEM_LIMIT=256m
# REDIS_CPUS=0.5
# The board's absolute public origin, used for e-mail links, feeds and canonical
# URLs. Optional, like MAIL_DRIVER and for the same reason: the installer asks
# for it — prefilled from the address you load /install at — and stores it as
# `board.url`, which /admin/settings?group=board can change without a redeploy.
#
# Set here, this wins outright — the settings screen warns that the stored
# field is not read until the variable is unset. Worth doing when the
# deployment is configured entirely from files. A board with neither still
# runs; what breaks is every link it sends, silently.
APP_URL=http://localhost:3000
# ─────────────────────────────────────────────────────────────────────────────
# Drivers — swap infrastructure without touching application code (F05)
# ─────────────────────────────────────────────────────────────────────────────
# postgres | memory. Postgres is the only production queue — it is already safe
# under any number of workers, so there is nothing a second queue technology
# would add. `memory` is for development and refuses to boot in production.
QUEUE_DRIVER=postgres # postgres | memory
# next | memory | redis. `next` and `memory` both store per process and differ
# only in name — right for the stock one-web-container board, where the process
# making a change is the process serving it. `redis` moves the cache into one
# shared store (REDIS_URL below becomes required), which is what lets several
# web containers serve fresh settings, word filters, group colours and theme
# overrides the moment any one of them makes a change — docs/scaling.md is the
# walkthrough.
CACHE_DRIVER=next
# local | s3. Avatars, attachments and the board logo share this store.
# `local` is right for development and for the Docker image, which mounts a
# volume at UPLOADS_DIR. It needs a disk that survives a restart: on a host
# whose filesystem is per-instance and ephemeral, an upload succeeds and then
# disappears for everyone but the instance that took it — which is a loss, not
# an error. `s3` is optional at any size and points at any S3-compatible bucket.
FILESTORE_DRIVER=local # local | s3
# Mail is the one driver here that does NOT have to be set. Leave MAIL_DRIVER
# unset (or `log`) and the board is configured from /admin/settings?group=mail
# — a screen with a "send a test message" button and no redeploy. The installer
# offers the same thing on first run, and refuses to install if the test fails.
#
# Set it here and the environment wins outright: the settings screen still
# accepts edits but warns that they are stored, not used, until the variable is
# unset. Worth doing when the credential must not live in the database, or when
# the deployment is configured entirely from files.
MAIL_DRIVER=log # log | http | smtp
# Required when CACHE_DRIVER=redis; a redis:// or rediss:// URL to a Valkey or
# Redis server. The store holds cache entries and nothing else — losing it
# costs a warm cache, not data. The board only speaks the protocol; Valkey
# (the open-source, BSD-licensed fork) is what the compose profile ships, and
# Redis proper works here unchanged.
# REDIS_URL=redis://localhost:6379
# All four required when FILESTORE_DRIVER=s3; boot fails naming any that are
# missing. S3_ENDPOINT is for anything S3-compatible — R2, MinIO, Spaces — and
# switches the client to path-style addressing.
# S3_BUCKET=
# S3_REGION=
# S3_ACCESS_KEY_ID=
# S3_SECRET_ACCESS_KEY=
# S3_ENDPOINT=
# `log` (the default above) writes each message to the server log and SENDS
# NOTHING. On a board that has also stored no mail settings, password reset and
# registration confirmation both silently go nowhere.
#
# MAIL_DRIVER=http posts a provider's JSON API. Resend's body matches the
# driver's as-is; Postmark and Mailgun use different field names, so use their
# SMTP hosts instead. All three are required together; boot fails naming
# whichever is missing:
#
# MAIL_DRIVER=http
# MAIL_HTTP_ENDPOINT=https://api.resend.com/emails
# MAIL_HTTP_TOKEN=re_…
# MAIL_FROM=noreply@yourdomain.com
#
# MAIL_DRIVER=smtp reaches every provider, and is the only option that needs no
# new DNS records if you already receive mail on this domain — SPF and DKIM are
# published for it already. MAIL_SMTP_HOST and MAIL_FROM are required; the
# username and password must be set together or not at all (a relay on this
# machine needs neither):
#
# MAIL_DRIVER=smtp
# MAIL_SMTP_HOST=smtp.fastmail.com
# MAIL_SMTP_PORT=465
# MAIL_SMTP_SECURITY=tls # tls (465) | starttls (587) | none
# MAIL_SMTP_USERNAME=
# MAIL_SMTP_PASSWORD= # an app password, not your login password
# MAIL_FROM=noreply@yourdomain.com
#
# `security` is three values rather than a boolean because `secure=false` does
# not mean unencrypted — it means STARTTLS. Picking a mode that disagrees with
# the port gives a connection that hangs instead of failing.
#
# Whichever transport: verify the sending domain with the provider first, and
# keep MAIL_FROM on that domain. Otherwise every message is rejected, which the
# driver treats as a configuration error and does not retry.
# See docs/operating.md § Mail.
# MAIL_FROM=noreply@example.com
# MAIL_HTTP_ENDPOINT=
# MAIL_HTTP_TOKEN=
# MAIL_SMTP_HOST=
# MAIL_SMTP_PORT=587
# MAIL_SMTP_SECURITY=starttls
# MAIL_SMTP_USERNAME=
# MAIL_SMTP_PASSWORD=
# ─────────────────────────────────────────────────────────────────────────────
# Background work (F06)
# ─────────────────────────────────────────────────────────────────────────────
# The worker runs this loop in-process every minute. Each task carries its own
# wall-clock budget in its definition, and the worker bounds the tick as a whole
# — neither is configurable here, and the two variables that claimed to do it
# were read by nothing.
# ─────────────────────────────────────────────────────────────────────────────
# Paths and access — rarely needed outside the Docker image
# ─────────────────────────────────────────────────────────────────────────────
# Where FILESTORE_DRIVER=local writes. The Docker image sets /app/.uploads and
# mounts a volume there; outside a container the default is ./.uploads.
# UPLOADS_DIR=
# Where the migration runner looks for the SQL, when it cannot find the
# packages/db/migrations folder by itself (the standalone image sets it).
# MIGRATIONS_DIR=
# Restrict /admin to these comma-separated IPs or CIDR prefixes. Anyone else
# gets a 404, before the password is even asked for. Unset means no address
# check.
# ADMIN_IP_ALLOWLIST=
# How many proxies sit between the internet and the board. The default, 1, is
# the shape docs/self-hosting.md describes: one reverse proxy terminating TLS.
# Add one for a CDN in front of it. 0 means nothing is in front and the
# X-Forwarded-For header is ignored outright.
#
# This is a security setting. The board reads this many entries back from the
# right-hand end of the forwarding chain and discards everything to the left,
# because a caller can prepend whatever they like. Set it too high and they can
# forge the address the allowlist, the login lockout and the audit log all
# key off. See docs/operating.md#visitor-addresses-and-proxies.
# TRUSTED_PROXY_HOPS=1
# Whether a post may embed an image hosted somewhere else. 0, the default,
# narrows the content policy to this board's own images and data: URLs, so a
# reader's browser never contacts a host you do not run — a remote image in a
# post is what tells that host who is reading the thread, and when. 1 allows
# them. docs/operating.md#remote-images.
# REMOTE_IMAGES=0
# ─────────────────────────────────────────────────────────────────────────────
# Demo mode — a public board that resets itself
# ─────────────────────────────────────────────────────────────────────────────
# Not a lighter board. It is this board with published credentials, seeded
# content, and every outbound surface disarmed, because on a demo everybody who
# visits is an administrator: mail is pinned to nowhere regardless of what the
# settings screen says, webhook delivery is never scheduled, login lockout is
# lifted so one visitor's typo cannot lock the account for the next, and the
# seeded accounts cannot have their password or email changed.
#
# Requires DATA_SOURCE=postgres. Do not set it on a board with real members:
# the reset below deletes everything they wrote. See docs/demo-mode.md.
# DEMO_MODE=0
# How often the board wipes itself back to the seed, in minutes (5–1440).
# DEMO_RESET_MINUTES=60
#
# Demo mode also installs the Dues plugin and seeds a shop with a year of
# history behind it. For a visitor to be able to buy, point the plugin at the
# fake Stripe the board serves itself at /demo/stripe — a checkout page that
# says so, asks for no card, and signs the webhook the way Stripe would. The
# route exists only under DEMO_MODE. Never point a real board at it.
# DUES_STRIPE_SECRET_KEY=sk_test_demo_no_such_account
# DUES_STRIPE_WEBHOOK_SECRET=<generated, any long random string>
# DUES_STRIPE_API_BASE=http://127.0.0.1:3000/demo/stripe
# Register every theme this repository ships — Midnight, Phasebook, Raidframe
# and Clubhouse alongside the default — rather than the default alone. This is what the public demo
# runs, so that it can be a shop window without deciding anything for a board
# you deploy yourself: yours starts with the default theme and adds what it
# wants in community.config.ts, a file you own and this flag never touches.
# SHOWCASE_THEMES=0
LOG_LEVEL=info