# Environment variables

Every variable 3pm, its modules, its SDKs, its installer and the fleet
backend read or set. Grouped by who reads it. Defaults are the values used
when the variable is unset or empty.

## Set by you, read by the `3pm` CLI and daemon

| Variable | Default | Effect |
|---|---|---|
| `THREEPM_HOME` | `~/.3pm` | The home: sockets (`rpc.sock`, `pub.sock`, `ctl.sock`, `host.sock`), `3pm.pid`, `3pm.log`, `logs/`, `pids/`, `dump.json`, `config.toml`, `modules/`, `actions/`, `agent/`. One daemon per home. Like pm2's `PM2_HOME` (which 3pm does **not** read). |
| `THREEPM_USERS_DIR` | `/var/lib/3pm/users` | Where a root daemon puts the homes of the accounts it hosts (`[users] allow` in `config.toml`); a client finds its hosted home there. |
| `THREEPM_MODULES_DIR` | `<exe dir>/modules`, then `<exe dir>/../lib/3pm/modules` | Where the bundled modules (`serve`, `agent`) are looked up; first hit wins. |
| `THREEPM_SPAWN_TIMEOUT_MS` | `3000` | How long a client waits for an auto-spawned daemon to be ready. |
| `THREEPM_JSON` | unset | `1` = same as `--json`: machine output on stdout (modules too). |
| `THREEPM_LOG` | `info` | The daemon's own log level (`3pm.log`), a `tracing` filter: `warn`, `debug`, … |
| `THREEPM_LOG_MAX_SIZE` | `20M` | Log rotation threshold per file; `0` turns rotation off. Per app `log_max_size` > env > `config.toml` > default. |
| `THREEPM_LOG_MAX_FILES` | `5` | Rotated files kept. |
| `THREEPM_LOG_MAX_DAYS` | `14` | Rotated files older than this are removed. |
| `THREEPM_LOG_COMPRESS` | off | `1`/`true`/`yes`/`on`: gzip rotated files. |
| `THREEPM_METRICS_INTERVAL_MS` | `1000` | Per-process CPU/memory sampling period (`3pm ls`). |
| `THREEPM_PROCESS_TREE` | on | `off`: sample the spawned pid alone instead of its whole process tree. |
| `THREEPM_HOSTMETRICS_INTERVAL_MS` | `1000` | Host agent fast tier (CPU, memory, load, network and disk rates). |
| `THREEPM_HOSTMETRICS_MEDIUM_MS` | `10000` | Host agent medium tier (process table, TCP states, sensors, GPUs, mounts, RAID). |
| `THREEPM_HOSTMETRICS_SLOW_MS` | `300000` | Host agent slow tier (NTP offset, host identity). |
| `THREEPM_NTP_SERVER` | `pool.ntp.org` | Clock-offset probe server; empty disables the probe. |

Variables of the daemon are read when it starts: set them on the command
that spawns it (`THREEPM_LOG_MAX_SIZE=50M 3pm ls`), then `3pm update` or
`3pm kill` to apply them to a running one.

## Injected by the daemon into every app it starts

| Variable | Value | Use |
|---|---|---|
| `THREEPM_INSTANCE` | `0` … `N-1` | The instance number of this process within its app (`-i N`). |
| `NODE_APP_INSTANCE` | same | pm2 compatibility. |
| `THREEPM_ID` | integer | The process id (`id` column of `3pm ls`). |
| `THREEPM_GEN` | integer | The incarnation, bumped at every restart; the control channel refuses a stale one. |
| `THREEPM_BOOT` | 16 hex digits | The daemon lineage, kept across `3pm update` handoffs; tells a child of this daemon from a survivor of a previous one. |
| `THREEPM_CTL_SOCK` | path | The control socket: `hello` (with id + gen), `ready` (`--wait-ready`), `shutdown` (`--shutdown-with-message`), and the application metrics, events and actions of the SDKs. Its absence makes every SDK call a no-op. |

These four — `THREEPM_CTL_SOCK`, `THREEPM_ID`, `THREEPM_GEN`, `THREEPM_BOOT` —
are inherited by every descendant, which is how 3pm attributes a process
tree to its app.

## Read by module commands (`3pm serve`, `3pm link`, your own)

| Variable | Set by | Meaning |
|---|---|---|
| `THREEPM_EXE` | the CLI | Path of the `3pm` binary. |
| `THREEPM_MODULE_DIR` | the CLI | The module's directory. |
| `THREEPM_HOME`, `THREEPM_JSON` | the CLI | As above. |

### `serve` module (pm2 `serve` names accepted too)

| Variable | Default | pm2 name |
|---|---|---|
| `THREEPM_SERVE_PATH` | `.` | `PM2_SERVE_PATH` |
| `THREEPM_SERVE_PORT` | `8080` | `PM2_SERVE_PORT` |
| `THREEPM_SERVE_HOST` | `0.0.0.0` | `PM2_SERVE_HOST` |
| `THREEPM_SERVE_SPA` / `THREEPM_SERVE_FTP` | `false` | `PM2_SERVE_SPA` / `PM2_SERVE_FTP` |
| `THREEPM_SERVE_HOMEPAGE` | `/index.html` | `PM2_SERVE_HOMEPAGE` |
| `THREEPM_SERVE_BASIC_AUTH_USERNAME` / `_PASSWORD` | none (both or neither) | `PM2_SERVE_BASIC_AUTH_*` |

