Files
cli/docs/service-discovery-labels.md
Sienna Meridian Satterwhite 65c8fb80e3 docs: service discovery labels migration guide
313-line walkthrough for adopting the `sunbeam.pt/*` label scheme on
existing manifests in sbbb. Documents the required labels, optional
annotations, virtual-service ConfigMap pattern, and the
multi-deployment grouping convention. Includes a complete table of
the 33 services with their target K8s resources and the values to put
on each. Teams onboarding new services can follow this without having
to read the registry source.
2026-04-07 17:52:50 +01:00

14 KiB

Sunbeam Service Discovery Labels

Migration guide: replacing hardcoded service definitions in sunbeam-sdk/src/registry/services.rs with Kubernetes label-based discovery.


1. Label Convention

Every Sunbeam-managed service must have labels and annotations on its primary Kubernetes resource (Deployment, StatefulSet, DaemonSet, or CNPG Cluster).

Labels (required)

Label Value Purpose
sunbeam.pt/service Service name (e.g. hydra) Primary lookup key for the CLI
sunbeam.pt/category Category slug (e.g. auth) Grouping for sunbeam status, sunbeam restart <category>

Annotations (conditional)

Annotation Value When to include
sunbeam.pt/display-name Human-readable name (e.g. "Hydra (OAuth2/OIDC)") Always
sunbeam.pt/kv-path OpenBao KV v2 secret path (e.g. hydra) Only if the service has secrets in OpenBao
sunbeam.pt/db-user PostgreSQL username (e.g. hydra) Only if the service has a CNPG database
sunbeam.pt/db-name PostgreSQL database name (e.g. hydra_db) Only if the service has a CNPG database
sunbeam.pt/build-target Build target name (e.g. people) Only if the service is built from source
sunbeam.pt/depends-on Comma-separated service names (e.g. postgres,openbao) Only if the service has dependencies
sunbeam.pt/health-check One of: pod-ready, cnpg, seal-status, or an HTTP path like /healthz Only if not the default (pod-ready). Omit for services with HealthCheck::None

Virtual services

Services with no workload pods (e.g. scaleway-s3, longhorn) should be represented by a ConfigMap carrying the labels and an additional marker:

apiVersion: v1
kind: ConfigMap
metadata:
  name: sunbeam-svc-scaleway-s3
  namespace: external
  labels:
    sunbeam.pt/service: scaleway-s3
    sunbeam.pt/category: infra
    sunbeam.pt/virtual: "true"
  annotations:
    sunbeam.pt/display-name: "Scaleway S3"
    sunbeam.pt/kv-path: scaleway-s3
data: {}

Multi-deployment services

When a service spans multiple Deployments (e.g. messages has messages-backend, messages-mta-in, messages-mta-out), all Deployments get the same sunbeam.pt/service label. The CLI groups them automatically. Put the full annotations on just one of them (conventionally the primary/backend Deployment) and minimal labels on the rest.


2. Complete Service Table

33 services organized by category. The "K8s Resource" column indicates which object to label.

Auth (namespace: ory)

Service K8s Resource Labels Annotations Notes
hydra Deployment hydra in ory service: hydra, category: auth display-name: "Hydra (OAuth2/OIDC)", kv-path: hydra, db-user: hydra, db-name: hydra_db, depends-on: postgres,openbao
kratos Deployment kratos in ory service: kratos, category: auth display-name: "Kratos (Identity)", kv-path: kratos, db-user: kratos, db-name: kratos_db, depends-on: postgres,openbao
login-ui Deployment login-ui in ory service: login-ui, category: auth display-name: "Login UI", kv-path: login-ui, depends-on: kratos

Data (namespace: data)

Service K8s Resource Labels Annotations Notes
postgres CNPG Cluster postgres in data service: postgres, category: data display-name: "PostgreSQL (CNPG)", health-check: cnpg Health check is cnpg, not pod-ready
openbao StatefulSet openbao in data service: openbao, category: data display-name: "OpenBao (Secrets)", health-check: seal-status Health check is seal-status
valkey Deployment valkey in data service: valkey, category: data display-name: "Valkey (Cache)"
opensearch Deployment opensearch in data service: opensearch, category: data display-name: "OpenSearch"

DevTools (namespace: devtools)

Service K8s Resource Labels Annotations Notes
gitea Deployment gitea in devtools service: gitea, category: devtools display-name: "Gitea (Git Forge)", kv-path: gitea, db-user: gitea, db-name: gitea_db, depends-on: postgres,openbao

Platform (namespace: lasuite)

