Files

9.0 KiB

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:

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:

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.