Skip to content

Label reference

Every label your adapter image carries. These are the only metadata the platform has about your adapter — the installer, the compose generator, the nginx route generator and the public catalog page all read them straight out of the image config blob.

Labels are strings. Booleans are the literal text "true" / "false"; lists are comma-separated in a single label. Anything else is treated as absent.


Identity — OCI standard

Label Required Read by Notes
org.opencontainers.image.title yes installer catalog, public catalog card Human display name, e.g. Example Vendor CCTV. Falls back to the image name if missing.
org.opencontainers.image.description yes installer catalog, public catalog card One or two sentences: what devices, over what protocol, with what capabilities. This is the card body — write it for an integrator, not a developer.
org.opencontainers.image.vendor yes catalog Who publishes the image (your company).
org.opencontainers.image.source recommended humans URL of the source repository or the registry page.
org.opencontainers.image.licenses recommended humans SPDX id or Proprietary.

Classification

Label Required Values Effect
org.protequ.adapter yes "true" The switch. Without it the image is classified as unknown, never appears in the installer catalog, and is skipped by the public catalog page.
org.protequ.id yes, when org.protequ.adapter="true" a stable per-image GUID Identity the pqshop catalogue sync joins on. An image without one is skipped by the sync entirely (no product is created or updated for it). Once set, never change it — the sync uses it to recognize "this is still the same adapter" across renames. AdapterLabelDriftTests enforces that every adapter image declares one and that no two images share the same value.
org.protequ.category yes see below Groups the adapter in the catalog and picks its icon. May be a comma-separated list (e.g. "intrusion,access") for an adapter sold under more than one category — the installer catalog groups/filters by the first (primary) value; the pqshop catalogue sync creates a product per listed category. Missing → other.
org.protequ.device_vendor yes free text Who makes the hardware, e.g. Example Vendor Ltd.. Distinct from image.vendor.
org.protequ.capabilities optional comma-separated Capability chips on the catalog card.
org.protequ.default_enabled optional "true" / "false" Whether the adapter's checkbox is pre-ticked in the installer. Default false. Only set true for something every install should have.
org.protequ.demo optional "true" Marks the card with a Demo badge — simulators and sample stubs.
org.protequ.in_development optional "true" Marks the card with an In development badge — not yet a production delivery.
org.protequ.docs recommended in-image path Points at the documentation bundle copied into the image, e.g. "/pq/adapter-docs/Pq.Adapter.Acme". Protequ extracts the bundle from there; the path's last segment names the adapter. See Writing and delivering adapter documentation.

Category

Value Catalog group
cctv Video Surveillance — NVRs and IP cameras
intrusion Intrusion Detection — alarm panels, partitions, zones
access Access Control — controllers, readers, biometric terminals
fire Fire Detection — fire alarm control panels (EPS), detectors, sounders
module Modules & Services — operational modules and platform services
security Security — general security integrations and software adapters

Any other value still works, but it lands in an unnamed group at the end of the catalog with a generic icon. Prefer one of the known values above.

Capability chips

These values render with a friendly label and an icon; anything else renders as raw text.

timeSync · rtsp · ptz · firmware · partitions · outputs · access · biometric · osdp · analytics

org.protequ.capabilities="timeSync,rtsp,ptz"

Deployment labels

These change the compose service the installer generates for your adapter. Use them instead of asking an operator to hand-edit docker-compose.yml — a hand edit is lost on the next deploy.

Label Format Generated into
org.protequ.ports "host:container", comma-separated ports: entries
org.protequ.volumes "host:container[:ro]", comma-separated volumes: entries
org.protequ.env.<NAME> one label per variable an environment: entry NAME: "<value>"
org.protequ.depends service names, comma-separated extra depends_on: entries, condition: service_started
LABEL org.protequ.ports="9000:9000" \
      org.protequ.volumes="./acme-config:/app/config:ro" \
      org.protequ.env.ACME__PollSeconds="30" \
      org.protequ.depends="go2rtc"

Notes:

  • depends_on: server (condition: service_healthy) is always added — you do not declare it.
  • depends entries must name services that exist in the customer's stack. A name that does not exist breaks docker compose up for the whole deployment.
  • Prefer defaults baked into appsettings.json over org.protequ.env.*. Use the label only for values that genuinely have to be visible and overridable in compose.
  • Every published port is a hole in the customer's perimeter. Declare one only if the device must connect inbound to your adapter.

UI labels

Only for adapters that serve their own web surface. See Adapters that ship a UI.

Label Required Default Effect
org.protequ.ui for UI adapters — "true" makes the installer generate an nginx front-door route.
org.protequ.ui.slug for UI adapters image name minus pq URL segment: the UI is served at /adapters/<slug>/. URL-safe characters only.
org.protequ.ui.port optional 8443 Internal HTTPS port nginx proxies to.

Copy-paste template

LABEL org.opencontainers.image.title="<Display Name>" \
      org.opencontainers.image.description="<What it integrates, over what protocol, what it can do.>" \
      org.opencontainers.image.vendor="<Your company>" \
      org.opencontainers.image.source="<repo or registry URL>" \
      org.opencontainers.image.licenses="Proprietary" \
      org.protequ.adapter="true" \
      org.protequ.id="<stable per-image GUID, generate once, never change>" \
      org.protequ.category="access" \
      org.protequ.device_vendor="<Hardware manufacturer>" \
      org.protequ.capabilities="access,outputs" \
      org.protequ.default_enabled="false"

How the labels are read

Worth knowing when a label change "doesn't take":

  1. The catalog resolves the latest tag. If the repository has no latest (a prerelease-only adapter), it falls back to the newest version tag and flags the entry as a prerelease.
  2. From a multi-arch index it picks the linux/amd64 child manifest, skipping Buildx attestation entries.
  3. It downloads that manifest's config blob and reads .config.Labels.

So: labels live in the image config, not in the tag or the manifest. Changing a label requires rebuilding and pushing the image — retagging an existing digest changes nothing.