Add be9700-api: TP-Link BE9700 router API proxy + Scalar docs

This commit is contained in:
2026-06-29 12:23:15 -07:00
parent 19fa1c7821
commit bf09e224c9
6 changed files with 145 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
# be9700-api — Build Notes
## Image
`git.alexzaw.dev/alexz/be9700-api:<tag>`
## Source
`/home/alexz/be9700-api` (also mirrored to `https://git.alexzaw.dev/alexz/be9700-api`)
The Dockerfile lives in the root of the source directory alongside `server.js`.
## Architecture
- **amd64 only** — the app is pure Node.js (no native addons) but the image is
only built and tested on the amd64 host. Add `--platform linux/arm64` to the
build command and push a separate tag to add arm64 support.
## Security
`.dockerignore` excludes `.env`, `.env.*`, `.git`, `scripts/`, `*.log`, `*.curl`,
`network-captures.js`. The image contains no router credentials.
## Build
```bash
# From this directory:
bash build.sh
# Or with overrides:
IMAGE_TAG=1.0.1 bash build.sh --no-cache
```
Requires the Docker daemon to be authenticated to `git.alexzaw.dev`.

View File

@@ -0,0 +1,26 @@
#!/bin/bash
# Build and push the be9700-api Docker image from the source in /home/alexz/be9700-api.
# The Dockerfile lives alongside the source (not in this build/ dir).
set -euo pipefail
IMAGE_NAME="${IMAGE_NAME:-git.alexzaw.dev/alexz/be9700-api}"
IMAGE_TAG="${IMAGE_TAG:-1.0.0}"
SOURCE_DIR="${SOURCE_DIR:-/home/alexz/be9700-api}"
echo "==> Building ${IMAGE_NAME}:${IMAGE_TAG}"
docker build "$@" \
-t "${IMAGE_NAME}:${IMAGE_TAG}" \
-t "${IMAGE_NAME}:latest" \
"${SOURCE_DIR}"
echo "==> Pushing ${IMAGE_NAME}:${IMAGE_TAG}"
docker push "${IMAGE_NAME}:${IMAGE_TAG}"
echo "==> Pushing ${IMAGE_NAME}:latest"
docker push "${IMAGE_NAME}:latest"
echo ""
echo "Done. To update on Runtipi:"
echo " cd /etc/runtipi/repos/runtipi && sudo git add . && sudo git commit -m 'be9700-api: bump' && sudo git push origin main"
echo " sudo /etc/runtipi/runtipi-cli appstore update"
echo " sudo /etc/runtipi/runtipi-cli app update be9700-api:runtipi"

View File

@@ -0,0 +1,21 @@
{
"$schema": "https://schemas.runtipi.io/app-info.json",
"name": "BE9700 Router API",
"id": "be9700-api",
"available": true,
"short_desc": "Stateless proxy + Scalar API docs for the TP-Link BE9700 WiFi 7 router",
"author": "alexz",
"port": 8347,
"categories": ["network", "utilities"],
"description": "A stateless Node.js proxy server that exposes the TP-Link BE9700 WiFi 7 router's internal API as a clean REST surface with interactive Scalar docs at /docs. Credentials are never stored — callers pass X-Router-Host and X-Router-Password (or X-Router-Session) per request. Covers 203 endpoints: wireless bands (2.4 GHz / 5 GHz / 6 GHz), LAN/DHCP, NAT, UPnP, time, and diagnostics.",
"tipi_version": 1,
"version": "1.0.0",
"source": "https://git.alexzaw.dev/alexz/be9700-api",
"website": "https://git.alexzaw.dev/alexz/be9700-api",
"exposable": true,
"dynamic_config": true,
"no_gui": false,
"form_fields": [],
"supported_architectures": ["amd64"],
"min_tipi_version": "4.0.0"
}

View File

@@ -0,0 +1,24 @@
{
"$schema": "https://schemas.runtipi.io/dynamic-compose.json",
"schemaVersion": 2,
"services": [
{
"name": "be9700-api",
"image": "git.alexzaw.dev/alexz/be9700-api:1.0.0",
"isMain": true,
"internalPort": 3000,
"environment": [
{ "key": "PORT", "value": "3000" },
{ "key": "TZ", "value": "${TZ}" },
{ "key": "NODE_ENV", "value": "production" }
],
"healthCheck": {
"test": "wget -qO- http://127.0.0.1:3000/ >/dev/null 2>&1 || exit 1",
"interval": "30s",
"timeout": "5s",
"retries": 3,
"startPeriod": "15s"
}
}
]
}

View File

@@ -0,0 +1,40 @@
# BE9700 Router API
A stateless Node.js proxy and interactive API documentation server for the
**TP-Link BE9700 WiFi 7** router.
## What it does
- Exposes the router's internal API as a clean, resource-oriented REST surface
(`/api/*`) covering **203 endpoints** across wireless bands (2.4 GHz / 5 GHz /
6 GHz), LAN/DHCP, NAT, UPnP, system time, and diagnostics.
- Serves **interactive Scalar API docs** at `/docs` — explore and try every
endpoint directly in the browser.
- Returns the OpenAPI 3.1 specification at `/openapi.json` for use with any
compatible tooling.
- Health/status JSON at `/`.
## Stateless header-auth model
No router credentials are stored in the container or in Runtipi form fields.
Every request to `/api/*` must carry:
| Header | Purpose |
|--------|---------|
| `X-Router-Host` | Router IP or hostname (e.g. `192.168.0.1`) |
| `X-Router-Password` | Router admin password (for fresh sessions) |
| `X-Router-Session` | Reuse a session token returned by a previous call (JSON) |
This means the container itself holds no secrets and is safe to expose via
Traefik without any additional auth middleware — just use the API from clients
that supply the headers.
## Quick start
Once installed, open the **Scalar docs** at `http://<your-server>:8347/docs`
and authenticate each request with the `X-Router-Host` and
`X-Router-Password` headers.
## Source
`https://git.alexzaw.dev/alexz/be9700-api`

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB