Skip to content

Offline & air-gapped activation

GRCFlow never contacts a licence server. A licence key is an Ed25519-signed claim that the backend verifies locally against a public key shipped with the product, so an install with no route to the internet activates exactly like one that is online.

There is no activation call, no phone-home, no periodic re-check, and nothing that expires because a network was unreachable.

What that means in practice

Network needed to activate No
Network needed to keep running No
Bound to a machine / MAC / CPU No — move it between hosts freely
Where the key is stored /etc/sovereign-grc/license.key
Survives restart Yes — read from disk at startup

Because keys are not hardware-bound, you can buy on a laptop, receive the key by email, and carry it to the air-gapped server on whatever media your policy allows.

Activating with no internet

  1. Buy from any internet-connected device. Checkout emails the signed key to the address on the order.
  2. Move the key to the air-gapped host. It is a single line of text — copy it via the same channel you use for any other config material.
  3. Apply it, either way:

Through the UI: Setup → License → paste the key.

Or with curl, from the host itself:

curl -X POST http://localhost:8000/api/v1/setup/license \
  -H "Content-Type: application/json" \
  -d '{"license_key":"<paste the key here>"}'
  1. Confirm it took. The response reports the tier, seat count and expiry. It is also written to /etc/sovereign-grc/license.key and reloaded on every restart.

If the key is rejected, the error distinguishes the cases: Invalid signature means the key was altered or is not ours; License expired means the term has ended; System clock appears to have been tampered with is covered below.

Why it works without a network

The backend holds only the public half of the signing key:

LICENSE_PUBLIC_KEY_HEX=302a300506032b6570032100bd52efaf3c8a0c8940a09d0dc5de5d7cd43802ec4a0d12b65a67b01cce9a27fe

That value ships in deploy/public/.env.example and as the default in deploy/public/docker-compose.yml, so a stock install already has it. Publishing it is safe and deliberate — a public key can verify a signature but cannot create one. Only the vendor's private half, held in the mint service, can sign a licence.

Do not blank this value

If LICENSE_PUBLIC_KEY_HEX is unset, the backend cannot verify signatures and rejects every licence with "License validation unavailable — public key not configured" — including keys you have paid for. A legitimate key then fails indistinguishably from a forged one.

Clock integrity on air-gapped hosts

An offline host has no NTP, so its clock can drift or be set backwards — accidentally or to extend an expired term. GRCFlow keeps a high-water mark at /etc/sovereign-grc/hwm.dat recording the furthest point in time it has seen. If the system clock later reads meaningfully earlier than that mark, validation returns CLOCK_TAMPER rather than silently accepting the licence.

If you hit this after a legitimate clock correction — a CMOS battery replacement, or a VM restored from an old snapshot — set the clock correctly and remove hwm.dat; it is rebuilt on the next validation.

Community edition

The Community edition needs no key at all. It self-activates when the backend runs with AUTH_MODE=local, and its licence rolls forward automatically while the backend runs, so an offline install never hits an expiry cliff. See Pricing.