Licensing
PRIOR is proprietary, licensed software. Steering requires a valid, ED25519-signed license. Paid licenses are node-locked (bind-on-first-use); the free trial is expiry-only and binds to nothing. This page explains the tiers, what a license binds, and how to apply one. For plans, pricing, and the pre-purchase FAQ, see eagle-logic.com/get-prior or contact sales@eagle-logic.com.
What a license grants
- The engine verifies the license locally against a baked ED25519 public key; verification needs no server and never happens in the inference path. Connected tiers make a periodic background license check-in (see Connected vs. air-gapped licensing); air-gapped tiers make none.
- Without a valid license, PRIOR still runs, but degrades to plain inference with no gate
actuation (
x-prior-steering: disabled). You are never locked out of the model; you just don't get policy enforcement. - A license binds: customer id, hardware id, tier, expiry, and capabilities. An expired, tampered, or wrong-host license is rejected.
At 1.0–1.2, every paid tier, and the free trial too, ships the full capability set. Tiers differ only by node quantity, term, and support, not by which features you get.
Tiers
| Tier | Price | License files (nodes) | Term | Node-lock | Fulfilment |
|---|---|---|---|---|---|
| Free Evaluation | $0 | 1 | 30 days (hard) | none (expiry-only) | email → instant |
| Single Node | $995 / yr | 1 | 1 yr | bind-on-first-use | Stripe → instant |
| Team Pack | $2,450 / yr | 5 | 1 yr | bind-on-first-use | Stripe → instant |
| Platform | $4,950 / yr | 12 | 1 yr | bind-on-first-use | Stripe → instant |
| Enterprise / Sovereign | Custom ($10k+) | N / unlimited | Custom | bind-on-first-use or pre-bound | Contact sales |
- The metric is the node, not the seat. One PRIOR container fronts as many application seats as you like; you license the running instances.
- A node pack is N independent single-node licenses, not one counted license. A 5-node Team Pack
is five
.licfiles, each independently node-locked on first use. - The free trial is full-featured, not a crippled binary. It is a 30-day, all-capabilities license with no node binding, so trial → paid is a pure license swap.
- Air-gapped is its own SKU, priced per site or fleet, issued on request. See Connected vs. air-gapped licensing.
- Enterprise covers custom procurement, >12 nodes, and long-lived (non-refreshing) licenses.
Engine tier mapping
The website SKUs map onto the engine's LicenseTier enum:
| SKU | Engine tier |
|---|---|
| Free Evaluation | TRIAL |
| Single / Team / Platform | PRIVATE (self-hosted, node-locked) |
| Air-gapped (per site / fleet) | AIR_GAPPED |
Node-locking (bind-on-first-use)
Paid licenses ship unbound. On first boot the engine resolves the node's stable identity and binds the license to it; thereafter that file only validates on that node.
- The bound identity is a node-identity token, not literally bare metal. The engine resolves a stable identity (a hardware id, a cluster id, or a volume id, depending on the environment).
- Trial licenses skip binding entirely (expiry-only), so evaluation is frictionless.
Moving a licence to another node
Since 1.2.0 this is self-service and immediate — no support ticket, and it does not consume or burn the licence. Release it from the old node:
curl -s -X POST http://localhost:8089/admin/license/deactivate \
-H "Authorization: Bearer $ADMIN_KEY"
The replacement node claims it on its next start, with no waiting period. Steering stops on the released node the moment it is released, so at most one node is ever steering on a licence — which is why the handover can be instant rather than gated behind a timeout.
Two things worth knowing:
- Keep
PRIOR_STATE_DIRon a persistent volume and a container rebuild keeps its identity, so there is nothing to transfer at all. This is the cheapest answer to redeploys and rescheduled pods. - If a node dies without releasing its licence, a replacement takes over automatically once the old one has been silent for a few days. You do not need to call us — but releasing it explicitly, as above, is instant, so prefer that whenever the old node is still reachable.
Applying a license
At deploy time, mount the file. There is no key to supply — the verification key is compiled into the engine, so a licence we signed validates out of the box:
docker run -d --name prior --gpus all \
-p 127.0.0.1:8089:8089 \
-e PRIOR_NATIVE_MODEL=/models/model.gguf \
-v /srv/models:/models:ro \
-v /path/to/license.bin:/app/license.bin:ro \
-v prior-state:/app/state \
ghcr.io/eagle-logic/prior:slim
Earlier docs showed a
PRIOR_LICENSE_PUBLIC_KEYenvironment variable here. It no longer exists. Baking the trust key into the environment meant the engine read it back at runtime, so anyone could point a published image at a key they held the private half of. Rotating the verification key is a release, not a deployment setting — and if you set that variable today, nothing happens.
At run time, upload it live (no restart) via the API or the WebUI:
curl -s -X POST http://localhost:8089/admin/license/upload \
-H "Authorization: Bearer $ADMIN_KEY" \
--data-binary @license.bin
Check status:
curl -s http://localhost:8089/admin/license/status -H "Authorization: Bearer $OPERATOR_KEY"
Returns the variant, tier, capability list, expiry + days remaining, and customer id. The WebUI's Access → License panel shows the same, with an Active/Unlicensed badge and an upload control.
Since 1.1.0 the status also reports Degraded — the license is structurally valid, but its
check-in was refused or has gone stale past the window, so steering is off on this node until it
reconnects. Degraded is distinct from Expired (the signed window actually lapsed) and from
Unlicensed (no license present).
Connected vs. air-gapped licensing
Running an engine older than 1.2.0? Upgrade it. Check-in now proves possession of the signed license, and engines from 1.1.0 and earlier do not send that proof, so their check-in is refused. The failure is silent: the engine keeps answering and keeps steering until its check-in window lapses, and then steering switches off and the model passes through unchanged. The upgrade is a pull and a restart, your license file is unchanged and needs no reissue, and
x-prior-steering: enabledon any response is how you confirm it took.
- Connected self-serve tiers (
PRIVATE,CLOUD) make a periodic, PII-free license check-in to the license server, roughly every two weeks (PRIOR_LICENSE_CHECKIN_DAYS, default 14). It carries only the license id and an opaque per-node identifier, never prompts, completions, or model data. The check-in confirms the subscription is active and that the node holds its one seat; a node that is refused (seat taken elsewhere, or subscription cancelled) or that cannot check in for the full window degrades to plain, unsteered inference on that node until it reconnects. The same loop auto-refreshes an approaching-expiry license (PRIOR_LICENSE_REFRESH_URL, or the server default). None of this happens in the inference path; it is a background task. - Air-gapped licenses make no outbound traffic of any kind, at any point. In exchange they require a one-time offline activation: the engine prints a challenge, we sign it, and you paste the signed response back. Until that response is applied the license loads but does not steer, so plan the handshake as part of installation rather than after it. The license itself is long-lived and does not refresh.
- Because node counting cannot be enforced offline, air-gapped licenses are priced per site or
fleet rather than per node.
PRIOR_CLUSTER_IDgives every node at a site one shared identity, so they emit the same challenge and are activated by the same response. This is a standard SKU, but it is issued by hand rather than self-serve: ask us and we will cut one.
Local development
There is no licence bypass. A licence verifies or it does not load — local development included.
PRIOR_LICENSE_MODE=dev used to skip verification and was removed: it was readable from the
environment, so a published image could be unlocked with a single docker run -e. Nothing replaced
it, and setting it today has no effect at all.
For local work, build with the dev-license cargo feature. That compiles in a second trust
anchor — a dev public key — alongside the production one, so a locally signed licence validates on
your own build and nowhere else. Production images compile that anchor out entirely, so the dev key
cannot be made to work in the field, and the production signing key never touches a dev box.
See also: Deployment · Concepts.