143 lines
9.0 KiB
Markdown
143 lines
9.0 KiB
Markdown
# Xiteng Site component labels
|
|
|
|
`xiteng.site` does not contain a hardcoded service list. A Docker container opts one or more
|
|
components into the public catalog with labels under this namespace:
|
|
|
|
```yaml
|
|
labels:
|
|
- "xiteng.site.component.example.enabled=true"
|
|
- "xiteng.site.component.example.name=Example"
|
|
- "xiteng.site.component.example.description=What this component does."
|
|
- "xiteng.site.component.example.section=services"
|
|
- "xiteng.site.component.example.category=开发与协作"
|
|
- "xiteng.site.component.example.url=https://example.xiteng.site"
|
|
- "xiteng.site.component.example.endpoint=example.xiteng.site:443"
|
|
- "xiteng.site.component.example.access=sso"
|
|
- "xiteng.site.component.example.access-label=需要 Authentik"
|
|
- "xiteng.site.component.example.icon=EX"
|
|
- "xiteng.site.component.example.icon-url=https://example.xiteng.site/favicon.svg"
|
|
- "xiteng.site.component.example.accent=blue"
|
|
- "xiteng.site.component.example.order=100"
|
|
- "xiteng.site.component.example.navigation=new-tab"
|
|
- "xiteng.site.component.example.portal-link=native"
|
|
- "xiteng.site.component.example.monitor.enabled=true"
|
|
- "xiteng.site.component.example.monitor.url=http://example:8080/healthz"
|
|
```
|
|
|
|
## Schema
|
|
|
|
| Field | Required | Values / behavior |
|
|
|---|---:|---|
|
|
| `enabled` | yes | Only the exact value `true` publishes the component. |
|
|
| `name` | yes | Public display name. |
|
|
| `description` | recommended | Public description; never put secrets here. |
|
|
| `section` | yes | `services` or `infrastructure`. |
|
|
| `category` | recommended | Dynamic group heading. |
|
|
| `url` | no | Only HTTP(S) URLs are accepted. No URL renders a non-clickable card. |
|
|
| `endpoint` | no | Public protocol endpoint or connection hint. |
|
|
| `access` | yes | Machine-readable mode such as `public`, `sso`, `mixed`, `access-key`, `ssh-key`, `local`, or `internal`. |
|
|
| `access-label` | recommended | Human-readable access boundary shown on the card. |
|
|
| `icon` | no | Final fallback text or emoji, limited to eight characters. |
|
|
| `icon-url` | no | Preferred HTTP(S) icon URL. Without it, the UI tries `/favicon.svg`, `/favicon.ico`, then `/favicon.png` on the component origin before showing `icon`. |
|
|
| `accent` | no | `red`, `green`, `yellow`, `blue`, or `ink`. |
|
|
| `order` | no | Numeric order inside a section; defaults to `999`. |
|
|
| `navigation` | no | `new-tab` (default for URLs), `same-tab`, or `endpoint` (default without a URL). |
|
|
| `portal-link` | no | `embedded`, `native`, or `none`; documents how the service returns to the Portal. |
|
|
| `monitor.enabled` | no | `true` enables the built-in HTTP GET probe. |
|
|
| `monitor.url` | when enabled | Internal HTTP(S) target. It is never returned by the public API. |
|
|
| `monitor.interval` | no | Check interval in seconds, default `60`. |
|
|
| `monitor.failures` | no | Consecutive failures before `down`, default `3`. |
|
|
| `monitor.timeout` | no | Request timeout in seconds, default `10`. |
|
|
| `monitor.accept` | no | Accepted HTTP codes, default `200-299`; comma-separated values and ranges are supported. |
|
|
|
|
The component id (`example` above) must be globally stable. One container may publish multiple
|
|
components by using multiple ids, which is useful for services such as SeaweedFS Web and its S3 API.
|
|
|
|
The registry reads container state and image names from Docker. It returns only the public fields above plus
|
|
Compose project/service names, runtime status, sanitized monitor state, response time, last check time, and
|
|
24-hour availability. Internal monitor URLs, errors, environment variables, mounts, raw labels, Docker
|
|
configuration, and secret values are never returned to the public site container.
|
|
|
|
## Navigation contract
|
|
|
|
Components with a public HTTP(S) URL open in a new tab by default with `noopener noreferrer`, leaving the
|
|
Portal available in the original tab. Owned or officially customizable applications link back to
|
|
`https://xiteng.site/?focus=<component-id>#services`; the Portal clears incompatible filters, scrolls to the
|
|
component card, briefly highlights it, and then removes the `focus` query parameter. Protocol endpoints and
|
|
internal-only components remain non-clickable. Do not inject navigation into third-party HTML at the proxy.
|
|
|
|
## Monitoring and lifecycle
|
|
|
|
The Registry is the only discovery and lifecycle control plane. It uses the stable component id as the
|
|
database primary key, so a component can never create multiple monitors. It performs bounded-concurrency
|
|
HTTP GET probes and stores state in `site/data/registry.db`:
|
|
|
|
```text
|
|
active → missing → archived → purged
|
|
```
|
|
|
|
- `active`: the component Label is currently present on a Docker container;
|
|
- `missing`: the container or Label disappeared, but catalog and monitor history remain for 30 days;
|
|
- `archived`: monitoring is paused and the component is hidden from the default public catalog;
|
|
- `purged`: an administrator explicitly removes the component and all of its monitoring data.
|
|
|
|
A component that returns with the same id before purge reuses its existing history. Raw checks are retained
|
|
for 30 days; hourly and daily aggregates are retained for 365 days. Response bodies are never stored.
|
|
|
|
`https://xiteng.site/admin` and `/api/admin/*` are protected by Authentik ForwardAuth and additionally
|
|
require the exact username `liooil`; this check is repeated in the site backend and Key Vault. All other
|
|
users use `/account` and `/api/account/*`. The account page is the canonical self-service surface for
|
|
profile name/email, avatar resolution, password recovery, TOTP, Passkeys, Authentik sessions, and Provider
|
|
configuration constrained by the session's `(issuer, sub)` pair. Provider definition, model list, and an
|
|
optional credential are saved from one form. Backend credentials are encrypted by Key Vault; Frontend
|
|
credentials remain in the current browser's IndexedDB. Either mode can be saved and connectivity-tested in
|
|
the same action. The public homepage remains unauthenticated.
|
|
|
|
The admin page is the canonical control plane for human users, ordinary groups, password setup/recovery,
|
|
session revocation, authenticator status/reset, and a group-only application access matrix. The native
|
|
Authentik admin UI is hidden. TOTP and Passkey enrollment launches dedicated Authentik setup flows and
|
|
returns to `/account`; list, rename, delete, reset, and ownership checks remain in the Portal API. The account
|
|
page hashes the normalized email with SHA-256 in the browser, then loads Gravatar and Libravatar directly with
|
|
no referrer; a deterministic initials image remains visible while loading and on failure. Avatar bytes never
|
|
pass through the Portal backend. The Portal accesses Authentik with a server-only API token and
|
|
records every identity mutation in a local JSONL audit; password values are never logged. `liuhome` is
|
|
protected and currently contains `liooil` and `ziyue`; all managed non-public applications are restricted
|
|
to that group.
|
|
|
|
The default Authentik identification stage enables WebAuthn conditional UI. A discoverable Passkey can
|
|
authenticate directly on `auth.xiteng.site`; Authentik's default flow policies then skip both password and
|
|
the later MFA stage. Username/password plus TOTP remains available as a fallback, and new Passkeys are
|
|
enrolled with the default `resident_key_requirement=preferred` setup stage.
|
|
|
|
## Host metrics
|
|
|
|
The internal `metrics` service publishes the sanitized `/api/metrics` payload used by the device status
|
|
cards. It reads host CPU and memory counters from a read-only `/proc` mount, root filesystem capacity
|
|
through a read-only bind on the same filesystem, and NVIDIA GPU telemetry through the `utility` driver
|
|
capability. The public payload is limited to:
|
|
|
|
- CPU usage, model, logical core count, and load averages;
|
|
- memory and root filesystem used/available/total values;
|
|
- GPU model, utilization, VRAM, temperature, and power;
|
|
- hostname and collection timestamp.
|
|
|
|
The metrics container has no Docker socket and no public router. The site server proxies its fixed
|
|
internal endpoint as `/api/metrics`; arbitrary host files and commands are not exposed.
|
|
|
|
## PWA and icons
|
|
|
|
`favicon.svg` is the source artwork for browser and install icons. The PNG and ICO derivatives live in
|
|
`icons/` and at `favicon.ico`. `manifest.webmanifest` enables standalone installation and shortcuts to the
|
|
service and infrastructure catalogs. `sw.js` caches only the public page shell and static artwork. Runtime
|
|
component/metrics APIs, Authentik paths, and all administration requests always use the network and are
|
|
never written to the PWA cache.
|
|
|
|
Setting `enabled=false`, removing the labels, or removing the container moves the component to `missing`
|
|
without changing `index.html` or `app.js`. The old `homepage.*` and `kuma.*` namespaces are no longer read;
|
|
new and existing components use only the `xiteng.site.component.*` schema.
|
|
|
|
Static edge caching is a separate, security-sensitive declaration and is intentionally not part of
|
|
the public component schema. A service can opt public, user-independent asset directories into the
|
|
shared cache with `xiteng.site.cache.<policy>.*` labels. See `edge-cache/README.md` for the schema;
|
|
never apply it to API, admin, callback, tokenized download, HTML, or user-content paths.
|