Files
2026-07-11 10:44:42 -05:00

185 lines
5.6 KiB
Markdown

# GracePress MeshPress Bridge
Small local HTTP bridge between WordPress/MeshPress and MeshCentral.
The bridge runs beside MeshCentral and uses MeshCentral's official `meshctrl` tool to read device groups and devices. WordPress talks to this bridge instead of trying to speak MeshCentral websocket protocol directly.
## Endpoints
- `GET /api/health`
- `GET /api/status`
- `GET /api/self-test`
- `GET /api/groups`
- `GET /api/users`
- `GET /api/events?limit=50`
- `GET /api/serverinfo`
- `GET /api/devices`
- `GET /api/device/:nodeId`
- `GET /api/fleet`
- `POST /api/push-now`
- `POST /api/cache/clear`
- `GET /api/link/desktop/:nodeId`
- `GET /api/link/terminal/:nodeId`
- `GET /api/link/files/:nodeId`
- `GET /api/link/:mode/:nodeId?link_mode=both`
- `GET /api/agent-links/:groupId`
- `POST /api/groups/create`
- `POST /api/groups/edit`
- `POST /api/groups/remove`
- `POST /api/groups/add-user`
- `POST /api/groups/remove-user`
- `POST /api/invite-link`
- `POST /api/device/message`
- `POST /api/device/toast`
- `POST /api/action`
All endpoints require `Authorization: Bearer TOKEN`. If `MESHPRESS_BRIDGE_TOKEN` is empty, protected requests are rejected.
`/api/action` is intentionally locked down for now. It returns a clear unsupported-command response until each broad remote-command workflow is whitelisted and tested.
Provisioning and device-command endpoints require:
```bash
MESHPRESS_ALLOW_COMMANDS="1"
```
Without that flag the bridge will read MeshCentral state but refuse provisioning actions.
## Install
```bash
cd /storage/meshcentral-workspace/bridge/meshpress-bridge
sudo ./install.sh
sudo nano /etc/gracepress/meshpress-bridge.env
pm2 restart gp-meshpress-bridge
```
## Required Config
```bash
MESHPRESS_BRIDGE_PORT="3099"
MESHPRESS_BRIDGE_BIND="127.0.0.1"
MESHPRESS_BRIDGE_TOKEN="generated-secret"
MESHPRESS_ALLOWED_IPS=""
MESHPRESS_AUTH_WINDOW_SECONDS="900"
MESHPRESS_AUTH_MAX_FAILURES="30"
MESHCTRL_URL="wss://127.0.0.1"
PUBLIC_MESH_URL="https://mesh.yourdomain.com"
MESHCTRL_USER="admin"
MESHCTRL_PASS=""
MESHCTRL_DOMAIN=""
MESHCTRL_LOGIN_KEY_FILE="/etc/gracepress/meshcentral-login.key"
MESHCTRL_PATH=""
MESHCTRL_IGNORE_CERT="0"
MESHPRESS_LINK_HIDE=""
MESHPRESS_LINK_MODE="gotonode"
MESHPRESS_ALLOW_COMMANDS="0"
WP_DOMAIN="https://christp2p.com"
WP_API_KEY="same-token-used-in-meshpress"
MESHPRESS_PUSH_INTERVAL_SECONDS="3600"
MESHPRESS_PUSH_EVENTS="1"
```
If auto-detection cannot find `meshctrl`, set `MESHCTRL_PATH` to the full path of `meshctrl.js`.
When `WP_DOMAIN` and `WP_API_KEY` are set, the bridge pushes fleet snapshots to WordPress at startup and then every hour.
When `MESHPRESS_PUSH_EVENTS` is enabled, selected bridge lifecycle events are posted to MeshPress so WordPress can record them through OmniLog.
## Public Exposure Hardening
Do not expose port `3099` to the public internet without firewall/VPN controls. Preferred options:
1. Bind to localhost and proxy privately:
```bash
MESHPRESS_BRIDGE_BIND="127.0.0.1"
```
2. Bind to a Tailscale address only:
```bash
MESHPRESS_BRIDGE_BIND="100.x.y.z"
```
3. If the bridge must listen on all interfaces temporarily, restrict source IPs at both the firewall and app layer:
```bash
MESHPRESS_BRIDGE_BIND="0.0.0.0"
MESHPRESS_ALLOWED_IPS="WORDPRESS_SERVER_IP,YOUR_ADMIN_IP"
```
The app-layer allowlist only accepts exact IP addresses. It is a backstop, not a replacement for firewall rules.
## Diagnostics
Use MeshPress > Diagnostics & Manual Actions first. It calls these bridge endpoints:
```bash
curl -H "Authorization: Bearer TOKEN" http://127.0.0.1:3099/api/health
curl -H "Authorization: Bearer TOKEN" http://127.0.0.1:3099/api/version
curl -H "Authorization: Bearer TOKEN" http://127.0.0.1:3099/api/status
curl -H "Authorization: Bearer TOKEN" http://127.0.0.1:3099/api/self-test
curl -H "Authorization: Bearer TOKEN" http://127.0.0.1:3099/api/groups?refresh=1
curl -H "Authorization: Bearer TOKEN" http://127.0.0.1:3099/api/devices?refresh=1
```
`/api/self-test` verifies the bridge can find `meshctrl`, has an auth method, has a public MeshCentral URL, and can list device groups and devices.
For direct session links, test both URL styles:
```bash
curl -H "Authorization: Bearer TOKEN" "http://127.0.0.1:3099/api/session-links/NODEID"
curl -H "Authorization: Bearer TOKEN" "http://127.0.0.1:3099/api/link/console/NODEID?link_mode=all"
```
To trigger a catalog-managed bridge update from MeshPress admin or curl:
```bash
curl -X POST -H "Authorization: Bearer TOKEN" http://127.0.0.1:3099/api/update-now
```
To test the first provisioning path, enable commands and create a temporary group:
```bash
curl -X POST \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"MeshPress Test Group","description":"Manual bridge validation"}' \
http://127.0.0.1:3099/api/groups/create
```
## MeshCentral Auth
The bridge supports either a MeshCentral login key file or a dedicated integration username/password.
For username/password auth, set:
```bash
MESHCTRL_USER="your-generated-integration-user"
MESHCTRL_PASS="your-generated-integration-password"
```
If `MESHCTRL_LOGIN_KEY_FILE` exists, the bridge will prefer it. If the file does not exist and `MESHCTRL_PASS` is set, it will use username/password auth.
## MeshCentral Login Key Option
On the MeshCentral server:
```bash
cd /opt/meshcentral
sudo node node_modules/meshcentral --loginTokenKey > /etc/gracepress/meshcentral-login.key
sudo chmod 600 /etc/gracepress/meshcentral-login.key
```
MeshCentral must have login tokens enabled in `meshcentral-data/config.json`:
```json
{
"settings": {
"allowLoginToken": true
}
}
```
Restart MeshCentral after changing config.