### `agent` module (`3pm link`, the fleet link)

| Variable | Default | Meaning |
|---|---|---|
| `THREEPM_LINK_CLUSTER` | — | Cluster key `3pmc_…` when not given as an argument (provisioning scripts). |
| `THREEPM_LINK_TOKEN` | — | Enrollment token `3pmk_…`. |
| `THREEPM_LINK_SERVER` | `wss://fleet.edgecr4ft.net` | Backend address; wins over the argument. |
| `THREEPM_LINK_INSECURE` | off | `1`: accept a non-loopback `ws://` or any TLS certificate. |
| `THREEPM_AGENT_STATE_DIR` | `<home>/agent` | `node.key`, `node.crt`, `ca.pub`, `link.toml`, `session.json`, `data.sock`. |
| `THREEPM_AGENT_INTERVAL_MS` | `1000` (floor 200) | Telemetry period. |
| `THREEPM_AGENT_FULL_EVERY_S` | `60` | Period of the full host frame; the backend's `welcome` overrides it. |
| `THREEPM_AGENT_NAME` | `agent` | Name of the supervised agent app. |
| `THREEPM_AGENT_LOG` | `info` | Agent log level (set it on the `agent` app). |

## Read by the SDKs (`@3pm/api`, `threepm-io`, `threepm_io.hpp`)

| Variable | Meaning |
|---|---|
| `THREEPM_CTL_SOCK`, `THREEPM_ID`, `THREEPM_GEN` | Injected by the daemon (above): where and as whom to connect. |
| `THREEPM_DATA_SOCK` | Fleet calls (`io.call` / `io.open` / `io.stream`, Node): the linked agent's data socket; default `<home>/agent/data.sock`. Set it on both the agent app and your app to move the socket. |
| `THREEPM_IO_DEBUG` | `1`: trace to stderr every call the SDK refuses or drops. |
| `THREEPM_IO_MAIN` | Written by the Node SDK in its own environment (`<id>.<gen>.<pid>`) so child processes do not also claim the `main` source. Do not set it. |
| `THREEPM_HOME` | Node client (`ThreePM`): the daemon to talk to. |
| `THREEPM_BIN` | Node client: the `3pm` binary used to auto-spawn a daemon (default `3pm` on `PATH`). |

## Read by `install.sh`

| Variable | Default | Effect |
|---|---|---|
| `THREEPM_VERSION` | latest | Version to install (`sh -s -- 0.3.0` does the same). |
| `THREEPM_INSTALL` | `~/.3pm` | Install directory (`bin/3pm`, `modules/`). |
| `THREEPM_CDN_URL` | `https://3pm.edgecr4ft.net` | Download base. |
| `THREEPM_NO_MODIFY_PATH` | unset | Set: do not edit shell rc files. |
| `THREEPM_HOME` | `~/.3pm` | Where to look for a running daemon to hand off to the new binary. |

## Read by `3pm-backend` (the fleet backend)

Every flag of `3pm-backend` has an environment variable: `--listen` is
`THREEPM_BACKEND_LISTEN`, `--metrics-url` is `THREEPM_BACKEND_METRICS_URL`,
and so on. The full list with defaults is in [backend/cli.md](backend/cli.md).

| Variable | Default | Meaning |
|---|---|---|
| `THREEPM_BACKEND_LISTEN` | `127.0.0.1:9616` | Bind address. |
| `THREEPM_BACKEND_ADVERTISE` | hostname + port | What agents connect to (goes into the pasted `3pm link` line), e.g. `wss://fleet.example.com`. |
| `THREEPM_BACKEND_DB` | `3pm-backend.sqlite` | SQLite database. |
| `THREEPM_BACKEND_DATA_DIR` | `<db>.d/` | Artifacts left by actions (profiles, dumps) and blobs. |
| `THREEPM_BACKEND_DEV` | off | Clear-text HTTP/WS, localhost advertise allowed, open registration. |
| `THREEPM_BACKEND_REGISTRATION` | `closed` | `closed`: first account only; `open`: anyone. |
| `THREEPM_BACKEND_COOKIE_SECURE` | off | `Secure` session cookie (behind HTTPS). |
| `THREEPM_BACKEND_TRUST_PROXY` | none | Peers whose `X-Forwarded-For` is believed. |
| `THREEPM_BACKEND_METRICS_URL` | none | VictoriaMetrics base URL; unset = telemetry not persisted. |
| `THREEPM_BACKEND_EVENTS_URL` | none | VictoriaLogs base URL for events. |

## Internal (tests, handoff) — do not set

`THREEPM_READY_FD`, `THREEPM_INHERITED_FDS`, `THREEPM_FLEET_SECRET`,
`THREEPM_HANDOFF_*`, `THREEPM_TEST_*`, `THREEPM_E2E_*`: plumbing between a
daemon and its successor, the agent gate, or the test harness.
