-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.env.example
More file actions
193 lines (164 loc) · 10 KB
/
Copy path.env.example
File metadata and controls
193 lines (164 loc) · 10 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
# ── NineDeploy environment ────────────────────────────────────────────
# Copy to .env and adjust. Never commit .env.
# Runtime: "development" | "production"
NODE_ENV=development
# Where NineDeploy stores its data (db, repos, logs, backups).
NINEDEPLOY_DATA_DIR=./.data
# SQLite database file (relative to data dir unless absolute).
NINEDEPLOY_DB_PATH=./.data/ninedeploy.db
# Server
NINEDEPLOY_HOST=0.0.0.0
NINEDEPLOY_PORT=3000
# Public URL the dashboard is reached at (used for webhooks, CORS, emails).
NINEDEPLOY_PUBLIC_URL=http://localhost:3000
# Comma-separated extra origins allowed by CORS (besides the public URL and
# localhost dev ports). Leave empty if the dashboard is same-origin with the API.
NINEDEPLOY_CORS_ORIGINS=
# Reverse-proxy trust (Fastify trustProxy). The default trusts ONE hop, which
# matches every standard install where the panel sits behind its own Traefik —
# without it, rate limits and audit logs see only the proxy's IP. Only
# loopback/private peers are ever trusted as a proxy, so a client connecting
# straight from the internet cannot spoof X-Forwarded-For even with this set.
# Set "false" to trust no proxy (e.g. untrusted clients on the same LAN), or a
# higher hop count when extra proxies sit in front of Traefik.
NINEDEPLOY_TRUST_PROXY=1
# Auth — JWT signing secrets (generate long random strings in production).
# REQUIRED in production: the server refuses to boot with the insecure default.
NINEDEPLOY_JWT_SECRET=change-me-to-a-long-random-string
NINEDEPLOY_JWT_ACCESS_TTL=15m
NINEDEPLOY_JWT_REFRESH_TTL=7d
# Master key for encrypting secrets at rest (AES-256-GCM).
# Leave empty on first run to auto-generate /etc/ninedeploy... or DATA_DIR/master.key.
#
# ⚠ DISASTER RECOVERY: EVERY stored secret and EVERY backup (local and S3) is
# sealed with this key. A lost host without a preserved master.key means the
# backups are cryptographically gone — the panel cannot warn you about this,
# so store master.key (and NINEDEPLOY_MASTER_KEYS) in your password manager or
# KMS, OFF the host, and keep it in sync when you rotate.
NINEDEPLOY_MASTER_KEY=
# Key rotation: comma-separated "version:hex" pairs. The highest version is the
# active (encryption) key; lower versions are kept only so old secrets decrypt.
# To rotate: add a new 32-byte key under a higher version, restart, then run
# `ninedeploy system rotate-keys` (or POST /v1/settings/master-key/rotate).
# Only THEN drop the old version — and not before every backup taken under it
# has aged out: dumps carry their own key version in the envelope header and are
# NOT rewritten by the rotation, so removing a key makes them unrestorable.
# Example: NINEDEPLOY_MASTER_KEYS=0:<old-hex>,1:<new-hex>
NINEDEPLOY_MASTER_KEYS=
# Override the SQL migrations folder. Leave empty — the server self-migrates at
# startup and auto-resolves the folder (env > dist layout > source > cwd).
NINEDEPLOY_MIGRATIONS_DIR=
# Wildcard domain for auto-URLs (e.g. ninedeploy.dev → my-app.ninedeploy.dev).
# Requires wildcard DNS *.ninedeploy.dev → your server IP.
NINEDEPLOY_WILDCARD_DOMAIN=
# Hostname the panel itself is served on, used to generate its own Traefik
# router. Settings → Security wins over this; the env var is the fallback for
# an install configured entirely from a file.
NINEDEPLOY_DOMAIN=
# Automatic HTTPS (Let's Encrypt): set an email and the SSL toggle on domains
# issues real certificates via Traefik's ACME http-challenge on :80. Leave
# empty to disable ACME. Configure it in Settings -> Security for immediate
# application; changing this environment fallback requires a server restart.
NINEDEPLOY_ACME_EMAIL=
# ACME directory override for testing (avoids the harsh production rate
# limits). Remove for real certificates once everything works.
# NINEDEPLOY_ACME_CA_SERVER=https://acme-staging-v02.api.letsencrypt.org/directory
# Template registry source override: an https URL or an absolute path to a JSON
# registry bundle. Leave empty to use the bundled registry (this repo).
NINEDEPLOY_TEMPLATES_SOURCE=
# DNS-01 challenge for WILDCARD certificates (needs NINEDEPLOY_WILDCARD_DOMAIN).
# Provider: cloudflare | digitalocean | hetzner | linode | gandi | duckdns.
# The token never appears in process argv — it reaches Traefik via --env-file.
NINEDEPLOY_DNS_PROVIDER=
NINEDEPLOY_DNS_TOKEN=
# Parallel deploy slots in the worker (1-8). The same service is never
# deployed concurrently regardless of this value.
NINEDEPLOY_DEPLOY_CONCURRENCY=1
# Outbound requests the panel makes on an operator's behalf (notification
# webhooks, the OIDC issuer, S3 endpoints, log drains, the template registry,
# git clones) are refused when they resolve to a private, loopback, link-local,
# CGNAT or multicast address — that is what stops a settings field becoming a
# request from inside the Docker network, or to the cloud metadata endpoint at
# 169.254.169.254. Set this to 1 if the instance legitimately has to reach a
# receiver on its own LAN (a self-hosted Gitea, an internal webhook sink).
NINEDEPLOY_ALLOW_PRIVATE_EGRESS=
# ── Sandbox plugin network (r600) ────────────────────────────────────────
# Sandbox plugins run in a Node permission-model child process. Node 25+ can
# deny that process the network; on Node 22/24 it cannot, so a sandbox plugin
# could make arbitrary requests from this host. New sandbox installs are
# therefore refused on Node < 25 unless this is 1 (already-installed plugins
# keep loading; the Doctor flags them). Prefer upgrading Node instead.
NINEDEPLOY_ALLOW_SANDBOX_NETWORK=
# ── Live signed marketplace index (G-24) ─────────────────────────────────
# When NINEDEPLOY_MARKETPLACE_URL is set, the panel's
# Plugins → Marketplace tab fetches a signed JSON index
# from this URL and merges the verified entries with the
# in-code fallback. The verifier is ed25519; the
# signature is over the canonical JSON of `entries`.
# A live index that fails signature verification is
# dropped (the fallback is served instead), so leave
# NINEDEPLOY_MARKETPLACE_PUBLIC_KEY unset in dev and
# always set it in production.
NINEDEPLOY_MARKETPLACE_URL=
NINEDEPLOY_MARKETPLACE_PUBLIC_KEY=
# How many snapshots each Docker volume keeps. Older ones are swept after a
# successful backup; database backups have their own retention (7 scheduled,
# manual ones untouched).
NINEDEPLOY_BACKUP_VOLUME_RETAIN_COUNT=10
# Where `system update-check` and the panel's update banner look for the latest
# release. This is the panel's only unprompted outbound call — set it to
# `disabled` to turn update checks off entirely, or point it at a mirror.
# With the default GitHub feed the panel falls back, in order, to the
# github.com release page, the same two via the host's curl, and
# `git ls-remote` — the sources install.sh itself uses — and keeps showing the
# last release it saw (<data dir>/update-check.json) when all of them fail.
NINEDEPLOY_UPDATE_CHECK_URL=
# Absolute path to the built dashboard (apps/web/dist). Leave empty: the server
# auto-detects it and falls back to API-only mode when it is genuinely absent.
# Only needed for an unusual layout where that detection cannot work.
NINEDEPLOY_WEB_DIST=
# Nixpacks CLI version (default: latest verified). The installer fetches the
# pinned release from railwayapp/nixpacks, checks it against the SHA-256
# table in install.sh, and only then exposes it on PATH. Set to a known
# release to pin (must exist in install.sh's checksum table).
# NINEDEPLOY_NIXPACKS_VERSION=1.41.0
# BuildKit daemon for the optional `railpack` build pack (r582). Railpack
# builds through its own BuildKit client and refuses to run without this; the
# panel refuses the build pack until it is set. Start a daemon once with
# docker run -d --name buildkit --restart unless-stopped --privileged moby/buildkit
# and point the panel at it. Never taken from a service's own env vars.
# BUILDKIT_HOST=docker-container://buildkit
# Per-database version override. Each managed DB row carries an optional
# `version` string; empty = the engine default. Examples:
# version: '8.4' (MySQL LTS, when the default is the Innovation track)
# version: '7.0' (MongoDB previous LTS)
# version: 'pg18' (any tag the upstream image actually publishes)
# ── Multi-server agent mode ───────────────────────────────────────────
# An agent is this same binary started with NINEDEPLOY_AGENT=1 on another
# host. It exposes a small HTTP surface the core drives to run deploy
# operations there. Set these on the AGENT host, not on the core.
# NINEDEPLOY_AGENT=1
# NINEDEPLOY_AGENT_PORT=4600
# The sha256 of the agent token (the panel shows the raw token once, at
# enrolment). The agent never holds the raw value.
# NINEDEPLOY_AGENT_TOKEN=
# Self-enrolment only: the RAW token to announce with, when you want to choose
# it rather than let the agent generate one. Ignored once NINEDEPLOY_AGENT_TOKEN
# is set — that is the normal path, and it keeps the raw value off the agent.
# NINEDEPLOY_AGENT_RAW_TOKEN=
# Optional self-enrolment against the core, instead of pasting a token:
# NINEDEPLOY_MASTER_URL=https://panel.example.com
# NINEDEPLOY_ENROLMENT_TOKEN=
# NINEDEPLOY_NODE_NAME=
# NINEDEPLOY_ADVERTISE_HOST=
# Set on the CORE. Core→agent traffic is sealed (AES-256-GCM under a key
# derived from the shared token) whenever the agent advertises support, so
# neither the token nor the deployed service's secrets cross in cleartext.
# Whether an agent supports sealing is learned from an UNAUTHENTICATED probe,
# so the cleartext fallback is DISABLED by default: an agent that does not
# advertise sealing fails the operation instead of having its request (agent
# token + decrypted service secrets) sent in plaintext. Only an operator who
# still runs agents that cannot seal should opt in:
# NINEDEPLOY_AGENT_ALLOW_CLEARTEXT=1
# The stricter alias — refuses the fallback even when ALLOW_CLEARTEXT is set.
# NINEDEPLOY_AGENT_REQUIRE_SEALED=1