Skip to content

Publishing an adapter

This section is for third-party and partner developers who have built an adapter against Pq.Adapters.Framework and now need to ship it so that a customer's Protequ installation can find, install and run it.

Everything the platform needs to know about your adapter travels inside the image itself, as OCI labels. There is no manifest to submit, no YAML to register, no entry to add to a central list: you build one Linux container image, label it correctly, push it to repo.protequ.com, and it appears in the installer's adapter catalog and on the public adapter page.

  your repo                     repo.protequ.com                customer's box
  ─────────                     ────────────────                ──────────────
  Dockerfile                                                    pq-installer
    LABEL org.protequ.*  ──►  pq/<image>:1.0.0   ──►  reads /v2/… labels
    ENTRYPOINT dotnet …         pq/<image>:latest       ├─ shows it in the catalog
                                                        ├─ writes the compose service
                                                        └─ writes the nginx route (UI only)
                                       │
                                       └──────────────►  protequ.github.io catalog page

Because the labels are the contract, a typo in a label is a deployment bug — see Label reference.


Prerequisites

You need How you get it
A Protequ registry account (username + token) Issued by Protequ. Grants push access to the pq namespace on repo.protequ.com.
Read access to the PQ NuGet feed Same account. Feed: https://repo.protequ.com/api/packages/PQ/nuget/index.json.
.NET 10 SDK For building the adapter locally.
Docker with Buildx For building and pushing the image.
A working adapter See Getting started and Local dev setup.

Never commit the token. In CI it belongs in a repository secret; locally it belongs in docker login / dotnet nuget add source, not in a file you push.


The procedure

1. Choose the image name

The image name is an identifier, not a display name — it drives the container name, the compose profile and the tag override variable on the customer's box.

  • lowercase and prefixed with pq: pqacme, pqtechfass, pqhikvision
  • keep the name stable forever; hyphens are allowed, but the installer converts them to underscores only in the tag override variable, for example pq-tools becomes PQ_TOOLS_TAG
  • one image per adapter, stable forever (renaming it looks like a different adapter)

Full reference: repo.protequ.com/pq/pqacme. See Registry for what the installer derives from this name.

2. Build the adapter against the published framework

Your project references Pq.Adapters.Framework from the PQ feed — you do not need the Protequ monorepo. The package carries the source generator, the framework YAML files and the bundled Pq.Domain / Pq.Messaging assemblies. See Image anatomy.

3. Write the Dockerfile

Multi-stage: SDK image builds and publishes, chiseled runtime image runs. The final stage carries the LABEL block. Full worked example: Image anatomy.

4. Label the image

At minimum org.opencontainers.image.title, .description, .vendor, org.protequ.adapter="true", org.protequ.category and org.protequ.device_vendor. Everything else is optional and additive. Full table: Label reference.

5. Build and smoke-test locally

docker build -t pqacme:dev -f Dockerfile .
docker run --rm -e Mq__Host=host.docker.internal:4222 -e Mq__User=<nats-user> -e Mq__Password=<nats-password> pqacme:dev

The adapter should connect to NATS and register. The NATS credentials are the ones configured for the PQ deployment you are pointing at — ask whoever runs it. If you have no PQ stack to test against, see Local dev setup for how to reach NATS from outside the PQ deployment.

Then confirm the labels actually landed on the image:

docker inspect pqacme:dev --format '{{json .Config.Labels}}'

6. Tag with a semver version

1.0.0 for a release, 1.0.0-rc.1 for a prerelease. The version is the image tag — there is no other version field. See Tagging rules.

7. Push to repo.protequ.com

Either from CI (recommended — worked GitHub Actions example) or by hand (manual push).

8. Verify it is discoverable

Pull the labels back out of the registry and confirm the adapter shows up in the installer's catalog. See Verifying the publish.


Release checklist

  • [ ] Image name is lowercase, pq-prefixed, and unchanged from the previous release
  • [ ] Final stage is a chiseled .NET runtime image, running as $APP_UID (non-root)
  • [ ] org.protequ.adapter="true" is present — without it the adapter is invisible
  • [ ] org.protequ.category is one of the known values (see Label reference)
  • [ ] org.opencontainers.image.title / .description read well on a catalog card
  • [ ] Any extra ports, volumes, env or dependencies are declared as labels, not documented in prose
  • [ ] Version tag is valid semver; a prerelease carries a - and does not move latest
  • [ ] docker inspect on the built image shows every label you expect
  • [ ] The pushed image resolves in the registry and appears in the installer catalog