Self-hosting
Wire your product to your instance
Make self-hosting real: point your customers' apps at your own Keyright instance. Create a product, generate its signing key, embed the public key and your base URL in the SDK, issue a license, and activate — the same SDKs as managed Keyright, just your product key and your URL.
This is the step that makes self-hosting real: your customers’ apps must license against your Keyright instance, not ours. The SDKs (NuGet, npm, PyPI, Maven) are the same ones the integration guides describe for managed Keyright — nothing is hardcoded to a Delta1 endpoint. The whole walkthrough runs against your instance; below, $BASE is your base URL (from Deploy → Verify) and $TOKEN is your KEYRIGHT_ADMIN_TOKEN.
Step 1 — Create the product
Products don’t exist until you create them (the signing-key call in step 2 will 404 otherwise). In the dashboard (Products → Add product) or via the API:
curl -X POST -H "X-Admin-Token: $TOKEN" -H "content-type: application/json" \
$BASE/admin/products -d '{"name":"Acme App","slug":"acme-app"}'
Step 2 — Generate the product’s signing key
This is the key that signs acme-app licenses; embed its public half in your app.
curl -X POST -H "X-Admin-Token: $TOKEN" $BASE/admin/products/acme-app/signing-key
# -> { "signingPublicKey": "MIIBIjANBgkq...", "rotated": false, ... }
The private key is generated and stored in your database, KEK-encrypted — it never leaves your instance. Copy the returned public key. (Alternatively, use a tenant-wide key via KEYRIGHT_SIGNING_KEY and embed GET $BASE/admin/public-key — but a per-product key is the simplest, unambiguous choice.)
Step 3 — Embed that public key in your app
Via the SDK — this verifies licenses offline, with no call to your server:
| Runtime | Option | Value |
|---|---|---|
.NET (Keyright.NET) | PublicKeyBase64 | your product’s public key (step 2) |
Node (keyright) | publicKeyBase64 | your product’s public key |
Python (keyright) | public_key_base64 | your product’s public key |
Java (com.delta1labs:keyright) | publicKeyBase64 | your product’s public key |
Step 4 — Point the SDK at your instance
For online activation/validation/metering — set the service URL to your instance’s base URL ($BASE):
| Runtime | Option | Value |
|---|---|---|
| .NET | ServiceUrl | https://licensing.acme.example |
| Node | serviceUrl | https://licensing.acme.example |
| Python | service_url | https://licensing.acme.example |
| Java | serviceUrl | https://licensing.acme.example |
.NET example (Node, Python and Java are identical bar naming — see their integration guides; for a self-service trial key your app calls POST <base>/v1/trial directly, which emails the key to the customer — who then enters it and your app activates it like any paid key):
using Keyright.Client;
static readonly KeyrightClient License = KeyrightClient.Initialize(new KeyrightOptions
{
Product = "acme-app", // your product slug on your instance
PublicKeyBase64 = "MIIBIjANBgkq...", // your product's public key (step 2)
ServiceUrl = "https://licensing.acme.example", // your instance base URL (step 4); omit if offline-only
});
Step 5 — Issue a license to a customer
Optionally define a tier (a seat count + entitlement template), then issue a key:
# optional: a reusable tier
curl -X POST -H "X-Admin-Token: $TOKEN" -H "content-type: application/json" \
$BASE/admin/products/acme-app/tiers -d '{"name":"pro","seats":3,"entitlements":{"export":"true"}}'
# issue a license (omit "id" to auto-generate the key)
curl -X POST -H "X-Admin-Token: $TOKEN" -H "content-type: application/json" \
$BASE/admin/licenses -d '{"licensee":"Acme Inc.","product":"acme-app","tier":"pro","seats":3,"email":"owner@acme.com"}'
# -> HTTP 201 { "id":"LIC-XXXX...", "product":"acme-app", "tier":"pro", "seats":3, "used":0, ... }
The id (LIC-…) is the key you hand the customer. seats on the license overrides the tier default.
Step 6 — The customer’s app activates
The SDK’s activate call (or a raw POST $BASE/v1/activate with body { "key", "machineId", "product" }, no auth) binds the machine, consumes a seat, and returns a signed lease your app caches and re-checks offline:
LicenseInfo info = await License.ActivateAsync(customerKey); // online: binds this machine
if (info.IsPaid && License.IsEnabled("export")) { /* unlock */ }
That’s the whole difference from managed Keyright: your product key and your URL. The /v1/* endpoints, the license/lease formats, and every SDK call are identical. Full per-language walkthroughs: .NET, Node.js, Python, Java, or the raw HTTP API (which documents the exact /v1/* request bodies).