# Licensing

URL: https://docs.testvibe.com/self-hosting/licensing

A self-hosted instance is licensed with an **offline, signed license** — there is no phone-home, so it works fully air-gapped. (The cloud SaaS is never license-checked; it's billed through Stripe instead.)

## How Licensing Works

- **Offline and signed.** TestVibe issues you a signed license. The instance verifies it locally against a key built into the app — no outbound calls, ever.
- **Bound to your instance.** The license names your organisation (shown in the app) and the specific **install id** it's valid for, so it can't be reused on a different install.
- **Perpetual by default.** Licenses don't expire unless TestVibe issues a time-boxed one.

## Grace, Then Read-Only

You don't need a license to start — the instance is fully usable while you activate:

| State | What happens | **Grace** | No valid license yet. The app runs normally and shows a warning. The grace window is a fixed number of days (default **14** ) and is persisted, so restarting doesn't reset it. | **Read-only** | Grace expired with no license. Existing data stays fully **viewable** , but **new test runs, generation, and load tests are paused** until you activate. | **Licensed** | A valid license is installed. Everything runs; the warning clears. 

info
Read access is **never** blocked — you can always sign in and view your projects, tests, and results. Only new chargeable work pauses in read-only.

## Activating A License

1. **Find your install id.** It's generated on first boot and printed in the web container's logs (look for a `[license]` line with the install id).
2. **Send TestVibe** that install id and your organisation name. TestVibe mints a license bound to your instance and sends it back.
3. **Install it** — set it as the license value in your environment (the string directly, or a mounted license file). The instance picks it up on its next periodic check or on restart, and the status returns to **Licensed** .
If a license ever lapses later, a fresh grace window starts before read-only kicks in again — so a renewal has a buffer, not an instant cutoff.

## Related Help

- [Install](/self-hosting/install)
- [Configuration](/self-hosting/configuration)
