Every operator-tunable setting on a DAPPS node has three configuration surfaces:
A persisted default in the SQLite database, seeded on first start.
An environment variable, of the form DAPPS_SCREAMING_SNAKE_NAME, which overrides the persisted default at first start and updates the persisted row.
The dashboard's /Config form (or POST /Config REST API), which writes a new value to the persisted row at any time.
For runtime-changeable knobs (probing on/off, fragment threshold, airtime budget, etc.), the dashboard is the right surface - changes pick up without a restart. For startup-only knobs (callsign, packet-node host/port, MQTT port, dashboard URL), the env var is the right surface - they're read once at boot.
Walks the persisted systemoptions table and prints DAPPS_SCREAMING_SNAKE=value pairs for every set knob, without booting the host. Useful when the daemon won't start and you need to see what state it'd boot into.
Your callsign with SSID, e.g. M0LTE-1. Refuses to start on the placeholder.
Node host
DAPPS_NODE_HOST
localhost
TCP host of your packet node (BPQ, XRouter, etc.).
Node bearer
DAPPS_NODE_BEARER
agw
Which host protocol DAPPS speaks to the packet node: agw (BPQ, Direwolf, AGWPE, ...) or rhpv2 (XRouter, future RHPv2-capable BPQ). See Connect a node.
AGW port
DAPPS_AGW_PORT
8000
TCP port the packet node's AGW interface listens on. Used when Node bearer = agw.
RHPv2 port
DAPPS_RHP_PORT
9000
TCP port the packet node's RHPv2 listener is on. Used when Node bearer = rhpv2.
RHPv2 user
DAPPS_RHP_USER
empty
Username for RHPv2 authentication. Leave empty if your packet node accepts unauthenticated RHPv2.
RHPv2 password
DAPPS_RHP_PASS
empty
Password matching the RHPv2 user.
Default bearer port
DAPPS_DEFAULT_BEARER_PORT
0
Bearer port (0-indexed) for outbound sessions when a neighbour has no per-row override. For AGW this is the AGW port byte; for RHPv2 DAPPS adds 1 internally to derive XRouter's 1-indexed PORT=N name.
Minimum hours between consecutive routes pulls from the same neighbour. The piggyback gate skips gossip if the previous pull is younger than this. 0 disables route gossip entirely.
The session-protocol version is the suffix on the prompt - DAPPSv1> today; DAPPSv2> for any future incompatible cut. The policy:
Forward-compatible additions stay on the current version. New optional ihave headers and new commands ride the existing prompt; receivers ignore unknown headers and respond ? to unrecognised commands.
Bump the prompt on any incompatible wire change. A clean version cut beats sticking a patch on v1 and hoping every implementation interprets it the same way.
Newer implementations should speak older versions for one-way compatibility.
The UDP / future MeshCore datagram bearer codec versions independently - different format, different schedule.
Pre-shipping caveat: while DAPPS has no non-author operators on the air, breaking changes to either format are still fair game without a version bump. The cost of compatibility tape that nobody benefits from is real. The policy fully kicks in when the first independent operator picks DAPPS up.
Everything is in the SQLite database at /var/lib/dapps/dapps.db (Linux/systemd) or data/dapps.db (run-from-anywhere). The file is the only state worth backing up.