Provider Ping
Source catalog · Knowledge graph
Facts
| Fact | Value |
|---|---|
| Status | dormant |
| Hosting platform | vps |
| Repository | https://github.com/meta4m/provider-ping |
| Tech stack | language: typescript, framework: nextjs, ui: react, styling: tailwindcss, ui_kit: shadcn-ui, animation: framer-motion, data_fetching: tanstack-query, validation: zod, crypto: libsodium, auth: jose, charts: recharts, package_manager: pnpm, containerization: docker |
| Tags | llm, monitoring, self-hosted, uptime, status-dashboard, encryption |
| Last audited | 2026-09-15 |
| Upstream dependencies | None declared |
| Downstream dependencies | None declared |
Secrets manifest
Key names and metadata only. Encrypted records are available in this project’s vault below.
No secrets declared in this project’s manifest.
Overview
Project Overview: Provider Ping
1. Executive Summary
- Mission: Single-admin, self-hosted dashboard for monitoring LLM/inference provider uptime and surface area — scheduled pings against provider health endpoints with green/red status, latency sparklines, 24-hour uptime %, live model lists, and balance/credits, all with no external services (no Postgres, no Redis, no cloud account).
- Target Audience: Solo operators self-hosting on a single VPS or home server who run workloads across multiple LLM providers and want one pane of glass for provider health, latency, and quota surface.
- Primary Maintainer: The operator (meta4m) — solo developer; v1 was built end-to-end by the MiniMax M3 model inside FreeBuff per the README preface, with issues routed to iullah@gmail.com.
2. Current Status & Roadmap
- Lifecycle State:
dormant— v1.0.0 “initial public release” plus SECURITY.md landed 2026-07-05 (3 commits total, 2026-07-04 → 2026-07-05) with no activity in the ~10 weeks since the audit. - Ongoing work: none visible.
docs/HANDOFF.md(same date) records unresolved issues — an app “stuck at login” investigation, pre-existingtscerrors inauto-ping-control.tsx, no/api/healthendpoint, no regression test for the secrets race — and the README defers chat-test streaming, >24 h history graphs, webhooks, auto-derived kinds, and multi-user to a v2 that has not started.
3. Core Capabilities
- 15+ prebuilt providers seeded in
data/seed.json(OpenAI, Groq, Mistral, Together, OpenRouter, DeepSeek, Cohere, xAI, Fireworks, Perplexity, Anthropic, Google Gemini, Replicate, Ollama, vLLM) plus a custom OpenAI-compat slot; host auto-detected from the Base URL. - Scheduled + manual pings: 60 s dashboard auto-ping, a Ping all sweep, and a server-side cron scheduler booted by
instrumentation.ts(pause/config endpoints under/api/ping-scheduler/*); every ping appended todata/pings/<id>.jsonl. - Status UI (
components/dashboard/): animated status dots with last HTTP status and latency, 30-ping sparklines, 24 h uptime %, model-kind pills, provider cards/rows. - Models + balance surfaces: live per-provider model lists (Gemini
supportedMethods, Ollama parameter sizes, OpenRouter context windows) and balance/credits for OpenAI, OpenRouter, Together, Replicate. - Encrypted at rest: provider API keys sealed with libsodium XChaCha20-Poly1305 (secretbox) over
providers.jsonwith a per-install salt; list views expose only an 8-hex BLAKE2b fingerprint, and the full key leaves the server only via the authenticatedreveal-keyendpoint. - Single-admin auth: first-run
/setupflow, scrypt-hashed password (OWASP 2024 params) indata/secrets.json(chmod 600), jose JWT in an HttpOnly cookie; Edge middleware does a presence-only cookie check with real verification on Node. - Docker-friendly: multi-stage non-root image (uid 1001) with a
/loginhealthcheck and a compose file persisting to thepp-datavolume.
4. Key References
- Repository: meta4m/provider-ping
- Production URL: none evidenced — the product is deliberately self-hosted (VPS/home server via
pnpm startor Docker); no deployed instance is referenced anywhere in the repo. - Architecture Docs:
architecture.md· Deployment Guide:deployment.md
Architecture
Architecture & System Design: Provider Ping
1. System Topology
graph TD Admin[Admin browser] --> MW["middleware.ts<br/>Edge: cookie presence check"] MW --> Pages["Next.js App Router<br/>/setup · /login · dashboard"] Pages --> API["API routes: auth, providers CRUD,<br/>ping / models / balance / reveal-key, ping-scheduler"] API --> Sched["lib/server-scheduler.ts<br/>cron sweep booted by instrumentation.ts"] API --> Reg["lib/providers/registry.ts<br/>Anthropic · Gemini · Replicate · Ollama · OpenAICompat"] Sched --> Reg Reg --> Up["15+ external provider APIs<br/>incl. local Ollama / vLLM"] API --> Store["lib/storage.ts<br/>encrypted providers.json + pings/*.jsonl"] Store --> Sec["lib/secrets-store.ts<br/>data/secrets.json"]2. Core Components & Subsystems
- App Router UI (
app/,components/): dashboard page with provider cards/rows, status dots, sparklines;/setupand/loginflows; TanStack Query polling wrapper; Framer Motion animations; shadcn/ui + Tailwind v4. - API layer (
app/api/):auth/{login,logout,setup}, providers CRUD (/api/providers,/api/providers/[id]), per-providerping/models/balance/reveal-key,providers/ping-all,ping-scheduler/{status,pause,config}, and a feature-flag-gated/api/chatplaceholder that 404s in v1. - Provider registry (
lib/providers/): bespoke classes for the four non-OpenAI shapes (Anthropic, Gemini, Replicate, Ollama) and anOpenAICompatProviderfallback for everything else;lib/provider-detect.tsauto-detects the host and derives default model kinds from the Base URL. - Storage layer (
lib/storage.ts): encryptedproviders.json(XChaCha20-Poly1305, key derived from APP_SECRET via scrypt + per-install salt), an in-memory ping ring buffer onglobalThis(1500 pings ≈ 25 h), and JSONL append per ping for >24 h trends. - Auth & secrets (
lib/auth.tsvslib/auth.server.ts,lib/secrets-store.ts,instrumentation.ts): scrypt password verifier + jose JWT session cookie; boot hook loadssecrets.jsoninto an in-memory cache so nothing readsprocess.env.APP_SECRETafter first boot. - Server scheduler (
lib/server-scheduler.ts): HMR-safe singleton onglobalThis,paused/setIntervalSecondscontrols, bounded-concurrency sweeps (PING_CONCURRENCY).
3. Data Flow & Storage Contracts
- No database —
DATA_DIR(default./datain dev,/app/datain Docker) is the entire state:providers.json(encrypted provider records + salt, gitignored),secrets.json(APP_SECRET+ scryptadminHash, chmod 600, gitignored),pings/<id>.jsonl(append-only ping log, gitignored), andseed.json(bootstrap list, committed). - Secrets deliberately stay out of env:
APP_SECRETis read fromprocess.envexactly once at first boot as an optional override, then persisted tosecrets.json;ADMIN_PASSWORDis only read by the offlinescripts/admin-set-password.mjspre-hash helper — the app never reads either at runtime. - Provider API keys: entered via the dashboard, stored encrypted at rest, decrypted only server-side for outbound pings; list endpoints expose only the BLAKE2b fingerprint, with plaintext retrieval solely through the authenticated
reveal-keyroute. - Ping history: 24 h uptime is derived from the in-memory ring buffer (rebuilt on restart from the next sweep); the on-disk JSONL holds the full history for the planned v2 time-series UI.
4. Architectural Decision Records (ADRs)
ADR-01: Zero-dependency file storage over any database
- Context: Single-admin, self-hosted, “no external services” is a stated product requirement.
- Decision: All state lives in
DATA_DIRJSON files; encryption at rest replaces a secrets manager. - Consequences: One process / one admin by design; backup = copy the directory; no horizontal scaling or multi-instance safety.
ADR-02: APP_SECRET lives in secrets.json, not process.env
- Context: A Next.js worker-pool race meant cold workers didn’t see
process.env.APP_SECRET, causing 500s and an Edge-lockout loop (documented indocs/HANDOFF.md). - Decision:
instrumentation.tsloadssecrets.jsoninto an in-memory cache at boot; the Edge middleware is presence-only and JWT verification happens on Node. - Consequences: The cold-worker race is closed; rotating
APP_SECRETeffectively resets the install because ciphertexts are bound to secret + salt.
ADR-03: Edge/Node code split via the .server.ts convention
- Context:
middleware.tsruns on the Edge runtime and must never transitively importnode:fs/node:crypto. - Decision:
lib/auth.ts(jose-only, Edge-safe) vslib/auth.server.ts(Node-only session/password helpers); accidental Edge import fails the build rather than crashing at runtime. - Consequences: Runtime isolation is enforced by the bundler; auth verification stays on Node where the secrets cache lives, at the cost of a presence-only Edge gate.
ADR-04: Registry pattern with an OpenAI-compat fallback
- Context: 15+ target providers, most OpenAI-compatible, four with bespoke API shapes.
- Decision:
registry.tsspecial-cases Anthropic/Gemini/Replicate/Ollama; everything else routes throughOpenAICompatProvider. - Consequences: New OpenAI-shaped providers need only a seed entry; non-standard providers each require a dedicated class.
Deployment
Deployment & Operational Runbook: Provider Ping
1. Hosting & Environments
| Environment | Platform | URL / Endpoint | Auto-Deploy Branch |
|---|---|---|---|
| Self-hosted production | Single VPS / home server — Node process or Docker Compose | none evidenced in the repo (no deployed instance referenced) | none — no CI/CD workflows exist |
| Local dev | Next.js dev server | http://localhost:3000 (auto-redirects to /setup on first run) | N/A |
The repo contains no .github/ workflows and no Vercel/Cloudflare configuration; deployment is entirely manual, by design.
2. Prerequisites & Toolchain
- Node.js ≥ 22, pnpm ≥ 9 (
corepack enablepins the version), Git. - Docker ≥ 24 with Compose v2 for the container route (image is
node:22-alpine, installscurlfor the healthcheck).
3. Local Development Setup
git clone https://github.com/meta4m/provider-ping.gitcd provider-pingcorepack enablepnpm installpnpm dev # → http://localhost:3000, redirects to /setupFirst run auto-generates a 32-byte APP_SECRET into data/secrets.json (chmod 600) and asks for the admin password. Note: the README’s cp .env.example .env step references a .env.example that is absent from the repo — every env var is optional with defaults, so this is cosmetic (for Docker, touch .env satisfies the compose env_file).
4. Environment & Secrets Provisioning
Refer to spec.yml — the secrets manifest is empty. No secrets required.
APP_SECRETand the admin password are self-managed: the first boot generatesAPP_SECRET(aprocess.env.APP_SECREToverride is honored once, then persisted), the password is set via/setup, and provider API keys are entered in the UI and stored encrypted at rest.- Nothing to retrieve from the 2Brain vault for this project.
- Optional runtime knobs (all defaulted in
lib/env.ts):DATA_DIR,PORT,LOG_LEVEL,AUTO_REFRESH_SECONDS,PING_CONCURRENCY,PING_TIMEOUT_MS,PING_DEFAULT_INTERVAL_SECONDS,SERVER_SCHEDULER_ENABLED,ENABLE_CHAT_TEST.
5. Deployment Commands
# Option A — Node process (pair with pm2 / systemd / runit per README)pnpm install --frozen-lockfilepnpm buildpnpm start
# Option B — Docker (non-root uid 1001, /login healthcheck, pp-data volume)touch .env # compose env_file requires the file; all vars optionaldocker compose up -d --build6. Verification & Health Checks
- Container healthcheck:
curl -fsS http://localhost:3000/loginevery 30 s (both theDockerfileHEALTHCHECK anddocker-compose.yml). - Known gap (flagged in
docs/HANDOFF.md): there is no/api/healthendpoint — process liveness is the only automated signal. - Smoke test: log in → add a provider → Ping all → check status dot, sparkline, and the Models pill;
pnpm lintfor code health (HANDOFF records pre-existingtscerrors inauto-ping-control.tsx).
7. Incident Response & Rollback
- Rollback: redeploy the previous revision —
git checkout <good-sha> && pnpm build && pnpm start— ordocker compose downand re-run the prior image. - Locked out / corrupted auth:
rm data/secrets.json→ next boot re-offers/setup;rm data/providers.json data/secrets.jsonwipes everything and re-seeds fromdata/seed.json. - Pre-hash a known admin password (backup/restore path):
node scripts/admin-set-password.mjs(readsADMIN_PASSWORDfrom env) prints a scrypt verifier to paste intodata/secrets.jsonunderadminHashwith chmod 600. - Suspected key exposure: rotate at the upstream provider and re-enter the key in the UI; on-disk ciphertexts are bound to the install salt +
APP_SECRET, so rotating the secret effectively resets the store. - Stuck at login (known open issue in
docs/HANDOFF.md): restart the dev server first; the Edge/Node secrets race was redesigned around it, but no regression test exists yet.
Project vault
Cloudflare Access authorization and your passphrase are required to retrieve and decrypt stored values.
Client-Side Encrypted Secret Vault
Zero-knowledge architecture. Secrets are encrypted client-side using Web Crypto AES-256-GCM before leaving this browser tab. Edge databases store only ciphertext, IV, and salt.
Encrypted Records for provider-ping (0)
Encrypted records have not been loaded.