Repository navigation
Expand file tree
/
Copy pathconfig.example.env
More file actions
796 lines (698 loc) · 38.3 KB
/
Copy pathconfig.example.env
File metadata and controls
796 lines (698 loc) · 38.3 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
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
#!/usr/bin/env bash
# Please change this to domain of the server where oneuptime is hosted on.
HOST=localhost
PROVISION_SSL=false
# OneUptime Port. This is the port where OneUptime will be hosted on.
ONEUPTIME_HTTP_PORT=80
# ==============================================
# SETTING UP TLS/SSL CERTIFICATES
# ==============================================
# OneUptime can automatically provision SSL certificates for the HOST when PROVISION_SSL=true.
# This requires port 80/443 to be reachable for Let's Encrypt validation and the HOST domain pointing to this server.
# If you prefer to terminate TLS on an external reverse proxy, leave PROVISION_SSL=false and manage certificates yourself.
HTTP_PROTOCOL=http
# Captcha configuration
CAPTCHA_ENABLED=false
CAPTCHA_SITE_KEY=
CAPTCHA_SECRET_KEY=
# Secrets - PLEASE CHANGE THESE. Please change these to something random. All of these can be different values.
ONEUPTIME_SECRET=please-change-this-to-random-value
REGISTER_PROBE_KEY=please-change-this-to-random-value
DATABASE_PASSWORD=please-change-this-to-random-value
CLICKHOUSE_PASSWORD=please-change-this-to-random-value
VALKEY_PASSWORD=please-change-this-to-random-value
ENCRYPTION_SECRET=please-change-this-to-random-value
GLOBAL_PROBE_1_KEY=probe-1-please-change-this-to-random-value
GLOBAL_PROBE_2_KEY=probe-2-please-change-this-to-random-value
# How many reverse proxies that YOU run sit in front of OneUptime and append to
# the X-Forwarded-For header. This decides which address OneUptime treats as the
# client for IP allowlists (status pages, public dashboards) and IP rate limits.
#
# X-Forwarded-For is a list that each proxy appends its peer to, so a caller can
# put anything they like at the front of it. Only the entries our own proxies
# wrote mean anything, and those are at the END of the list. This number says how
# far in from that end the real client sits.
#
# 1 is correct for a stock install: OneUptime ships its own nginx gateway and
# nothing else touches the header.
#
# Raise it if you put your own HTTP proxy in front. A CDN or WAF that appends to
# X-Forwarded-For (Cloudflare, an AWS ALB, your own nginx or ingress controller)
# makes this 2, and each further proxy adds one. Too low and every visitor looks
# like your proxy; too high and visitors can choose the address you see, which
# defeats the allowlists.
#
# 0 ignores X-Forwarded-For entirely and uses the connecting address — set this
# only if OneUptime is exposed directly with no proxy at all.
TRUSTED_PROXY_HOPS=1
# If you are connecting Status Pages to custom domains, then this will be the port where the status page will be hosted on.
# This should be https port because oneuptime automatically generates ssl certs from lets encrypt.
STATUS_PAGE_HTTPS_PORT=443
# If you would like to attach status pages to custom domains use this setting.
# For example, lets say you would like the status page to be hosted on status.yourcompany.com, then
# 1. Create a A record in your DNS provider with the name "oneuptime.yourcompany.com" and value to Public IP of the server oneuptime is deployed on.
# 2. Set the STATUS_PAGE_CNAME_RECORD to "oneuptime.yourcompany.com"
# 3. Create CNAME record in your DNS provider with the name "status.yourcompany.com" and value "oneuptime.yourcompany.com"
STATUS_PAGE_CNAME_RECORD=oneuptime.yourcompany.com
# If you would like to attach public dashboards to custom domains use this setting.
# Works the same way as STATUS_PAGE_CNAME_RECORD but for dashboards.
# For example, if you want dashboard.yourcompany.com to show a public dashboard:
# 1. Set the DASHBOARD_CNAME_RECORD to "oneuptime.yourcompany.com"
# 2. Create CNAME record in your DNS provider with the name "dashboard.yourcompany.com" and value "oneuptime.yourcompany.com"
DASHBOARD_CNAME_RECORD=oneuptime.yourcompany.com
# --------------------------------------------- #
# You can safely ignore anything below this line. Keep them as default to make things work.
# --------------------------------------------- #
# This supports test | production | development | ci.
# Development is used for local development. Test is used for insider / beta / staging builds. Production is used for production ready app. ci is for testing in the CI/CD.
ENVIRONMENT=production
# What image should we pull from docker hub. This only applies when the ENVIRONMENT is production or test
# The tag also picks the edition:
# release the Community Edition (Apache-2.0), SAML and OIDC
# single sign-on included.
# enterprise-release the Enterprise Edition: the same release plus the
# enterprise features (SCIM, audit logs, team
# compliance, instance health dashboards), licensed
# under the OneUptime Enterprise License (ee/LICENSE).
# Production use requires a OneUptime Enterprise
# subscription. An install without a license runs a
# 14-day trial, which is for evaluation only. After
# the trial (or 30 days after a license expires),
# SCIM and audit logging stop and enterprise
# configuration becomes read-only, until a license is
# activated. Single sign-on does not depend on the
# license, and core monitoring is never affected.
# Pinned versions work the same way: 13.1.0 and enterprise-13.1.0.
APP_TAG=release
# DEPRECATED: the image you pull (APP_TAG above) picks the edition, not this
# variable, and setting it never turns enterprise features on. The Enterprise
# image carries ONEUPTIME_EDITION=enterprise itself, so do not set
# ONEUPTIME_EDITION here. Keep this key for older configs, but know that true
# means "this install must run the Enterprise Edition":
# - On the Community image (APP_TAG=release) the App refuses to start with
# IS_ENTERPRISE_EDITION=true, instead of silently stopping SCIM
# provisioning and audit logging. Set APP_TAG=enterprise-release
# (or enterprise-<version>) to keep the Enterprise Edition, or set this to
# false to run the Community Edition.
# - While it is true, `npm run update` moves APP_TAG to the matching
# enterprise- tag (release -> enterprise-release) and prints what it did.
IS_ENTERPRISE_EDITION=false
# What is the name of the docker compose project. This is used to prefix the docker containers.
COMPOSE_PROJECT_NAME=oneuptime
# Clickhouse Settings
CLICKHOUSE_USER=default
CLICKHOUSE_DATABASE=oneuptime
CLICKHOUSE_HOST=clickhouse
CLICKHOUSE_PORT=8123
# Per-container ClickHouse connection pool ceilings. The ingest pool (used by
# the fan-in telemetry writer) inherits CLICKHOUSE_MAX_OPEN_CONNECTIONS when
# left empty.
CLICKHOUSE_MAX_OPEN_CONNECTIONS=100
CLICKHOUSE_INGEST_MAX_OPEN_CONNECTIONS=
# Postgres DB Settings.
DATABASE_PORT=5432
DATABASE_USERNAME=postgres
DATABASE_NAME=oneuptimedb
DATABASE_HOST=postgres
# Used to connect to managed postgres providers.
# Fill only what your provider needs.
DATABASE_SSL_REJECT_UNAUTHORIZED=false
DATABASE_SSL_CA=
DATABASE_SSL_KEY=
DATABASE_SSL_CERT=
# Cache / queue settings. The bundled container is Valkey (the BSD-licensed
# fork of Redis 7.2), and any Redis-protocol server works here -- point
# VALKEY_HOST at a managed Redis if you prefer.
#
# These were named REDIS_* until 13.0.0. The old names still work: the app
# falls back to them, the compose service still answers to the hostname `redis`,
# and `npm run update` will not overwrite them. Nothing to do on upgrade.
VALKEY_HOST=valkey
VALKEY_PORT=6379
VALKEY_DB=0
VALKEY_USERNAME=default
VALKEY_IP_FAMILY=
VALKEY_TLS_CA=
VALKEY_TLS_SENTINEL_MODE=false
# Hostnames. Usually does not need to change.
SERVER_APP_HOSTNAME=app
#Ports. Usually they don't need to change.
APP_PORT=3002
TEST_SERVER_PORT=3800
HOME_PORT=1444
# Plans
# This is in the format of PlanName,PlanIdFromBillingProvider,MonthlySubscriptionPlanAmountInUSD,YearlySubscriptionPlanAmountInUSD,Order,TrialPeriodInDays
# Enterprise plan will have -1 which means custom pricing.
SUBSCRIPTION_PLAN_BASIC=Basic,priceMonthlyId,priceYearlyId,0,0,1,0
SUBSCRIPTION_PLAN_GROWTH=Growth,priceMonthlyId,priceYearlyId,0,0,2,14
SUBSCRIPTION_PLAN_SCALE=Scale,priceMonthlyId,priceYearlyId,0,0,3,0
SUBSCRIPTION_PLAN_ENTERPRISE=Enterprise,priceMonthlyId,priceYearlyId,-1,-1,4,14
# If you want to run the backup script, then you need to fill these values.
DATABASE_BACKUP_DIRECTORY=/Backups
DATABASE_BACKUP_HOST=localhost
DATABASE_BACKUP_PORT=5400
DATABASE_BACKUP_NAME=oneuptimedb
DATABASE_BACKUP_USERNAME=postgres
DATABASE_BACKUP_PASSWORD=${DATABASE_PASSWORD}
# If you want to run the restore script, then you need to fill these values. Use host.docker.internal if you want to use the host machine's IP.
DATABASE_RESTORE_HOST=host.docker.internal
DATABASE_RESTORE_DIRECTORY=/Backups
DATABASE_RESTORE_PORT=5400
DATABASE_RESTORE_NAME=oneuptimedb
DATABASE_RESTORE_USERNAME=postgres
DATABASE_RESTORE_PASSWORD=${DATABASE_PASSWORD}
DATABASE_RESTORE_FILENAME=db-31.backup
ANALYTICS_KEY=
ANALYTICS_HOST=
# Google Tag Manager. Only ever loaded when BILLING_ENABLED=true, so a
# self-hosted install never reaches googletagmanager.com regardless of this
# value. Set to false to keep the container off even on a billing-enabled
# deployment - which is what the end-to-end suite does, so its scripted
# registrations are not reported as real sign_up conversions.
GOOGLE_TAG_MANAGER_ENABLED=true
DATABASE_MIGRATIONS_HOST=localhost
DATABASE_MIGRATIONS_PORT=5400
# Global Probes
# This is in the format of GLOBAL_PROBE_NAME=ProbeName,ProbeDescription,ProbeKey
GLOBAL_PROBE_1_NAME="Probe-1"
GLOBAL_PROBE_1_DESCRIPTION="Global probe to monitor oneuptime resources"
GLOBAL_PROBE_1_MONITORING_WORKERS=5
GLOBAL_PROBE_1_MONITOR_FETCH_LIMIT=10
# How many NetworkDevice SNMP walks this probe runs at once. Empty uses the
# probe default (25). Together with NETWORK_DEVICE_POLL_FETCH_LIMIT below this
# is what sets how fast a device fleet can be polled — see that entry.
GLOBAL_PROBE_1_NETWORK_DEVICE_POLL_CONCURRENCY=
# How many SNMP OIDs this probe asks for in one GET. Empty uses the probe
# default (20). Every configured OID used to go into a single UDP datagram, so
# a long health-OID list answered tooBig and the DEVICE was reported offline;
# lower this only for an agent with an unusually small maximum message size.
GLOBAL_PROBE_1_SNMP_GET_CHUNK_SIZE=
GLOBAL_PROBE_1_ONEUPTIME_URL=http://localhost
GLOBAL_PROBE_1_SYNTHETIC_MONITOR_SCRIPT_TIMEOUT_IN_MS=60000
GLOBAL_PROBE_1_SYNTHETIC_MONITOR_MAX_CONCURRENCY=4
GLOBAL_PROBE_1_SYNTHETIC_MONITOR_MAX_PROCESS_TREE_RSS_BYTES=1610612736
GLOBAL_PROBE_1_SYNTHETIC_MONITOR_MAX_DISK_BYTES=268435456
# Size of /dev/shm for this probe's container (Docker's default is 64MB). The
# synthetic runtime's browsers do not use it: Playwright starts Chromium with
# --disable-dev-shm-usage, so Chromium keeps its shared memory in the
# per-execution run directory under /tmp, and Firefox uses memfd.
GLOBAL_PROBE_1_SHM_SIZE=512m
GLOBAL_PROBE_1_CUSTOM_CODE_MONITOR_SCRIPT_TIMEOUT_IN_MS=60000
GLOBAL_PROBE_1_PORT=3874
# (Optional) Configure HTTP and HTTPS proxy URLs independently. The legacy
# GLOBAL_PROBE_1_PROXY_URL remains a fallback for both protocols.
GLOBAL_PROBE_1_HTTP_PROXY_URL=
GLOBAL_PROBE_1_HTTPS_PROXY_URL=
GLOBAL_PROBE_1_NO_PROXY=
GLOBAL_PROBE_1_PROXY_URL=
GLOBAL_PROBE_2_NAME="Probe-2"
GLOBAL_PROBE_2_DESCRIPTION="Global probe to monitor oneuptime resources"
GLOBAL_PROBE_2_MONITORING_WORKERS=5
GLOBAL_PROBE_2_MONITOR_FETCH_LIMIT=10
GLOBAL_PROBE_2_ONEUPTIME_URL=http://localhost
GLOBAL_PROBE_2_SYNTHETIC_MONITOR_SCRIPT_TIMEOUT_IN_MS=60000
GLOBAL_PROBE_2_SYNTHETIC_MONITOR_MAX_CONCURRENCY=4
GLOBAL_PROBE_2_SYNTHETIC_MONITOR_MAX_PROCESS_TREE_RSS_BYTES=1610612736
GLOBAL_PROBE_2_SYNTHETIC_MONITOR_MAX_DISK_BYTES=268435456
# Size of /dev/shm for this probe's container (Docker's default is 64MB). The
# synthetic runtime's browsers do not use it: Playwright starts Chromium with
# --disable-dev-shm-usage, so Chromium keeps its shared memory in the
# per-execution run directory under /tmp, and Firefox uses memfd.
GLOBAL_PROBE_2_SHM_SIZE=512m
GLOBAL_PROBE_2_CUSTOM_CODE_MONITOR_SCRIPT_TIMEOUT_IN_MS=60000
GLOBAL_PROBE_2_PORT=3875
# (Optional) Configure HTTP and HTTPS proxy URLs independently. The legacy
# GLOBAL_PROBE_2_PROXY_URL remains a fallback for both protocols.
GLOBAL_PROBE_2_HTTP_PROXY_URL=
GLOBAL_PROBE_2_HTTPS_PROXY_URL=
GLOBAL_PROBE_2_NO_PROXY=
GLOBAL_PROBE_2_PROXY_URL=
SMS_DEFAULT_COST_IN_CENTS=
CALL_DEFAULT_COST_IN_CENTS_PER_MINUTE=
SMS_HIGH_RISK_COST_IN_CENTS=
WHATSAPP_TEXT_DEFAULT_COST_IN_CENTS=
CALL_HIGH_RISK_COST_IN_CENTS_PER_MINUTE=
# IS BILLING ENABLED for this installer.
BILLING_ENABLED=false
# Public and private key for billing provider, usually stripe.
BILLING_PUBLIC_KEY=
BILLING_PRIVATE_KEY=
# Webhook secret for verifying Stripe webhook events (for automatic invoice emails)
# Get this from Stripe Dashboard > Developers > Webhooks > Your endpoint > Signing secret
BILLING_WEBHOOK_SECRET=
# Average telemetry row sizes in bytes used to estimate usage when reporting to the billing provider.
AVERAGE_SPAN_ROW_SIZE_IN_BYTES=1024
AVERAGE_LOG_ROW_SIZE_IN_BYTES=1024
AVERAGE_METRIC_ROW_SIZE_IN_BYTES=1024
AVERAGE_EXCEPTION_ROW_SIZE_IN_BYTES=1024
# Use this when you want to disable incident creation.
DISABLE_AUTOMATIC_INCIDENT_CREATION=false
# Use this when you want to disable incident creation.
DISABLE_AUTOMATIC_ALERT_CREATION=false
# When set to true, OneUptime will reject all incoming telemetry ingestion
# (OpenTelemetry traces / metrics / logs / profiles over HTTP and gRPC,
# Fluentd logs, Syslog logs, and Pyroscope profiles). The ingestion endpoints
# stay reachable and return success quickly so clients don't retry, but no
# data is queued or persisted.
DISABLE_TELEMETRY_INGESTION=false
# Once a day this installation asks the GitHub API which OneUptime version is
# the latest release, so admins are told when an upgrade is available. The
# request sends no usage data — GitHub sees your public IP and a User-Agent
# naming OneUptime and the version you run, as with any outbound HTTP request.
# Set to true to make no outbound call at all (air-gapped deployments can also
# leave it false — the failed request is logged and ignored).
DISABLE_UPDATE_CHECK=false
# Point the update check at an internal mirror instead of GitHub. The mirror
# must answer with GitHub's release shape (tag_name, html_url, published_at).
# Leave blank to use https://api.github.com/repos/OneUptime/oneuptime/releases/latest
LATEST_RELEASE_CHECK_URL=
# On-call calendar feeds let people subscribe Google Calendar / Outlook / Apple
# Calendar to their on-call shifts through a secret .ics URL
# (https://<host>/api/on-call-calendar/user/<token>/shifts.ics). Set to true
# to switch every feed URL off: clients get a 503 with Retry-After: 3600, keep
# the copy they already have and try again in an hour. Nothing is deleted.
DISABLE_ON_CALL_CALENDAR_FEED=false
# Rate limits for those feed URLs. The token+address counter is the budget one
# subscribed calendar gets; the address counter is the ceiling that survives a
# caller rotating tokens. Calendar clients poll about hourly (Apple every five
# minutes at most), so the defaults leave plenty of room for a whole team's
# clients behind one office address. Blank keeps the default. The limiter fails
# open when Valkey is unreachable.
ON_CALL_CALENDAR_FEED_RATE_LIMIT_WINDOW_SECONDS=60
ON_CALL_CALENDAR_FEED_RATE_LIMIT_PER_TOKEN_PER_WINDOW=60
ON_CALL_CALENDAR_FEED_RATE_LIMIT_PER_IP_PER_WINDOW=3000
# OAuth sign-in for the MCP server (https://<host>/mcp). An MCP client can
# connect by having a project member sign in to OneUptime and approve it,
# instead of being handed an API key. Set to true to switch that off: the
# authorization server under /mcp/oauth and its discovery documents stop being
# served and the MCP server accepts API keys only, as it did before. Nothing is
# deleted; clients that were connected work again when it is switched back.
DISABLE_MCP_OAUTH=false
# An MCP client may identify itself by an https URL that this server fetches
# to read the client's name and redirect URIs (a Client ID Metadata Document).
# That is an outbound request, so set this to true on an instance that cannot
# reach the internet: clients then register themselves with this server
# instead, which needs no outbound request.
DISABLE_MCP_OAUTH_CLIENT_ID_METADATA_DOCUMENTS=false
# Browser source maps, uploaded from CI so exception stack traces show original
# file names and line numbers instead of minified ones.
#
# Raise SOURCE_MAP_MAX_MAPS_PER_RELEASE if your build emits more .map files per
# release than the default holds -- route-level code splitting routinely emits
# hundreds. It is a storage-shape limit only: resolution is bounded by
# SOURCE_MAP_MAX_BYTES_PER_RESOLVE, so anything that fits the ceiling resolves.
#
# The two request-shaped limits can only be LOWERED. The multipart body is
# parsed before authentication, so the shared 50-file / 50 MiB ceilings are
# what an unauthenticated caller is held to; values above them are narrowed.
SOURCE_MAP_MAX_MAPS_PER_RELEASE=1000
SOURCE_MAP_MAX_FILES_PER_REQUEST=50
SOURCE_MAP_MAX_FILE_SIZE_BYTES=52428800
SOURCE_MAP_MAX_BYTES_PER_RESOLVE=536870912
SOURCE_MAP_RETENTION_DAYS=90
# Server-side OpenTelemetry exporter configuration. These values are available
# only to backend processes. They are never serialized into frontend env.js
# responses, so headers may contain a Server ingestion key or another secret.
OPENTELEMETRY_EXPORTER_OTLP_ENDPOINT=
# You can set the env var to "x-oneuptime-token=<YOUR_ONEUPTIME_TELEMETRY_INGEST_TOKEN>"
OPENTELEMETRY_EXPORTER_OTLP_HEADERS=
# Optional browser RUM exporter configuration. Both values below are PUBLIC:
# every visitor can read them from /env.js. Use only a OneUptime Browser
# ingestion key configured with this deployment's exact origins. Browser keys
# are limited to browser ingest surfaces, checked against the Origin header and
# rate-limited. Never place a Server key or an arbitrary collector bearer token
# here. Leave both blank to disable browser RUM export.
PUBLIC_OPENTELEMETRY_EXPORTER_OTLP_ENDPOINT=
PUBLIC_OPENTELEMETRY_EXPORTER_OTLP_BROWSER_INGESTION_KEY=
# This can be one of ERROR, WARN, INFO, DEBUG
#
# Logs go to container stdout, to an in-memory recent-log buffer the master
# admin support bundle can read back, and to the OTLP exporter above when one
# is configured -- so anything logged lands in every log system you retain.
# Credentials are redacted centrally before they reach any of those, but DEBUG
# is verbose and its output is worth the same protection as the rest of your
# telemetry: keep it off unless you are troubleshooting, and treat retained
# DEBUG output as sensitive.
LOG_LEVEL=ERROR
# Thse env vars are for E2E tests
E2E_TEST_IS_USER_REGISTERED=false
E2E_TEST_REGISTERED_USER_EMAIL=
E2E_TEST_REGISTERED_USER_PASSWORD=
# If you want to run the E2E tests on a status page, then you need to fill in the URL.
E2E_TEST_STATUS_PAGE_URL=
# This URL will be called when the E2E tests fail. This should be a GET endpoint.
E2E_TESTS_FAILED_WEBHOOK_URL=
# This is the timeout for the workflow script in milliseconds.
# How long do we wait for "Scripts" (like Custom Code Components) running in workflow to complete.
WORKFLOW_SCRIPT_TIMEOUT_IN_MS=5000
# How long do we wait for entire workflow to complete.
WORKFLOW_TIMEOUT_IN_MS=120000
# Concurrency settings
# Max number of telemetry jobs processed concurrently by OpenTelemetry Ingest worker
TELEMETRY_CONCURRENCY=100
# How many NetworkDevices one probe is handed per fetch. A probe fetches once a
# minute, so this is the ceiling on how fast that probe's fleet can be polled,
# whatever the devices' own polling intervals say: 250 devices/minute clears a
# 1000-device fleet on a 5-minute interval. Empty uses the server default (250).
#
# Raise it together with the probe's own
# GLOBAL_PROBE_n_NETWORK_DEVICE_POLL_CONCURRENCY. Claiming a device advances its
# schedule whether or not the walk actually happens, so handing a probe more
# devices than it can walk inside a cycle skips them rather than polling them
# sooner. A "claimed a full batch" warning in the app log means this limit, not
# the devices' intervals, is setting the fleet's cadence.
NETWORK_DEVICE_POLL_FETCH_LIMIT=
# Fan-in telemetry writer (per container). Batches all telemetry ClickHouse
# inserts into a handful of large INSERTs so ingestion can scale without
# exploding ClickHouse insert concurrency. Defaults shown below match the code.
# Rows buffered per table before a flush is forced.
TELEMETRY_FANIN_MAX_BATCH_ROWS=100000
# Per-table override for session replay chunks. The batcher counts rows, not
# bytes, and a replay row carries the whole decompressed rrweb payload in one
# column, so the global 100000 above would attempt a multi-hundred-MB insert.
TELEMETRY_FANIN_MAX_BATCH_ROWS_SESSION_REPLAY=2000
# Longest a buffered row waits (in ms) before its table is flushed anyway.
TELEMETRY_FANIN_MAX_WAIT_MS=5000
# Max simultaneous ClickHouse INSERTs per container. Total insert concurrency
# across all containers should stay under ~60% of ClickHouse
# max_concurrent_queries.
TELEMETRY_FANIN_MAX_CONCURRENT_INSERTS=4
# Backpressure cap: ingestion jobs block once this many rows are queued.
TELEMETRY_FANIN_MAX_PENDING_ROWS=200000
# Retry budget for failed inserts: attempts + exponential backoff bounds (ms).
TELEMETRY_FANIN_RETRY_MAX_ATTEMPTS=6
TELEMETRY_FANIN_RETRY_BASE_DELAY_MS=250
TELEMETRY_FANIN_RETRY_MAX_DELAY_MS=10000
# Ack mode for telemetry ClickHouse inserts. Default false = fire-and-forget
# async inserts: ClickHouse acks once a batch is accepted into its
# async-insert buffer and owns flushing it (flush errors surface only in
# ClickHouse server logs; a crash between accept and flush loses that
# buffer). Set true to make acks wait for the durable flush — each waiting
# insert then holds a ClickHouse query slot until its buffer flushes.
TELEMETRY_WAIT_FOR_ASYNC_INSERT=false
# Dedicated telemetry-writer tier (advanced; normally left empty in compose —
# the Helm chart wires this via telemetryWriter.enabled). When set on a
# container that processes telemetry ingest, its fan-in writer ships batched
# ClickHouse inserts to this URL (cluster-key authenticated) instead of
# inserting directly, so ingestion containers scale without adding ClickHouse
# insert concurrency. The container SERVING that URL must NOT have this set.
# Example: TELEMETRY_WRITER_URL=http://telemetry-writer:3002
TELEMETRY_WRITER_URL=
# How long a shipped insert may take end-to-end (writer batching + retries).
# Keep 6 x this + backoff under the 10-minute telemetry job lock.
TELEMETRY_WRITER_REQUEST_TIMEOUT_MS=90000
# Split shipped batches whose JSON body would exceed this many bytes (stay
# under the 50 MB internal request-body limit; oversized posts are dropped).
TELEMETRY_WRITER_MAX_BODY_BYTES=30000000
# Writer-side admission cap: concurrently-served insert requests per
# container before shedding with 429 (callers retry with the same
# idempotent dedup token).
TELEMETRY_WRITER_MAX_INFLIGHT_REQUESTS=100
# Session replay ingest.
# Instance-level kill switch for accepting session replay chunks. Independent
# of the per-project and per-application toggles: set false to stop accepting
# recordings fleet-wide without a deploy.
SESSION_REPLAY_INGEST_ENABLED=true
# Whether this deployment offers session replay at all. TRUE by default.
#
# On a self-hosted install, set this to false unless you have also set a byte
# budget below. Plan gating is a no-op when BILLING_ENABLED=false, so nothing
# else stops 100% sampling at 90-day retention on a single ClickHouse node —
# and because replay is the fattest table, the capacity pruner would then start
# dropping partitions, potentially destroying the install's logs and traces to
# make room.
SESSION_REPLAY_ENABLED_BY_DEFAULT=true
# Ask every browser recorder this deployment serves to print its decisions to
# the console. OFF by default and it should stay that way in normal operation:
# the recorder runs on your customers' sites, in their end users' browsers.
#
# This is the switch of last resort, for an operator who needs to know why
# replay produces nothing on a page they do not own and cannot edit. The
# per-browser switches are usually the right ones instead —
# localStorage.setItem("oneuptime.sessionReplay.debug", "true"), or an
# ?oneuptime_debug=1 on the URL. Turn this on, collect one reload, turn it off.
#
# It changes no policy: not sampling, not masking, not consent. It only adds
# output. See /docs/rum/session-replay-troubleshooting.
SESSION_REPLAY_DEBUG=false
# Per-project chunk ceiling per minute, counted in Valkey so it holds across
# every app pod. Exceeding it answers 429 with Retry-After.
SESSION_REPLAY_MAX_CHUNKS_PER_PROJECT_PER_MINUTE=20000
# Per-project daily byte budget (default 1 GiB). This is the disk-protection
# control that works regardless of billing. Exceeding it answers 204 and tells
# live recorders to stand down for the rest of the day.
SESSION_REPLAY_MAX_BYTES_PER_PROJECT_PER_DAY=1073741824
# Chunks at or under this size ride inline in the queue job as base64 instead
# of being staged in Valkey. A typical chunk is ~7 KB, so this keeps ~99% of
# chunks out of Valkey entirely — which matters because compose runs Valkey
# with persistence off and no configured maxmemory.
SESSION_REPLAY_INLINE_STAGING_MAX_BYTES=65536
# Replay's share of the shared telemetry worker's concurrency slots, per pod.
# Caps a replay backlog so it cannot starve trace and log ingest.
SESSION_REPLAY_WORKER_CONCURRENCY=20
# The ONE request header whose country code replay ingest is allowed to trust,
# lowercased (cf-ipcountry behind Cloudflare, x-vercel-ip-country behind
# Vercel). Empty means no country is recorded at all, which is the default:
# nothing in the Nginx config strips these headers, so honouring one on a
# deployment that is not actually behind that CDN lets any client stamp
# arbitrary countries onto session rows.
SESSION_REPLAY_TRUSTED_GEO_HEADER=
# MQTT ingest for IoT devices. Devices connect over MQTT-over-WebSocket at
# ws(s)://<your-host>/mqtt (rides the normal HTTP/HTTPS ports), or over raw
# MQTT TCP on MQTT_INGEST_PORT inside the compose network. Set
# MQTT_INGEST_ENABLED=false to turn the listeners off.
MQTT_INGEST_ENABLED=true
MQTT_INGEST_PORT=1883
# Max number of jobs processed concurrently by Fluent Logs worker
FLUENT_LOGS_CONCURRENCY=100
# Max number of jobs processed concurrently by Worker service
WORKER_CONCURRENCY=100
# Role split (advanced, mainly for Kubernetes). When true, this process does
# NOT consume BullMQ queues — it only serves the API + ingest endpoints and
# enqueues jobs. A separate "worker" deployment (with DISABLE_QUEUE_WORKERS
# unset/false) then drains the queues, so heavy telemetry/background processing
# can't stall API requests. Default false: this process both serves the API and
# processes all background + telemetry jobs (single-container behavior).
DISABLE_QUEUE_WORKERS=false
# Lets encrypt notification email. This email will be used when certs are about to expire
LETS_ENCRYPT_NOTIFICATION_EMAIL=
# Generate a private key via openssl, encode it to base64 and paste it here.
# Example: "LS0tLS....1cbg=="
LETS_ENCRYPT_ACCOUNT_KEY=
# This is the number of active monitors allowed in the free plan.
ALLOWED_ACTIVE_MONITOR_COUNT_IN_FREE_PLAN=10
# Outbound Webhook Egress Policy (self-hosted)
#
# By default OneUptime refuses to send any workflow request, project webhook,
# on-call user webhook or sandboxed HTTP call to a target that resolves into a
# private, loopback or link-local range. That is the right default, but it also
# blocks the ordinary self-hosted case of posting an alert to an internal
# Mattermost, Jira or ticketing system on 10.x / 192.168.x.
#
# Both settings below are OFF by default and both are instance-wide. They are
# the only gate: there is no per-project setting, so whatever they allow applies
# to every project on this instance. Status page subscriber webhooks are never
# covered, because any visitor to a public status page can register one.
#
# Permit the private tier — RFC-1918, CGNAT, IPv6 unique-local and site-local.
# Loopback, link-local (169.254.169.254 lives there), multicast and reserved
# stay blocked; use the allowlist below if you truly need one of those.
ALLOW_PRIVATE_NETWORK_WEBHOOKS=false
#
# Comma-separated hosts and CIDRs that are allowed regardless of range —
# hostnames ("mattermost.internal"), wildcards ("*.svc.cluster.local"), IPs and
# CIDRs ("10.20.0.0/16", "fd00::/8"). A hostname listed here is trusted without
# a DNS check, which is the point: it is expected to resolve somewhere private.
# NEVER list 169.254.169.254 or a range containing it — on a cloud VM that
# hands every project member the instance's IAM credentials.
PRIVATE_NETWORK_WEBHOOK_ALLOWLIST=
# Outbound Connection Egress Policy (everything that is not a webhook)
#
# External data sources (security event connections such as Splunk, threat
# intel feeds), LLM providers, SMTP servers (project settings and the workflow
# Email component), SMTP and workflow OAuth token URLs, OIDC discovery, status
# page / dashboard domain verification and Runbook HTTP steps are checked by a
# separate guard. Loopback, link-local (169.254.169.254) and reserved ranges are
# refused everywhere. The private tier (RFC-1918, CGNAT, IPv6 unique-local) is
# ALLOWED on a self-hosted install, because the servers these connect to usually
# live there.
#
# Set this to true to refuse the private tier for these connections as well --
# for example when projects on this instance belong to people who should not
# reach your internal network. Only the exact value "true" turns it on. It is
# always on when BILLING_ENABLED=true, whatever this line says. It does not
# change which webhook targets (see above) or monitor targets (see below) are
# allowed, and it does not apply to a Global LLM Provider
# (GLOBAL_LLM_PROVIDER_* below, or one added in the Admin Dashboard): you
# choose its address, not a project. It does change how refusals read: with it
# on, a refused host name -- here, and for webhooks and workflow requests too
# -- is reported as "... could not be reached." without saying whether it
# failed to resolve or what it resolved to, so project members cannot use it
# to map internal names. LOG_LEVEL=DEBUG logs the exact reason.
DATA_SOURCE_BLOCK_PRIVATE_ADDRESSES=false
# Whether API, Website, External Status Page and Custom JavaScript Code
# MONITORS may reach private network addresses (RFC-1918, CGNAT, IPv6
# unique-local) from a probe.
#
# This is a separate, probe-side switch, and it is read by the probe process
# from its OWN environment — not from the settings above, which live on the API
# server. Whoever deploys a probe controls its environment, and they are the
# party who knows which network that probe can see. Off by default.
#
# It applies to every probe that has it set, including the bundled Docker
# Compose probes: docker-compose.base.yml passes this one value to probe-1 and
# probe-2 alike. Those are GLOBAL probes (they register with
# REGISTER_PROBE_KEY and every project can select them), so setting it to true
# here lets monitors from EVERY project on this instance reach private
# addresses through them. If projects on this instance should not share that
# reach, leave it false and deploy a private (custom) probe inside each
# network that needs monitoring.
#
# API, Website and External Status Page requests are DNS-validated and pinned
# at connection time; Custom Code uses the same address policy in its sandbox
# bridge. Only the exact value "true" turns it on.
#
# Turning it on does NOT open loopback, link-local or the cloud metadata
# endpoint — those stay refused on every probe.
#
# A global probe with BILLING_ENABLED=true in its environment (the hosted,
# open-signup product) stays public-only: the setting is ignored there, and the
# probe logs a warning at startup saying so. Both the bundled Compose probes and
# the Helm chart's probes are given BILLING_ENABLED for this.
#
# To turn it on, change the line below to true (do not add a second line: the
# later one wins) and run `npm run start` to recreate the probe containers.
# A value other than exactly "true" or "false" is reported as a warning at
# startup. The probe's routine "private network monitoring is on/off" line is
# logged at LOG_LEVEL=INFO, above the LOG_LEVEL=ERROR this file ships with
# (OneUptime issue #3879).
PROBE_ALLOW_PRIVATE_NETWORK_MONITORS=false
# Open Source Deployment Webhook
# This webhook is called when a new self-hosted open source deployment registers.
OPEN_SOURCE_DEPLOYMENT_WEBHOOK_URL=
# Notifications Webhook (Slack)
# This webhook notifies slack when the new user signs up or is created.
NOTIFICATION_SLACK_WEBHOOK_ON_CREATED_USER=
# This webhook notifies slack when the new project is created.
NOTIFICATION_SLACK_WEBHOOK_ON_CREATED_PROJECT=
# This webhook notifies slack when the project is deleted.
NOTIFICATION_SLACK_WEBHOOK_ON_DELETED_PROJECT=
# This webhook notifies slack when the subscription is updated.
NOTIFICATION_SLACK_WEBHOOK_ON_SUBSCRIPTION_UPDATE=
# VAPID keys for Web Push Notifications
# Generate using: npx web-push generate-vapid-keys
VAPID_PUBLIC_KEY=
VAPID_PRIVATE_KEY=
VAPID_SUBJECT=mailto:support@oneuptime.com
# Expo access token for sending mobile push notifications directly via Expo SDK.
# If not set, push notifications are relayed through the push notification relay URL below.
EXPO_ACCESS_TOKEN=
# Push notification relay URL for self-hosted instances without Expo credentials.
# Self-hosted servers relay push notifications through this gateway.
PUSH_NOTIFICATION_RELAY_URL=https://oneuptime.com/api/notification/push-relay/send
# AI Agent Configuration
ONEUPTIME_RUNNER_KEY=please-change-this-to-random-value
ONEUPTIME_RUNNER_ONEUPTIME_URL=http://localhost
ONEUPTIME_RUNNER_PORT=3876
# By default telemetry is disabled for all services in docker compose. If you want to enable telemetry for a service, then set the env var to false.
DISABLE_TELEMETRY_FOR_APP=true
DISABLE_TELEMETRY_FOR_TEST_SERVER=true
DISABLE_TELEMETRY_FOR_PROBE=true
DISABLE_TELEMETRY_FOR_INGRESS=true
DISABLE_TELEMETRY_FOR_RUNNER=true
# By default profiling is disabled for all services. Set to true to enable CPU profiling for a service.
ENABLE_PROFILING_FOR_APP=false
ENABLE_PROFILING_FOR_TEST_SERVER=false
ENABLE_PROFILING_FOR_PROBE=false
ENABLE_PROFILING_FOR_RUNNER=false
# Connect OneUptime with Slack App
SLACK_APP_CLIENT_ID=
SLACK_APP_CLIENT_SECRET=
SLACK_APP_SIGNING_SECRET=
# Example -
# IPv6 only:
# NGINX_LISTEN_ADDRESS=[::]:
# NGINX_LISTEN_OPTIONS=
# dual stack:
# NGINX_LISTEN_ADDRESS=[::]:
# NGINX_LISTEN_OPTIONS=ipv6only=off
NGINX_LISTEN_ADDRESS=
NGINX_LISTEN_OPTIONS=
# Microsoft Teams / Azure AD App Configuration
# IMPORTANT: Use the SECRET VALUE, not the SECRET ID from Azure App Registration
# The secret value is typically longer and includes more characters
MICROSOFT_TEAMS_APP_CLIENT_ID=
MICROSOFT_TEAMS_APP_CLIENT_SECRET=
MICROSOFT_TEAMS_APP_TENANT_ID=
# GitHub App Configuration
# Create a GitHub App at https://github.com/settings/apps
# Required for connecting GitHub repositories to OneUptime
#
# The GitHub App must have "Request user authorization (OAuth) during
# installation" enabled. OneUptime exchanges the OAuth code GitHub returns to
# confirm the person installing the app actually controls the installation
# before connecting it to their project; without it, connecting is refused.
# CLIENT_ID and CLIENT_SECRET are required for that exchange.
#
# GITHUB_APP_WEBHOOK_SECRET is also required: webhooks whose signature cannot
# be verified are rejected rather than trusted.
#
# GITHUB_APP_NAME must match the app's real name on GitHub. The app's mention
# handle is derived from it (lowercased, spaces to hyphens), so an app named
# "Acme AI" is addressed as "@acme-ai" — get this wrong and mentions silently
# never match. Answering mentions also needs the app to hold the "Issues:
# Read & write" permission and to be subscribed to the Issue comment, Issues,
# Pull request, Pull request review and Pull request review comment events.
# See: https://oneuptime.com/docs/self-hosted/github-integration
# and: https://oneuptime.com/docs/ai/github-app
GITHUB_APP_ID=
GITHUB_APP_NAME=
GITHUB_APP_CLIENT_ID=
GITHUB_APP_CLIENT_SECRET=
GITHUB_APP_PRIVATE_KEY=
GITHUB_APP_WEBHOOK_SECRET=
# Inbound Email Configuration
# Required for Incoming Email Monitor feature
# See documentation: https://oneuptime.com/docs/self-hosted/sendgrid-inbound-email
INBOUND_EMAIL_PROVIDER=SendGrid
# The domain configured for inbound email (e.g., inbound.yourdomain.com)
INBOUND_EMAIL_DOMAIN=
# Optional webhook secret for validating incoming webhooks
INBOUND_EMAIL_WEBHOOK_SECRET=
# Marketing conversion webhooks
# OneUptime does not store conversions. Signups, plan upgrades/downgrades
# and issued enterprise licenses are POSTed to this
# endpoint as they happen and kept nowhere afterwards — leave the URL empty and
# those moments are simply not measured.
# Requests are signed with HMAC-SHA256 over the exact body bytes, hex encoded,
# in the x-oneuptime-signature-256 header. Both values are required: a URL set
# without a secret is refused rather than sent unsigned.
# See Docs/analytics/marketing-event-webhooks.md for the payload structure.
MARKETING_WEBHOOK_URL=
MARKETING_WEBHOOK_SECRET=
# BullMQ Queue Dashboard (Bull Board)
# When enabled, exposes the queue inspector UI at /worker/inspect/queue/<QUEUE_DASHBOARD_SECRET>.
# Both must be set for the dashboard to be mounted. The secret acts as the URL path segment that
# operators must know to reach the UI.
ENABLE_QUEUE_DASHBOARD=false
QUEUE_DASHBOARD_SECRET=
# Global LLM Provider (optional)
# Declaratively registers a Global LLM Provider at startup so AI features work
# for all projects without dashboard setup — including AI Agent fix tasks on
# self-hosted instances. Set GLOBAL_LLM_PROVIDER_TYPE to enable (one of:
# OpenAI, AzureOpenAI, Anthropic, Groq, Mistral, Ollama, OpenAICompatible);
# unset it to remove the seeded provider on the next restart.
# An API key is required for OpenAI, AzureOpenAI, Anthropic, Groq and Mistral.
# Ollama and OpenAICompatible (vLLM, LocalAI, LM Studio, etc.) are keyless and
# need GLOBAL_LLM_PROVIDER_BASE_URL instead; OpenAICompatible also requires
# GLOBAL_LLM_PROVIDER_MODEL_NAME.
GLOBAL_LLM_PROVIDER_TYPE=
GLOBAL_LLM_PROVIDER_NAME=
GLOBAL_LLM_PROVIDER_DESCRIPTION=
# e.g. http://ollama:11434 for Ollama, or http://my-vllm:8000/v1 for vLLM.
# The app container connects to it, so localhost would be that container;
# loopback is refused anyway. Use a service name on this compose network,
# or the host's LAN IP. See https://oneuptime.com/docs/ai/llm-provider
GLOBAL_LLM_PROVIDER_BASE_URL=
GLOBAL_LLM_PROVIDER_MODEL_NAME=
GLOBAL_LLM_PROVIDER_API_KEY=