Service K8s Resource Labels Annotations Notes
hive Deployment hive in lasuite service: hive, category: platform display-name: "Hive (Backend)", kv-path: hive, db-user: hive, db-name: hive_db, depends-on: postgres,openbao
people-backend Deployment people-backend in lasuite service: people-backend, category: platform display-name: "People (Backend)", kv-path: people, db-user: people, db-name: people_db, build-target: people, depends-on: postgres,openbao
people-frontend Deployment people-frontend in lasuite service: people-frontend, category: platform display-name: "People (Frontend)", build-target: people-frontend
people-celery Deployments people-celery-worker + people-celery-beat in lasuite service: people-celery, category: platform display-name: "People (Workers)", depends-on: people-backend Multi-deploy: both Deployments get the same service label
docs Deployment docs-frontend in lasuite service: docs, category: platform display-name: "Docs", kv-path: docs, db-user: docs, db-name: docs_db, build-target: docs-frontend, depends-on: postgres,openbao
meet Deployment meet in lasuite service: meet, category: platform display-name: "Meet", kv-path: meet, db-user: meet, db-name: meet_db, build-target: meet, depends-on: postgres,openbao,livekit
drive Deployment drive in lasuite service: drive, category: platform display-name: "Drive", kv-path: drive, db-user: drive, db-name: drive_db, depends-on: postgres,openbao
projects Deployment projects in lasuite service: projects, category: platform display-name: "Projects", kv-path: projects, db-user: projects, db-name: projects_db, build-target: projects, depends-on: postgres,openbao
calendars Deployment calendars in lasuite service: calendars, category: platform display-name: "Calendars", kv-path: calendars, db-user: calendars, db-name: calendars_db, build-target: calendars, depends-on: postgres,openbao
kratos-admin Deployment kratos-admin in lasuite service: kratos-admin, category: platform display-name: "Kratos Admin UI", kv-path: kratos-admin, build-target: kratos-admin, depends-on: kratos,seaweedfs
collabora Deployment collabora in lasuite service: collabora, category: platform display-name: "Collabora (Office)", kv-path: collabora

Messaging

Service K8s Resource Labels Annotations Notes
messages Deployments messages-backend, messages-mta-in, messages-mta-out in lasuite service: messages, category: messaging display-name: "Messages (Mail)", kv-path: messages, db-user: messages, db-name: messages_db, build-target: messages, depends-on: postgres,openbao Multi-deploy: all 3 get the same service label
tuwunel Deployment tuwunel in matrix service: tuwunel, category: messaging display-name: "Tuwunel (Matrix)", kv-path: tuwunel, build-target: tuwunel, depends-on: openbao

Media (namespace: media)

Service K8s Resource Labels Annotations Notes
livekit Deployment livekit-server in media service: livekit, category: media display-name: "LiveKit (WebRTC)", kv-path: livekit, depends-on: openbao

Storage (namespace: storage)

Service K8s Resource Labels Annotations Notes
seaweedfs Deployment seaweedfs-filer in storage service: seaweedfs, category: storage display-name: "SeaweedFS (S3)", kv-path: seaweedfs, depends-on: openbao

Monitoring (namespace: monitoring)

Service K8s Resource Labels Annotations Notes
grafana Deployment grafana in monitoring service: grafana, category: monitoring display-name: "Grafana", kv-path: grafana, depends-on: openbao
prometheus Deployment prometheus in monitoring service: prometheus, category: monitoring display-name: "Prometheus" No KV, no DB, no deps
loki Deployment loki in monitoring service: loki, category: monitoring display-name: "Loki" No KV, no DB, no deps

Infra

Service K8s Resource Labels Annotations Notes
cilium Deployment cilium-operator in kube-system service: cilium, category: infra display-name: "Cilium (CNI)" No health check (HealthCheck::None)
longhorn ConfigMap sunbeam-svc-longhorn in longhorn-system service: longhorn, category: infra, virtual: "true" display-name: "Longhorn (Storage)" Virtual: no deployments listed
cert-manager Deployment cert-manager in cert-manager service: cert-manager, category: infra display-name: "cert-manager (TLS)" No health check
ingress Deployment pingora in ingress service: ingress, category: infra display-name: "Ingress (Proxy)", depends-on: cert-manager No health check
vso Deployment vault-secrets-operator in vault-secrets-operator service: vso, category: infra display-name: "Vault Secrets Operator", depends-on: openbao No health check
headscale Deployment headscale in vpn service: headscale, category: infra display-name: "Headscale (VPN)", db-user: headscale, db-name: headscale_db, depends-on: postgres No health check, no KV, but has a DB
scaleway-s3 ConfigMap sunbeam-svc-scaleway-s3 in external service: scaleway-s3, category: infra, virtual: "true" display-name: "Scaleway S3", kv-path: scaleway-s3 Virtual: external service, no pods

