Skip to main content
Migrate Already selling? Move your customers to Keylight without re-issuing a single key.
Keylight

Use case · Rust

Licensing for Rust apps and CLIs

Add license keys to any Rust binary with the native keylight crate — synchronous, runtime-free, with offline Ed25519 verification and Stripe-native billing.

Start Free

For developers shipping Rust desktop apps, CLIs, and daemons direct.

  • You want a crate you cargo add, not a licensing backend to build.
  • Async licensing SDKs drag in a Tokio runtime you may not want.
  • Users expect the binary to validate its license offline.

Updated June 2026

Rust is increasingly the language of choice for developers who want performance without compromise — CLI tools, desktop apps, background daemons, and system utilities. If you are selling a Rust binary directly to customers, you need licensing. The keylight crate gives you signed key activation and offline Ed25519 verification with a single cargo add, no async runtime required.

Why Rust apps deserve proper licensing

Rust developers shipping commercial software often reach for the same approach that worked in 2005: a plain random string delivered by email, checked against a hard-coded hash. It is fast to write and immediately insufficient.

The problem is not the string itself — it is everything around it. A plain key can be shared freely, because there is nothing to verify against. Once one customer posts it, every copy of your binary unlocks. You need a signed key: a payload containing the customer’s entitlements, signed by a private key your server holds, verifiable by a public key your binary bundles. That is Ed25519 in practice, and building it yourself means writing the crypto, building the signing server, managing key rotation, and maintaining a dashboard for customer support.

For most indie Rust developers, that backend accumulates for months before it is solid — time better spent on the product.

The keylight crate handles all of it. When a customer completes checkout through Stripe, Keylight receives the webhook, mints a signed lease, and delivers the key by email. Your binary activates the key with one function call, the lease is verified locally, and you gate features on entitlements. The only code you write is the call site.

Why async runtimes are the wrong fit here

Most licensing SDKs for Rust are built around async networking, which means they pull in Tokio — a capable runtime, but a significant dependency if your binary does not already use it. A CLI that runs in 30 milliseconds does not want to boot a multi-threaded async runtime to make a single HTTP call on first launch.

The keylight crate is synchronous. Activation calls the Keylight API over a blocking HTTP request. Offline verification — the path your binary takes on every subsequent launch — makes no network call at all: it reads the cached lease from disk and verifies the Ed25519 signature against the bundled public key. Fast, deterministic, and dependency-light.

For binaries that already use Tokio, this is equally fine: a synchronous call from async code requires a spawn_blocking, which is the correct pattern for blocking I/O inside an async context anyway. The crate does not fight your runtime — it simply does not require one.

What offline verification means in practice

Rust apps run in more constrained environments than web services. A CLI tool might run in a CI pipeline with no outbound HTTPS. A desktop app might open on a laptop that is offline. A daemon might run in a locked-down corporate network where your licensing API is not reachable.

Offline license validation means the critical path — verifying that the running binary is licensed — never requires a network call. The lease is a signed payload stored locally after activation. On every launch your binary reads it, verifies the Ed25519 signature against the public key compiled into the binary, checks the entitlement fields, and proceeds. No round trip.

Online revalidation still happens when connectivity is available — typically on activate and on periodic checks you control — to pick up revocations, subscription renewals, and entitlement changes. The max_offline_days parameter sets how long a cached lease stays valid without a successful revalidation. After that window, the crate requires an online check before granting access. You set the window based on your product’s risk tolerance.

The architecture is also more robust for you as the operator. If your server is unavailable for an hour, every customer with a valid cached lease is completely unaffected. The licensing service going down does not bring your customers’ software down.

Integrating with Keylight

use keylight::{Keylight, KeylightConfig};

let cfg = KeylightConfig::builder("your-tenant", "your-product", "sdk_live_…")
    .max_offline_days(7)
    .build();
let kl = Keylight::new(cfg)?;

// Activate a key (online). The lease is Ed25519-verified before it is persisted.
let res = kl.activate("USER-LICENSE-KEY")?;
println!("activated: {}", res.activated);

// Gate features on entitlements — works offline from the cached lease.
if kl.has_entitlement("pro") {
    // unlock pro features
}

KeylightConfig::builder takes your tenant ID, product ID, and SDK key — all available from your Keylight dashboard after creating a product. The max_offline_days call is optional; omit it to use the default window.

Keylight::new initializes the client and loads any existing cached lease from disk. activate makes a single outbound call, receives the signed lease, verifies it locally before persisting it, and returns the activation result. Subsequent launches that call has_entitlement skip the network entirely — the cached lease is sufficient.

Entitlements map directly to the product configuration you define in the Keylight dashboard. You might have a pro entitlement for a paid tier, a beta entitlement for early access, or a teams entitlement for multi-seat licenses. Your binary gates features on whatever entitlements you define; Keylight carries them in the signed payload.

Getting started

The typical integration takes under an hour. Create a Keylight account, connect your Stripe account, and create a product in the dashboard. Add the keylight crate to your Cargo.toml, build a KeylightConfig with the SDK key from your dashboard, and wire activate into your CLI’s first-run flow or your desktop app’s license entry screen.

The dashboard gives you license lookup, activation reset, and revocation — the operational surface that accumulates fastest when you roll your own system. When a customer emails saying they switched machines, you reset their activation in two clicks.

Keylight plans start at $19/month on the pricing page. The free tier supports up to five licenses, which is enough to run the full end-to-end flow — Stripe checkout, webhook, key delivery, binary activation, offline verification — before you ship.

The hardest part of licensing a Rust binary is not the Ed25519 math. It is the API, the dashboard, the email delivery, and the Stripe webhook plumbing that has to be solid before you charge a single customer. The keylight crate offloads all of that so you can stay in Rust.

Frequently asked

How do I license a Rust app?+

Run cargo add keylight, build a KeylightConfig with your tenant, product, and SDK key, then call activate and gate features on entitlements — verified offline from a signed lease.

Is the Rust SDK async?+

No. The keylight crate is synchronous and runtime-free — no async or Tokio. You drive checks on launch and on events.

Start licensing your app today

Drop in the Swift SDK, point it at your dashboard, and sell paid apps in under a minute. Free forever tier included.

Start Free