Environment reference
Every variable the hub, the dashboard and the agent read.
.env is what the stack needs to boot and connect. What is tuned while it
runs — concurrency, intervals, retention, heartbeat, the monitoring ceilings —
lives in Settings → Tuning and is not an env var. Values that moved there
are ignored in silence if left behind in .env.
With docker compose these come from .env at the repo root (copy
.env.example). On Coolify the SERVICE_* ones are generated and shown in the
resource's Environment tab.
URLs
| Variable | Default | What it is |
|---|---|---|
EDGE_PORT | 8090 | Host port the edge publishes, plain HTTP. Your proxy terminates TLS and forwards here. Compose only. |
MAGNEMITE_PUBLIC_URL | — | Base URL handed to agents. Artifact URLs are built from it, so it must be what the boxes can reach. On Coolify it defaults to the edge's generated domain (SERVICE_URL_EDGE); set it to override a stale one. |
MAGNEMITE_DASHBOARD_URL | MAGNEMITE_PUBLIC_URL | The dashboard's own origin — auth callbacks and notification links. On Coolify it defaults to the web service's generated domain (SERVICE_URL_WEB), which is a different host from the agents' one. |
BETTER_AUTH_URL | MAGNEMITE_DASHBOARD_URL | Only when neither of the above is the right origin for auth callbacks. A bare host with no scheme is accepted. |
HUB_URL | http://hub:3001 | Where the dashboard reaches the hub's internal API, over the compose network. |
Database
| Variable | Default | What it is |
|---|---|---|
DATABASE_URL | — | Required everywhere: no deployment runs a database of its own. Resolved from inside the containers, so not a host-published port. |
DB_PROVIDER | mysql | mysql (also covers MariaDB) or postgresql. Must match DATABASE_URL; changing it needs a rebuild, not a restart. |
Auth and the first admin
| Variable | Default | What it is |
|---|---|---|
AUTH_SECRET | — | Signs Better Auth cookies. openssl rand -base64 32. Coolify: SERVICE_BASE64_64_AUTHSECRET. |
ADMIN_EMAIL | [email protected] | Login identifier. Nothing is sent to it, but it must be well-formed — admin@localhost is rejected. |
ADMIN_PASSWORD | — | Admin password. Coolify: SERVICE_PASSWORD_ADMIN. |
Both live on the hub service: the hub syncs the admin account to them on every boot, and there
is no .env inside the container. Changing ADMIN_PASSWORD and restarting the hub is the way
back in if the login is lost. Changing ADMIN_EMAIL renames that one account rather than adding
another, so the old address stops working as a login.
Hub
| Variable | Default | What it is |
|---|---|---|
HUB_PORT · HUB_HOST | 3001 · 0.0.0.0 | Where the hub listens. |
HUB_INTERNAL_SECRET | — | Shared secret for web → hub internal calls. Coolify: SERVICE_PASSWORD_HUBSECRET. |
ARTIFACT_DIR | /data/artifacts | Where cached bundles live. Must match the volume Caddy mounts as /srv/artifacts. |
SERVE_ARTIFACTS | false | Serve /files/* from Node. true only for local development without Caddy. |
AGENT_AUTO_UPDATE | true | Tell boxes on an older build to update themselves. |
AGENT_BIN_DIR | /app/agent-bin | Where the hub image keeps those binaries. |
LOG_LEVEL | info in prod | pino level: trace … fatal. PRISMA_LOG=1 logs every query — development only. |
Web push
Optional; see Notifications. Without a keypair web push is simply unavailable, and the Notifications tab says so rather than offering a button that cannot work.
| Variable | Default | What it is |
|---|---|---|
VAPID_PUBLIC_KEY | — | Handed to the browser at subscribe time. Needed by both the hub and the web. |
VAPID_PRIVATE_KEY | — | Signs each push. Hub only — it must never reach the browser. |
VAPID_SUBJECT | mailto:[email protected] | Contact address for the push service. A mailto: or https: URL; required by the spec. |
Generate the pair once:
npx web-push generate-vapid-keysThe keypair is identity, not a setting
A push service only accepts a message signed by the key it saw when the browser subscribed, so
regenerating the pair silently unsubscribes every browser that already opted in. Back it up with
AUTH_SECRET, and change it only when you mean to start over.
The Discord webhook, the ntfy topic and which events go where are not here — those are set on Settings → Notifications, because they are changed while running rather than at boot.
Rotom
Optional; see Rotom.
| Variable | What it is |
|---|---|
ROTOM_ENABLED | false by default. |
ROTOM_URL | RotomNG's HTTP listener, usually :7072. /api is appended. |
ROTOM_SECRET | Matches secret under http_listener in the Rotom config. |
ROTOM_BASIC_USERNAME · ROTOM_BASIC_PASSWORD | BasicAuth for a proxy in front of Rotom. |
The agent's own configuration
Per-box, in /data/adb/magnemite/config.json or as flags:
| Flag | Config key | What it is |
|---|---|---|
-server | serverUrl | The hub URL — MAGNEMITE_PUBLIC_URL, never the dashboard's. |
-enroll-token | enrollmentToken | Used once on first run, then deleted from the config. |
-name | name | Friendly name for the box. |
-config | — | Path to config.json. |
-work-dir | — | Scratch directory for downloads and extraction. |
-serial | serial | Report this serial instead of ro.serialno. Needed on Redroid. |
-reboot-command | rebootCommand | What a reboot from the hub runs. Default reboot. |
-fake-root | — | Simulate an Android box. See testing without hardware. |
-fake-serial | — | Serial to report in -fake-root mode. |
-version | — | Print the agent version and exit. |
Not env vars
Version sources are rows in the database (Settings → Version sources). Automatic rollouts, canary, soak, attempts, backoff, cooldown and the rollout window are per app target (Settings → Apps). Everything fleet-wide and numeric — concurrency, stall timeout, heartbeat, offline timeout, sample interval, retention, monitoring graces and ceilings — is in Settings → Tuning. The Discord webhook, the ntfy topic and the rest of where notifications go are in Settings → Notifications.