RMM OpenWrt Server
MVP backend for OpenWrt RMM.
Run
RMM_INSECURE_DEV_MODE=true go run ./server/cmd/rmm-server
Environment variables:
RMM_ADDR- listen address, default:8080RMM_DB_PATH- SQLite database path, defaultrmm.dbRMM_OPERATOR_PASSWORD- required password used only when the bootstrap administrator is first created; rotate it later in the account UIRMM_OPERATOR_TOKEN- optional emergency/API bearer tokenRMM_OPERATOR_USERNAME- web UI username, defaultadminRMM_PUBLIC_URL- trusted external base URL used in password recovery linksRMM_SMTP_HOST,RMM_SMTP_PORT,RMM_SMTP_USERNAME,RMM_SMTP_PASSWORD,RMM_SMTP_FROM- optional SMTP delivery for password recoveryRMM_SMTP_TLS_MODE-starttls(default),tls, ornonein insecure local mode onlyRMM_SMTP_SERVER_NAME- optional TLS server name overrideRMM_COOKIE_SECURE- defaults totrueoutside explicit development modeRMM_DEVICE_DOMAIN- wildcard device domain, for examplerouters.example.comRMM_DNS_SYNC_TOKEN- optional random bearer secret (at least 32 characters in production) for an authoritative DNS synchronizerRMM_ALLOW_LEGACY_ENROLLMENT- opt-in shared enrollment compatibility modeRMM_METRIC_RETENTION_DAYS- metric history retention, default30RMM_WEB_DIR- static web UI directory, defaultweb
Docker Compose
The repository includes a Compose stack with the RMM server and a reverse SSH tunnel sidecar:
docker compose up -d --build
See docs/docker-compose.md for router key installation and remote access setup.
MVP API
Agent API:
POST /api/agent/enrollPOST /api/agent/heartbeatPOST /api/agent/dns/updatePOST /api/agent/commands/nextPOST /api/agent/commands/{id}/result
Operator API:
-
POST /api/auth/login -
POST /api/auth/password-reset/request -
POST /api/auth/password-reset/confirm -
POST /api/auth/logout -
GET /api/auth/me -
PATCH /api/auth/profile -
POST /api/auth/change-password -
POST /api/auth/logout-all -
GET|POST /api/users(administrator only) -
PATCH /api/users/{id}(administrator only) -
POST /api/enrollment-grants -
GET /api/devices -
GET /api/dns/records -
GET|PATCH /api/devices/{id}/dns -
GET /api/devices/{id}/dns/history -
GET /api/events(authenticated SSE stream; the client reloads user-scoped data on change) -
GET /api/devices/{id} -
POST /api/devices/{id}/transfer -
POST /api/devices/{id}/commands -
GET /api/devices/{id}/commands -
GET /api/devices/{id}/commands/{command_id} -
POST /api/devices/{id}/commands/{command_id}/cancel -
GET /api/audit-events
The web UI uses revocable, server-side sessions. Each normal user only sees and controls devices enrolled with their own one-time grants. The optional bootstrap bearer token is administrator-scoped:
Changing a password keeps the current browser session and revokes the user's other sessions. The bootstrap environment password does not overwrite a password stored in SQLite after a container restart.
Authorization: Bearer <RMM_OPERATOR_TOKEN>
See KeenDNS-like cloud mode for wildcard DNS, wildcard TLS, and the
isolated LuCI access flow. Browser requests to an unavailable LuCI route receive a safe HTML
status page while API clients continue to receive JSON. The reverse proxy waits up to 15 seconds
for LuCI response headers before returning 504 Gateway Timeout.