-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy path.env.example
More file actions
223 lines (188 loc) · 9.49 KB
/
.env.example
File metadata and controls
223 lines (188 loc) · 9.49 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
# ============================================================================
# ePDS — Shared Environment Variables
# ============================================================================
#
# This file contains variables shared across multiple services, plus
# service-specific vars for convenience when running with docker-compose
# (which loads this single file for both core and auth).
#
# For the authoritative list of what each service reads, see:
# packages/pds-core/.env.example
# packages/auth-service/.env.example
# packages/demo/.env.example
#
# How env vars work in each context:
#
# docker-compose: Loads this file via env_file for core, auth, and caddy.
# Each container gets ALL vars; services ignore what they
# don't read.
#
# Railway: This file is NOT used. Set vars per-service in the
# Railway dashboard. Use shared variable groups for vars
# that must match across services (marked [shared] in the
# per-package .env.example files).
#
# pnpm dev: pds-core calls dotenv.config() which loads this file.
# Auth-service inherits the same process environment.
#
# Run ./scripts/setup.sh to create .env files (this + per-package) and
# auto-generate all secrets. Works for all deployment targets:
# docker-compose: core/auth/caddy use this file; demo uses packages/demo/.env.
# pnpm dev: uses this file directly.
# Railway: generates per-package .env files to paste into the dashboard.
# ============================================================================
# Shared — MUST match in pds-core and auth-service
# ============================================================================
# ePDS version reported by /health endpoints and the demo footer.
# Automatically derived at Docker build time from package.json + commit SHA
# (e.g. 0.2.2+f37823ee). In dev, falls back to the package.json version.
# Only set this manually if you have a specific reason, such as obfuscating
# the running version for security.
# EPDS_VERSION=
# Your PDS domain (handles will be <random>.PDS_HOSTNAME)
PDS_HOSTNAME=pds.example
# Public URL of the PDS (used as OAuth issuer)
PDS_PUBLIC_URL=https://pds.example
# HMAC secret for signing /oauth/epds-callback redirects.
# Generate with: openssl rand -hex 32
EPDS_CALLBACK_SECRET=
# Internal URL for auth-service → pds-core calls.
# Docker: http://core:3000 (Docker Compose service name)
# Railway: http://pds-core.railway.internal:3000 (or your service name)
# pnpm dev: not needed (defaults to PDS_PUBLIC_URL on localhost)
PDS_INTERNAL_URL=http://core:3000
# Secret for internal service-to-service calls (auth → pds).
# Generate with: openssl rand -hex 32
EPDS_INTERNAL_SECRET=
# PDS admin password (also used by auth-service for account provisioning).
# Generate with: openssl rand -hex 32
PDS_ADMIN_PASSWORD=
# Set to 'development' for dev mode (disables secure cookies, etc.)
# NODE_ENV=development
# ============================================================================
# pds-core only — see packages/pds-core/.env.example for full docs
# ============================================================================
PDS_PORT=3000
PDS_DATA_DIRECTORY=/data
PDS_DID_PLC_URL=https://plc.directory
PDS_BSKY_APP_VIEW_URL=https://api.bsky.app
PDS_BSKY_APP_VIEW_DID=did:web:api.bsky.app
PDS_CRAWLERS=https://bsky.network
PDS_JWT_SECRET=
PDS_DPOP_SECRET=
# Generate with:
# openssl ecparam -name secp256k1 -genkey -noout | openssl ec -text -noout 2>/dev/null | grep priv -A 3 | tail -n +2 | tr -d '[:space:]:'
PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=
# Comma-separated OAuth client_id URLs trusted for CSS branding injection.
# Set identically for both pds-core and auth-service.
# PDS_OAUTH_TRUSTED_CLIENTS=
# Legal links surfaced under the auth-service login form. Both URLs must
# be set for the line to render; if either is missing the line is
# omitted entirely. PDS_LEGAL_ENTITY_NAME (optional) supplies a
# possessive: "By signing in, you agree to <name>'s Terms of Use and
# Privacy Policy." When unset, copy falls back to a generic "the Terms
# of Use and Privacy Policy". The two URL vars match upstream PDS
# (consumed by pds-core too).
# PDS_TERMS_OF_SERVICE_URL=https://example.com/terms
# PDS_PRIVACY_POLICY_URL=https://example.com/privacy
# PDS_LEGAL_ENTITY_NAME=Acme
PDS_EMAIL_SMTP_URL=smtp://localhost:1025
PDS_EMAIL_FROM_ADDRESS=noreply@pds.example
PDS_BLOBSTORE_DISK_LOCATION=/data/blobs
# Trusted OAuth clients — comma-separated client_id URLs.
# PDS_OAUTH_TRUSTED_CLIENTS=https://app.example/client-metadata.json
# Skip consent on sign-up for trusted clients that request it.
# Requires PDS_OAUTH_TRUSTED_CLIENTS and client metadata with
# "epds_skip_consent_on_signup": true. Default: false.
# PDS_SIGNUP_ALLOW_CONSENT_SKIP=false
# Expose /preview and /preview/consent on pds-core, rendering the OAuth
# consent page with fixture hydration data so client-app developers can
# iterate on their branding.css without walking through a real OAuth
# flow. ?client_id=... injects that client's branding.css (subject to
# PDS_OAUTH_TRUSTED_CLIENTS, same as a real flow). Intended for preview
# envs and dev instances — leave off in production. The matching
# auth-service flag is AUTH_PREVIEW_ROUTES (see auth-service section
# below); both flags are independent.
#
# Privacy: enabling this also exposes /preview/cache-status, which
# returns the list of client_id URLs currently in the shared
# client-metadata cache — i.e. apps that have recently started an
# OAuth flow against this PDS. That partially leaks which
# third-party clients are using the instance, so keep this off in
# production unless you're OK with that disclosure.
# PDS_PREVIEW_ROUTES=1
# Invite code for automated account creation (ePDS creates accounts on first login).
# Required when PDS_INVITE_REQUIRED is true (the default).
# Generate with:
# curl -u admin:$PDS_ADMIN_PASSWORD -H 'Content-Type: application/json' \
# -d '{"useCount":10000}' https://$PDS_HOSTNAME/xrpc/com.atproto.server.createInviteCode
# Note: PDS must be running before you can generate this. Run setup.sh first,
# start the PDS, generate the code, then add it here.
EPDS_INVITE_CODE=
# ============================================================================
# auth-service only — see packages/auth-service/.env.example for full docs
# ============================================================================
AUTH_HOSTNAME=auth.pds.example
AUTH_PORT=3001
# Generate with: openssl rand -hex 32
AUTH_SESSION_SECRET=
AUTH_CSRF_SECRET=
EPDS_LINK_EXPIRY_MINUTES=10
EPDS_LINK_BASE_URL=https://auth.pds.example/auth/verify
SESSION_EXPIRES_IN=604800
SESSION_UPDATE_AGE=86400
# OTP code length — number of characters in the email verification code (default: 8)
# Must be between 4 and 12 characters. Applies to login, recovery, and account settings OTP flows.
# OTP_LENGTH=8
# OTP character set — 'numeric' for digits only (0-9), 'alphanumeric' for uppercase letters + digits (A-Z, 0-9)
# Default: numeric. Alphanumeric codes have higher entropy but require text input instead of numeric keyboard.
# OTP_CHARSET=numeric
# Default handle assignment mode for new user signups.
# Controls what happens when neither the OAuth request param nor the client
# metadata specifies epds_handle_mode.
# Values: random | picker | picker-with-random
# Defaults to 'picker-with-random' if not set.
EPDS_DEFAULT_HANDLE_MODE=picker-with-random
# Expose /preview/* routes on auth-service that render each page
# (login / OTP / choose-handle / recovery) with fixture data, so
# client-app developers can iterate on their branding.css without
# walking through a real OAuth flow each time. The trusted-clients
# gate on CSS injection is preserved: ?client_id=... only gets its
# branding.css injected when on PDS_OAUTH_TRUSTED_CLIENTS. Intended
# for preview envs and dev instances — leave off in production.
# The matching pds-core flag (PDS_PREVIEW_ROUTES, see pds-core section
# above) covers the consent page. Both flags are independent.
#
# Privacy: enabling this also exposes /preview/cache-status, which
# returns the list of client_id URLs currently in this service's
# client-metadata cache — i.e. apps that have recently started an
# OAuth flow against this PDS. That partially leaks which
# third-party clients are using the instance, so keep this off in
# production unless you're OK with that disclosure.
# AUTH_PREVIEW_ROUTES=1
# GOOGLE_CLIENT_ID=
# GOOGLE_CLIENT_SECRET=
# GITHUB_CLIENT_ID=
# GITHUB_CLIENT_SECRET=
EMAIL_PROVIDER=smtp
SMTP_HOST=localhost
SMTP_PORT=1025
SMTP_USER=
SMTP_PASS=
SMTP_FROM=noreply@pds.example
SMTP_FROM_NAME=ePDS
DB_LOCATION=/data/epds.sqlite
# ============================================================================
# Docker/Caddy only
# ============================================================================
# Override reverse proxy upstreams (for non-Docker or custom setups)
# PDS_UPSTREAM=core:3000
# AUTH_UPSTREAM=auth:3001
# ES256 (P-256) private JWK for the demo-untrusted docker service. Distinct
# from packages/demo/.env's EPDS_CLIENT_PRIVATE_JWK so the two demo
# containers cannot impersonate each other at the token endpoint. Without
# this set, the untrusted demo runs in public-client mode and upstream
# @atproto/oauth-provider forces prompt=consent on every authorize request,
# breaking the cross-client session-reuse e2e scenarios. Generate with:
# node scripts/generate-es256-jwk.cjs
# DEMO_UNTRUSTED_PRIVATE_JWK={"kty":"EC","crv":"P-256","d":"...","x":"...","y":"...","kid":"..."}