-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.env.example
More file actions
206 lines (184 loc) · 10.1 KB
/
Copy path.env.example
File metadata and controls
206 lines (184 loc) · 10.1 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
# Copy to .env and fill in real values. Never commit .env.
# --- General ---
# Container timezone (applies to the db + app containers; affects log timestamps).
TZ=UTC
# Reverse-proxy hops in front of the app, for X-Forwarded-For trust (login/enroll
# rate-limiting + audit source IP). Set to EXACTLY the number of *your* trusted
# reverse proxies — too high lets an attacker spoof client IPs and bypass the
# brute-force login + enrollment rate limiter.
#
# The bundled compose defaults this to 1 (its nginx). Add 1 for each additional
# proxy you control (e.g. Traefik in front → 2). 0 = trust nothing, use direct peer.
# In non-dev the app will refuse to start if this is set > 3.
# DASH_TRUSTED_PROXY_HOPS=1
# --- Database (MariaDB 11) ---
DB_USER=dash
DB_PASSWORD=change-me-strong-random
DB_ROOT_PASSWORD=change-me-root-strong-random
DB_NAME=dash
# How long the app waits for the database at boot before giving up (seconds).
# Orchestrators without `depends_on` (Swarm, Kubernetes) start the app before
# the database is resolvable; it polls instead of crash-looping. Raise it for a
# slow-starting database, lower it to fail fast.
DASH_DB_WAIT_SECONDS=60
# Backend DB connection pool. Raise for large fleets (many concurrent agent
# pushes); keep pool_size + max_overflow below MariaDB's max_connections.
# DASH_DB_POOL_SIZE=20
# DASH_DB_MAX_OVERFLOW=30
# --- Backend ---
DASH_ENV=prod
DASH_LOG_LEVEL=info
# Log output: console (human-readable key=value) | json (one JSON object per line).
# Security/operational events (logins, failed passwords, IP locks, device up/down)
# stay visible even at DASH_LOG_LEVEL=warning.
# DASH_LOG_FORMAT=console
# Fernet key for every stored credential (firewall API keys, SSH keys,
# notification tokens). Must be url-safe base64 of EXACTLY 32 bytes — the app
# refuses to boot on anything else.
# just gen-key
# openssl rand -base64 32 | tr '+/' '-_' # the tr is required: plain
# # base64 uses + and /, which a
# # Fernet key may not contain
# NEVER change this on a database that already holds data — a new key does not
# re-encrypt anything, it makes every existing *_enc row unreadable.
DASH_MASTER_KEY=
# Initial admin password (only used on first start when no admin exists yet)
DASH_ADMIN_PASSWORD=change-me-on-first-login
# Bootstrap admin = password-only break-glass seed (exempt from 2FA). Three values:
# auto (default) — disabled automatically once another admin exists; re-enabled
# (password reset from DASH_ADMIN_PASSWORD) when none remains.
# 0 — force the seed admin ENABLED (keep it on / manual break-glass).
# 1 — force the seed admin DISABLED.
DASH_ADMIN_DISABLED=auto
# Initial superadmin password (seed account "superadmin"). SuperAdmins manage
# rights only: groups, users and group memberships — no instance access. Same
# break-glass lifecycle as the bootstrap admin (auto|0|1).
DASH_SUPERADMIN_PASSWORD=change-me-on-first-login
DASH_SUPERADMIN_DISABLED=auto
# Two-factor auth. Issuer label shown in authenticator apps for TOTP.
DASH_MFA_ISSUER=Orbit Dashboard
# WebAuthn / passkeys. rp_id = the registrable domain (no scheme/port); origin =
# the EXACT scheme+host+port the browser shows. Dev defaults match the Vite dev
# server. In PRODUCTION (behind Traefik/any proxy) you MUST set both to your real
# domain or passkey registration fails with a browser SecurityError — e.g.
# DASH_WEBAUTHN_RP_ID=dash.example.com and DASH_WEBAUTHN_ORIGIN=https://dash.example.com
# (https, no trailing slash). The backend logs a warning at startup if left at
# localhost when DASH_ENV is not dev. TOTP is unaffected.
DASH_WEBAUTHN_RP_ID=localhost
DASH_WEBAUTHN_ORIGIN=http://localhost:5173
DASH_WEBAUTHN_RP_NAME=Orbit Dashboard
# Orbit (Elixir/LiveView) serves its own SecurityPage on a DIFFERENT origin than
# the python/React UI above, so it needs its own accepted-origin(s) or the two
# stacks clobber each other during the migration window. Comma-separated =
# multiple accepted origins. Unset in prod → falls back to DASH_WEBAUTHN_ORIGIN.
ORBIT_WEBAUTHN_ORIGIN=http://localhost:8000,http://localhost:5173
# Default per-instance poll cadence for direct-API devices (seconds); an
# instance can override it in the UI. The scheduler ticks every
# DASH_POLL_TICK_SECONDS and polls each instance once its interval is due.
DASH_POLL_INTERVAL_SECONDS=30
DASH_POLL_TICK_SECONDS=10
DASH_POLL_CONCURRENCY=20
# Default agent push cadence (seconds) sent to push-mode agents; an instance
# can override it in the UI (applied live on the agent's next push).
DASH_PUSH_INTERVAL_SECONDS=30
# --- Retention & health thresholds ---
# Agent-offline floor (seconds): an agent is flagged offline after ~4 missed
# pushes, but never sooner than this. Raise it if you run very slow push intervals.
DASH_AGENT_STALE_SECONDS=120
# How long raw metrics are kept before the maintenance job prunes them (days).
# Raw rows only serve the 1h/6h chart ranges — longer ranges read the rollup
# tiers below, so this can be short (7 is plenty once the rollups are filled).
DASH_METRICS_RETENTION_DAYS=7
# Rollup tiers: 5-minute buckets serve the 24h/7d ranges, hourly buckets the
# 30d/90d/1y ranges. An hourly row costs ~1% of the raw rows it summarizes,
# which is what makes year-long chart history affordable.
DASH_METRICS_5M_RETENTION_DAYS=90
DASH_METRICS_1H_RETENTION_DAYS=730
# Resolved alert-lifecycle rows (first-seen/acked/resolved trail on the Alerts
# page) are pruned after this many days. Live alerts are never pruned.
DASH_ALERT_HISTORY_RETENTION_DAYS=90
# How long IPsec tunnel events (the VPN history timeline) are kept (days).
DASH_IPSEC_EVENT_RETENTION_DAYS=90
# Access log (Audit page → Access tab): sampled request rows / ended login
# sessions hold user IPs — short window; hourly counters are cheap — long window.
DASH_ACCESS_EVENTS_RETENTION_DAYS=30
DASH_ACCESS_SESSIONS_RETENTION_DAYS=30
DASH_ACCESS_STATS_RETENTION_DAYS=365
# --- Notifications (all optional) ---
# Three channels: Mattermost, Telegram, Email. All settable (and overridable) in
# Settings → Notifications, where secrets are stored encrypted. Which alert
# categories each channel receives is configured per channel in the same UI.
# Mattermost: incoming-webhook URL (secret).
DASH_NOTIFY_MATTERMOST_URL=
# Telegram: bot token (secret) + target chat ID. Used only when both are set.
DASH_NOTIFY_TELEGRAM_TOKEN=
DASH_NOTIFY_TELEGRAM_CHAT_ID=
# Email (SMTP). All settable (and overridable) in Settings → Notifications; the
# password is stored encrypted. Email is sent only when host, from and to are set.
# Security: starttls (587) | ssl (465) | none (25). Username empty = no auth.
DASH_NOTIFY_EMAIL_SMTP_HOST=
DASH_NOTIFY_EMAIL_SMTP_PORT=587
DASH_NOTIFY_EMAIL_SECURITY=starttls
DASH_NOTIFY_EMAIL_FROM=
DASH_NOTIFY_EMAIL_TO=
DASH_NOTIFY_EMAIL_USERNAME=
DASH_NOTIFY_EMAIL_PASSWORD=
# --- Public bind port (host -> container :80) ---
DASH_PORT=80
# --- Optional: pass through to frontend build (Vite) ---
# VITE_API_BASE_URL=
# Firewall GUI proxy (OPTIONAL). Off by default. Orbit gives each firewall a
# per-instance origin and serves it itself — no sidecar. In prod you only add a
# wildcard route on the reverse proxy you already run (see README "Firewall GUI
# proxy"); in dev it works out of the box on <slug>.localhost.
DASH_GUI_PROXY_ENABLED=false
# Per-instance origin template (prod). {slug} = instance slug (persistent, URL-safe;
# {id} also accepted for back-compat). Empty -> the dev convention
# http://{slug}.localhost:8000. Prod e.g.:
# DASH_GUI_BASE_TEMPLATE=https://gui-{slug}.gui.example.com
DASH_GUI_BASE_TEMPLATE=
# Close an instance forwarder after N idle minutes (0 disables).
DASH_GUI_IDLE_MINUTES=15
# Browser terminal (SPIKE): root shell on the firewall via the agent, in a browser
# tab. ARBITRARY ROOT RCE on the box — off by default. Enabling this global gate is
# not enough on its own: each instance must also opt in (Edit instance -> Terminal).
# See docs/agent-architecture.md §22.
DASH_SHELL_ENABLED=false
# Optional session recording (asciicast v2, replay with `asciinema play`). Empty
# = off. Records the box's OUTPUT only, never keystrokes — those carry the
# passwords the terminal does not echo. 8 MB per session, then the file closes
# and the session continues unrecorded. The bundled compose.yml mounts a volume
# at /data/shell-recordings for exactly this; any other path is yours to make
# persistent. Old files are pruned daily — Settings -> Retention.
DASH_SHELL_RECORD_DIR=
# --- GeoIP access restriction (docs/geoip-access-restriction.md) ---
# Superadmin-configured country allowlist + CIDR/DynDNS whitelist, enforced on
# every interactive request. Empty config = allow all; agents and orbit_ API
# keys are always exempt.
# EMERGENCY KILL SWITCH: set true + restart when a bad config locks you out.
DASH_GEOIP_DISABLE=false
# MaxMind credentials for the weekly GeoLite2-City auto-download
# (free GeoLite2 account: https://www.maxmind.com). Empty = no auto-download;
# you can also place the .mmdb into the geoip volume manually.
DASH_MAXMIND_ACCOUNT_ID=
DASH_MAXMIND_LICENSE_KEY=
# Path of the database inside the container (volume-backed by compose).
# Filename is historic — the City .mmdb is installed here in place.
DASH_GEOIP_DB_PATH=/data/geoip/GeoLite2-Country.mmdb
# --- CrowdSec bad-actor blocklist (optional; DR-G8) ---
# Denies IPs with an active CrowdSec ban decision on every interactive request
# (agents/API keys stay exempt; the GeoIP whitelist above always wins).
# Active as soon as the API key is set. Setup:
# docker compose --profile crowdsec up -d
# docker compose --profile crowdsec exec crowdsec cscli bouncers add orbit-dashboard
# DASH_CROWDSEC_DISABLE=true switches it off without removing the key
# (same shape as DASH_GEOIP_DISABLE, which also kills this check).
DASH_CROWDSEC_DISABLE=false
DASH_CROWDSEC_LAPI_URL=http://crowdsec:8080
DASH_CROWDSEC_API_KEY=
# --- Orbit (Elixir/LiveView rewrite, compose profile "orbit") ---
# Cookie-signing secret for the orbit release (prod only; dev uses dev.exs).
# Generate with: openssl rand -base64 48
ORBIT_SECRET_KEY_BASE=
# Public hostname the orbit endpoint generates URLs for (behind nginx/TLS).
DASH_PUBLIC_HOST=