3. Example Patches

Example 1: Standard Deployment (hydra)

# Deployment in namespace: ory
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hydra
  namespace: ory
  labels:
    sunbeam.pt/service: hydra
    sunbeam.pt/category: auth
  annotations:
    sunbeam.pt/display-name: "Hydra (OAuth2/OIDC)"
    sunbeam.pt/kv-path: hydra
    sunbeam.pt/db-user: hydra
    sunbeam.pt/db-name: hydra_db
    sunbeam.pt/depends-on: postgres,openbao

Example 2: StatefulSet (openbao)

# StatefulSet in namespace: data
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: openbao
  namespace: data
  labels:
    sunbeam.pt/service: openbao
    sunbeam.pt/category: data
  annotations:
    sunbeam.pt/display-name: "OpenBao (Secrets)"
    sunbeam.pt/health-check: seal-status

Example 3: CNPG Cluster (postgres)

# CNPG Cluster in namespace: data
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: postgres
  namespace: data
  labels:
    sunbeam.pt/service: postgres
    sunbeam.pt/category: data
  annotations:
    sunbeam.pt/display-name: "PostgreSQL (CNPG)"
    sunbeam.pt/health-check: cnpg

Example 4: External service ConfigMap (scaleway-s3)

# No pods exist for this service; use a ConfigMap placeholder
apiVersion: v1
kind: ConfigMap
metadata:
  name: sunbeam-svc-scaleway-s3
  namespace: external
  labels:
    sunbeam.pt/service: scaleway-s3
    sunbeam.pt/category: infra
    sunbeam.pt/virtual: "true"
  annotations:
    sunbeam.pt/display-name: "Scaleway S3"
    sunbeam.pt/kv-path: scaleway-s3
data: {}

Example 5: Multi-deployment service (messages)

All three Deployments carry the same sunbeam.pt/service: messages label. Full annotations go on the primary Deployment; the others only need the labels.

# Primary Deployment - carries all annotations
apiVersion: apps/v1
kind: Deployment
metadata:
  name: messages-backend
  namespace: lasuite
  labels:
    sunbeam.pt/service: messages
    sunbeam.pt/category: messaging
  annotations:
    sunbeam.pt/display-name: "Messages (Mail)"
    sunbeam.pt/kv-path: messages
    sunbeam.pt/db-user: messages
    sunbeam.pt/db-name: messages_db
    sunbeam.pt/build-target: messages
    sunbeam.pt/depends-on: postgres,openbao
---
# Secondary Deployment - labels only
apiVersion: apps/v1
kind: Deployment
metadata:
  name: messages-mta-in
  namespace: lasuite
  labels:
    sunbeam.pt/service: messages
    sunbeam.pt/category: messaging
---
# Secondary Deployment - labels only
apiVersion: apps/v1
kind: Deployment
metadata:
  name: messages-mta-out
  namespace: lasuite
  labels:
    sunbeam.pt/service: messages
    sunbeam.pt/category: messaging

The same pattern applies to people-celery (Deployments: people-celery-worker, people-celery-beat).


4. Verification

List all sunbeam-managed services

kubectl get deploy,sts,cm -A -l sunbeam.pt/service

Check a specific service

kubectl get deploy -n ory -l sunbeam.pt/service=hydra \
  -o jsonpath='{.items[0].metadata.annotations}'

List all services in a category

kubectl get deploy,sts,cm -A -l sunbeam.pt/category=platform

List virtual services only

kubectl get cm -A -l sunbeam.pt/virtual=true

Verify all 33 services are discoverable

kubectl get deploy,sts,cm -A -l sunbeam.pt/service \
  -o jsonpath='{range .items[*]}{.metadata.labels.sunbeam\.pt/service}{"\n"}{end}' \
  | sort -u | wc -l
# Expected: 33

Test with the CLI after labeling

sunbeam status          # Should list all services
sunbeam logs hydra      # Should find hydra pods via label selector
sunbeam restart auth    # Should restart all services in the auth category

Notes

  • The sunbeam.pt/health-check annotation defaults to pod-ready when omitted. Only set it explicitly for cnpg, seal-status, or custom HTTP paths.
  • Services with HealthCheck::None in the registry (all Infra services) should not have a health-check annotation. The CLI treats missing health-check on infra services as "no active health monitoring."
  • The sunbeam.pt/virtual label is only needed on ConfigMap placeholders for services with no workload resources. The two virtual services are longhorn and scaleway-s3.
  • Namespace is not encoded as a label/annotation because it is intrinsic to the Kubernetes resource itself.