107 lines
5.0 KiB
Markdown
107 lines
5.0 KiB
Markdown
# Axolotl Telemetry Dashboard
|
|
|
|
Read-only administration UI for the existing `axolotl-telemetry` D1 database and
|
|
`axolotl-telemetry-errors` R2 bucket. It does not share routes or code with the public telemetry
|
|
collector.
|
|
|
|
## Local development
|
|
|
|
Mock authentication is accepted only when `NODE_ENV=development` and
|
|
`TELEMETRY_ADMIN_MOCK_AUTH=true` are both present.
|
|
|
|
Use the production D1 and R2 resources through Wrangler remote bindings while keeping authentication
|
|
local to the development server:
|
|
|
|
```powershell
|
|
$env:TELEMETRY_ADMIN_MOCK_AUTH='true'
|
|
$env:TELEMETRY_ADMIN_REMOTE_BINDINGS='true'
|
|
pnpm --filter @axolotl/telemetry-dashboard dev
|
|
```
|
|
|
|
Remote mode is read-only at the application layer: the Admin API issues only `SELECT` statements
|
|
and a single registered-object R2 `GET`. It never exposes Cloudflare credentials to the browser.
|
|
|
|
For deterministic fixture scenarios, leave `TELEMETRY_ADMIN_REMOTE_BINDINGS` unset:
|
|
|
|
```powershell
|
|
$env:TELEMETRY_ADMIN_MOCK_AUTH='true'
|
|
$env:TELEMETRY_ADMIN_MOCK_SCENARIO='normal'
|
|
pnpm --filter @axolotl/telemetry-dashboard dev
|
|
```
|
|
|
|
Supported deterministic scenarios are `normal`, `empty`, `api-error`, `no-sample`,
|
|
`budget-reached`, `unconfigured-auth`, and `forbidden`. All mock values are synthetic fixtures.
|
|
|
|
## Production deployment (Cloudflare Workers)
|
|
|
|
The dashboard runs on the `axolotl-telemetry-dashboard` Worker with the custom domain
|
|
`admin.axlmc.org`. It uses the native D1 and R2 bindings declared in `wrangler.toml`; no data
|
|
credentials are sent to the browser.
|
|
|
|
Do not deploy the dashboard until every item below is complete:
|
|
|
|
1. Create a GitHub OAuth App controlled by the `Axolotl-Launcher` organization. Use
|
|
`https://admin.axlmc.org` as its homepage and the callback URL shown by Cloudflare Zero Trust,
|
|
normally `https://<team-name>.cloudflareaccess.com/cdn-cgi/access/callback`.
|
|
2. Add GitHub as a Cloudflare Zero Trust identity provider using that Client ID and Client Secret.
|
|
Keep the Client Secret only in GitHub and Cloudflare.
|
|
3. Create a self-hosted Access application for `admin.axlmc.org` with an 8-hour session duration.
|
|
4. Create one Allow policy with `Include -> GitHub Organization -> Axolotl-Launcher`. Do not add a
|
|
bypass policy or a broader include rule.
|
|
5. Keep the Worker custom domain `admin.axlmc.org` bound to `axolotl-telemetry-dashboard`. The DNS
|
|
records for `axlmc.org` stay proxied through Cloudflare.
|
|
|
|
Build and deploy from `apps/telemetry-dashboard`:
|
|
|
|
```powershell
|
|
pnpm --filter @axolotl/telemetry-dashboard build
|
|
pnpm --filter @axolotl/telemetry-dashboard exec wrangler deploy
|
|
```
|
|
|
|
`nuxi build` uses Nitro's `cloudflare-module` preset by default and emits
|
|
`.output/server/index.mjs` plus `.output/public`, exactly what `wrangler.toml` references.
|
|
|
|
### Automatic deployment
|
|
|
|
`.github/workflows/deploy-telemetry-dashboard.yml` deploys on every push to `main` that touches
|
|
`apps/telemetry-dashboard/**`, and can also be triggered manually. It requires one repository
|
|
secret:
|
|
|
|
- `CLOUDFLARE_API_TOKEN`: an API token with Workers Scripts Edit and Workers Routes Edit
|
|
permission for the account that owns `axolotl-telemetry-dashboard`.
|
|
|
|
Do not add `[skip ci]` to commits that should reach production: GitHub Actions skips all workflows
|
|
for such commits, including this deployment.
|
|
|
|
### Cloudflare account usage check
|
|
|
|
The system page reports account-wide Workers, D1, and R2 usage through the GraphQL Analytics API.
|
|
Enable it once with two Worker secrets; secrets survive CI deploys because they live on the Worker,
|
|
not in the repository:
|
|
|
|
1. Create an API token at `dash.cloudflare.com` → My Profile → API Tokens with the
|
|
`Account Analytics: Read` permission for the account that owns the telemetry resources.
|
|
2. From `apps/telemetry-dashboard`, run
|
|
`pnpm exec wrangler secret put CLOUDFLARE_ANALYTICS_TOKEN` and paste that token.
|
|
3. Run `pnpm exec wrangler secret put CLOUDFLARE_ACCOUNT_ID` and paste the 32-character account ID.
|
|
|
|
The check stays fail-closed: without both values the row reports 尚未配置, and any dataset failure
|
|
only degrades the row. The token is used server-side for three read-only GraphQL queries per system
|
|
page load (Workers invocations 24h, D1 rows today, R2 operations 30d) and is never sent to the
|
|
browser.
|
|
|
|
### Unused Vercel target
|
|
|
|
An earlier Vercel project (`axolotl-telemetry-dashboard`) exists, but its `admin.axlmc.org` domain
|
|
was never pointed at Vercel and traffic is served by the Cloudflare Worker. The Nitro `vercel`
|
|
preset and `server/utils/vercel-data-source.ts` remain as an offline fallback and are not part of
|
|
the production path. Do not enable both targets for the same hostname.
|
|
|
|
Verify an unauthenticated request is intercepted by Cloudflare Access, then verify
|
|
`/api/admin/session` reports `dataSource: production` after authentication.
|
|
|
|
The server fails closed when Access or the remote data source configuration is absent. A production
|
|
build ignores the mock provider even if a mock environment variable is present. All Admin API D1
|
|
operations are restricted to `SELECT`/`WITH` queries, and R2 reads require an object key previously
|
|
registered in D1.
|