Repository navigation
Expand file tree
/
Copy path.env.example
More file actions
260 lines (231 loc) · 8.82 KB
/
Copy path.env.example
File metadata and controls
260 lines (231 loc) · 8.82 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
# ==================================
# OpenTaberna API - Environment Configuration
# ==================================
#
# Copy this file to .env and customize for your environment
# Never commit .env files to version control!
# ----------------------------------
# Application
# ----------------------------------
APP_NAME=OpenTaberna API
APP_VERSION=0.1.0
ENVIRONMENT=development
DEBUG=false
SECRET_KEY=CHANGE_ME_IN_PRODUCTION
# ----------------------------------
# Server
# ----------------------------------
HOST=0.0.0.0
PORT=8000
WORKERS=1
RELOAD=false
# ----------------------------------
# Database
# ----------------------------------
# PostgreSQL connection URL
# Format: postgresql+asyncpg://user:password@host:port/database
DATABASE_URL=postgresql+asyncpg://opentaberna:opentaberna_password@opentaberna-db:5432/opentaberna
# Connection pool settings
DATABASE_POOL_SIZE=20
DATABASE_MAX_OVERFLOW=40
DATABASE_POOL_TIMEOUT=30
DATABASE_ECHO=false
# ----------------------------------
# Redis
# ----------------------------------
REDIS_URL=redis://localhost:6379/0
# REDIS_PASSWORD= # Load from Docker/K8s secret in production
# ----------------------------------
# CORS
# ----------------------------------
# Comma-separated list of allowed origins
# Use ["*"] for development, specific domains in production
CORS_ORIGINS=["*"]
CORS_CREDENTIALS=true
# ----------------------------------
# Logging
# ----------------------------------
LOG_LEVEL=INFO
LOG_FORMAT=console
# LOG_FILE=/var/log/opentaberna/app.log
# ----------------------------------
# Cache
# ----------------------------------
CACHE_ENABLED=true
CACHE_TTL=300
# ----------------------------------
# Rate Limiting
# ----------------------------------
RATE_LIMIT_ENABLED=true
RATE_LIMIT_PER_MINUTE=60
# ----------------------------------
# Feature Flags
# ----------------------------------
FEATURE_WEBHOOKS_ENABLED=false
# ==================================
# Notes:
# ==================================
#
# Sensitive values (passwords, secrets) should be loaded from:
# - Docker secrets: /run/secrets/<secret_name>
# - Kubernetes secrets: /var/run/secrets/<secret_name>
# - Environment variables (uppercase with underscores)
#
# Example production setup:
# - Store DATABASE_URL in /run/secrets/database_url
# - Store REDIS_PASSWORD in /run/secrets/redis_password
# - Store KEYCLOAK_CLIENT_SECRET in /run/secrets/keycloak_client_secret
#
# Generate secure SECRET_KEY:
# python -c "import secrets; print(secrets.token_urlsafe(32))"
# ----------------------------------
# Stripe (Payment Provider)
# ----------------------------------
# Get your keys from https://dashboard.stripe.com/test/apikeys
STRIPE_SECRET_KEY=sk_test_CHANGE_ME
STRIPE_PUBLISHABLE_KEY=pk_test_CHANGE_ME
# Accepted payment method types (JSON array)
STRIPE_PAYMENT_METHODS=["card"]
# Required for bank transfer payment methods — ISO 3166-1 alpha-2 country code
# STRIPE_BANK_TRANSFER_COUNTRY=DE
# Webhook signing secret. docker-compose.dev.yml generates and mounts this
# automatically via its Stripe CLI listener. Set it manually only when running
# FastAPI outside Compose or when using a Dashboard-managed endpoint.
# STRIPE_WEBHOOK_SECRET=whsec_CHANGE_ME
# ----------------------------------
# Email (Tracking Notifications)
# ----------------------------------
# Leave SMTP_HOST empty to skip sending entirely — useful in development,
# where the endpoint logs a warning instead of failing.
SMTP_HOST=
SMTP_PORT=587
SMTP_USER=
SMTP_PASSWORD=
EMAIL_FROM=noreply@opentaberna.local
# ----------------------------------
# Admin mailbox / future webmail (IMAP + SMTP)
# ----------------------------------
# Works with a hosted provider or a self-hosted server such as Stalwart/Mailcow.
# Microsoft 365 commonly requires an app password or a future Graph/OAuth adapter.
MAIL_PROVIDER=imap_smtp
MAIL_IMAP_HOST=
MAIL_IMAP_PORT=993
MAIL_IMAP_SSL=true
MAIL_SMTP_HOST=
MAIL_SMTP_PORT=587
MAIL_SMTP_STARTTLS=true
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_FROM=
MAIL_TIMEOUT_SECONDS=30
# Folder names protected from rename/delete through the admin API.
MAIL_PROTECTED_FOLDERS=["INBOX"]
# ----------------------------------
# Accounting documents (Paperless-ngx)
# ----------------------------------
# API-facing Paperless connection. docker-compose.dev.yml overrides the URL
# with the internal service address; localhost:8010 is appropriate when the
# API runs directly on the host.
PAPERLESS_URL=http://localhost:8010
# Create this token in Paperless under My Profile after the first login.
PAPERLESS_TOKEN=
PAPERLESS_TIMEOUT_SECONDS=30
# Largest accounting document accepted through the API (50 MiB).
PAPERLESS_MAX_UPLOAD_BYTES=52428800
# Paperless development-container credentials and persistence services.
# Replace every default below outside local development.
PAPERLESS_ADMIN_USER=admin
PAPERLESS_ADMIN_PASSWORD=admin
PAPERLESS_DB_PASSWORD=paperless
PAPERLESS_SECRET_KEY=CHANGE_ME_IN_PRODUCTION
# ----------------------------------
# Object Storage (S3-compatible; Garage in the dev stack) — labels and product images
# ----------------------------------
# The dev stack's Garage creates its access key from STORAGE_ACCESS_KEY and
# STORAGE_SECRET_KEY below. It also needs a cluster secret of 32 random bytes:
# openssl rand -hex 32
GARAGE_RPC_SECRET=
STORAGE_ENDPOINT_URL=http://localhost:9000
STORAGE_ACCESS_KEY=opentaberna
STORAGE_SECRET_KEY=opentaberna_secret
STORAGE_BUCKET_LABELS=labels
# Bucket holding product images shown in the storefront.
STORAGE_BUCKET_ITEMS=item-images
# Largest product image accepted, in bytes. Guards the object store against
# a single oversized upload filling it.
STORAGE_MAX_IMAGE_BYTES=5242880
STORAGE_REGION=us-east-1
# ----------------------------------
# DHL (Carrier Adapter)
# ----------------------------------
DHL_API_BASE_URL=https://api-sandbox.dhl.com/parcel/de/shipping/v2
DHL_CLIENT_ID=CHANGE_ME
DHL_CLIENT_SECRET=CHANGE_ME
DHL_BILLING_NUMBER=CHANGE_ME
# Label format requested from DHL: pdf or zpl
DHL_DEFAULT_LABEL_FORMAT=pdf
# ----------------------------------
# ARQ Worker / Job Queue
# ----------------------------------
# Concurrent jobs per worker process
ARQ_MAX_JOBS=10
# Seconds a single job may run before it is killed
ARQ_JOB_TIMEOUT=300
# Delivery attempts per job before it is dead-lettered (status DEAD)
ARQ_MAX_TRIES=5
# ----------------------------------
# Transactional Outbox
# ----------------------------------
# Seconds between sweeps of the outbox table for un-enqueued events.
# The poller schedule is derived from this value.
OUTBOX_POLL_INTERVAL=30
# How many times the poller retries enqueuing one event before marking it
# FAILED for manual review. FAILED means the event never reached the queue;
# DEAD means the job ran and exhausted its retries.
OUTBOX_MAX_ATTEMPTS=5
# ----------------------------------
# Keycloak / Authorization
# ----------------------------------
# Base URL the API uses to fetch signing keys (server-to-server).
KEYCLOAK_URL=http://localhost:8080
# Base URL that appears in the token's iss claim. Inside Docker the API talks
# to Keycloak over the compose network while browsers use localhost, so the two
# differ and issuer validation needs the public one. Empty falls back to
# KEYCLOAK_URL.
KEYCLOAK_PUBLIC_URL=
KEYCLOAK_REALM=opentaberna
# Expected token audience — the API's client id, not a frontend's.
KEYCLOAK_CLIENT_ID=opentaberna-api
KEYCLOAK_CLIENT_SECRET=
# Realm role required for admin endpoints.
KEYCLOAK_ADMIN_ROLE=admin
# Clients whose tokens may reach admin endpoints, matched against the token's
# azp. An administrator signed into the storefront therefore cannot drive
# back-office endpoints from it.
KEYCLOAK_ADMIN_CLIENT_IDS=["opentaberna-admin-ui"]
# How long signing keys are cached before being refetched. Keycloak rotates
# keys, so this must expire rather than being fetched once at startup.
KEYCLOAK_JWKS_CACHE_SECONDS=300
# ----------------------------------
# Analytics / reporting
# ----------------------------------
# IANA timezone the shop trades in. Analytics buckets days in this zone rather
# than UTC, so "today" matches the operator's day.
SHOP_TIMEZONE=Europe/Berlin
# Accept anonymous shopper events from the storefront. Off by default: cloning
# OpenTaberna must not silently start collecting anything. While false the
# ingest endpoint returns 404.
STOREFRONT_ANALYTICS_ENABLED=false
# Accept uncaught error reports from the frontends. Off by default, for the same
# reason. While false the report endpoint returns 404.
FRONTEND_ERRORS_ENABLED=false
# ----------------------------------
# OpenTelemetry
# ----------------------------------
# Export traces and metrics over OTLP. Off by default, for the same reason.
OTEL_ENABLED=false
# The seam: pointing this at a vendor's collector is the whole change needed to
# use one, because no application code imports a vendor SDK.
OTEL_EXPORTER_OTLP_ENDPOINT=http://opentaberna-otel-collector:4318
OTEL_SERVICE_NAME=opentaberna-api
OTEL_METRIC_EXPORT_INTERVAL_SECONDS=30