Skip to content

Devices for your own Hub

A self-hosted Hub on its own domain is only half the story — the devices have to talk to it. Stock Pantavisor images are built for the hosted service: they connect to api.pantahub.com. This page covers building your own images with meta-pantavisor that point at api.<your-domain> and — the part that is easy to forget — actually trust its TLS certificate.

Note the prerequisite: devices talk TLS only, and verify the server's certificate. That is why a development deployment without a domain (compose, or the chart on localhost) cannot serve real hardware, no matter how the image is configured — the Hub must be reachable on a TLS endpoint whose certificate chains to a CA in the device's trust store. (In development, simulate devices with pantavisor-mocker instead.)

The two things a device needs

Pantavisor device/config/pantahub.configcreds.host = api.<your-domain>/etc/thttp/certsCA that signed the server certHTTPSapi.<your-domain>ingress + cert-managercertificate from Let's Encrypt→ base (your Hub API)
  1. The endpointcreds.host / creds.port in the device's pantahub.config. Stock images ship creds.host=api.pantahub.com.
  2. The trust anchor — Pantavisor's HTTP client (libthttp/mbedTLS) does not use a full system CA bundle; it verifies servers against the small PEM store in /etc/thttp/certs. Out of the box that store contains only the Let's Encrypt roots (ISRG Root X1).

That default has a pleasant consequence: if your Hub uses the chart's Let's Encrypt setup, the certificate is already trusted — you only need to change creds.host. Any other CA (a corporate CA, self-signed, or a commercial one) must be added to the store at build time.

Point the image at your domain

In your Yocto layer, override the pantahub.config that the pantavisor-pvroot recipe installs into the image's config partition:

sh
# meta-yourlayer/recipes-pv/pantavisor/pantavisor-pvroot.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
sh
# meta-yourlayer/recipes-pv/pantavisor/pantavisor-pvroot/pantahub.config
updater.interval=10
updater.network_timeout=120
creds.host=api.pantahub.example.com
creds.port=443
creds.id=
creds.prn=
creds.secret=

This is also where a factory image bakes in its auto-join token:

sh
PH_FACTORY_AUTOTOK=<your token secret>

Without a token, devices register unclaimed against your Hub and you claim them as usual.

Add your CA (non-Let's Encrypt certificates only)

The /etc/thttp/certs store is installed by the libthttp recipe (libthttp-certs package). Append your root CA to it:

sh
# meta-yourlayer/recipes-pv/libthttp/libthttp_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

SRC_URI += "file://my-root-ca.pem"

do_install:append() {
    install -m 0644 ${WORKDIR}/my-root-ca.pem ${D}${sysconfdir}/thttp/certs/
}

Ship the root certificate (PEM) of the chain that signs your ingress certificate. If the store lacks the right CA, devices fail TLS verification against your API and never register — with nothing visible on the Hub side, so check the device's Pantavisor logs when a fleet stays silent.

(The store's location is itself configurable via PV_LIBTHTTP_CERTSDIR in pantavisor.config; the default is /etc/thttp/certs.)

Build

With the layer in place, build as usual with meta-pantavisor's kas setup — for example:

sh
./kas-container build kas/machines/rpi.yaml:kas/scarthgap.yaml:kas/bsp-base.yaml

See the meta-pantavisor build guide for machines, configuration menus and flashing instructions.

Trying it without a rebuild

For a quick test, you can retarget an already-flashed stock image: mount its config partition and edit pantahub.config (creds.host=…) before first boot. This only works when the server certificate chains to Let's Encrypt, since the trust store can't be changed this way — anything else needs the image rebuild above.

Once devices register against your domain, everything else in these guides — claiming, auto-join tokens, TLS onboarding, updates and pvr (point it at your API with pvr -b https://api.<domain>) — works unchanged.