archergate-license
License management for indie software developers.
Machine binding. Offline grace periods. 14-day trials. Anti-tamper.
Works from Rust, C, C++, or any language via REST API.
What it does
- Validates license keys against the Archergate server (or your own)
- Binds licenses to machines via hardware fingerprint (CPU + OS install ID)
- Works offline for 30 days after last validation (touring producers stay unblocked)
- 14-day trials with zero server calls
- HMAC-signed cache files detect manual tampering
- Validation receipts make binary patching harder
Rust integration
Cargo.toml
[]
= "0.1"
Validate on startup
use ;
let client = new;
match client.validate
Trial mode
match client.start_trial
Anti-tamper (defense in depth)
// Get a cryptographic receipt proving validation ran
let receipt = client.validate_with_receipt.unwrap;
// Check it later (e.g. in your audio callback, on a timer, wherever)
let fp = machine_fingerprint;
if !receipt.verify
// Or check the global heartbeat counter
if heartbeat_count == 0
Complete example (20 lines)
use ;
C / C++ integration
This is what most indie software developers need.
Build the library
Produces:
- Windows:
target/release/archergate_license.dll+archergate_license.dll.lib - macOS:
target/release/libarchergate_license.dylib+libarchergate_license.a - Linux:
target/release/libarchergate_license.so+libarchergate_license.a
Include the header
Copy include/archergate_license.h into your JUCE project.
Link in CMakeLists.txt
target_include_directories(YourPlugin PRIVATE path/to/archergate-license/include)
target_link_libraries(YourPlugin PRIVATE path/to/libarchergate_license.a)
# On Windows, also link:
# ws2_32 userenv bcrypt ntdll
Use in your PluginProcessor
;
Or use the C++ wrapper (included in the same header)
;
Trial mode in C++
archergate::License ;
try catch
Error codes
| Code | Constant | Meaning |
|---|---|---|
| 0 | AG_OK |
License valid |
| -1 | AG_ERR_INVALID |
Key not recognized |
| -2 | AG_ERR_EXPIRED |
License expired |
| -3 | AG_ERR_MACHINE_MISMATCH |
Wrong machine |
| -4 | AG_ERR_NETWORK |
No internet + no cache |
| -5 | AG_ERR_TRIAL_EXPIRED |
Trial period over |
| -6 | AG_ERR_ACTIVATION_LIMIT |
Too many machines |
Self-hosted server
The server is a single Rust binary with SQLite. No Postgres, no Redis, no Docker required.
Setup
# Create an API key
# → ag_key_abc123... (save this)
# Create a license
# Run the server
Point the SDK at your server
let client = new
.with_api_url;
Or in C:
AgLicenseClient* client = ;
API endpoints
POST /validate
Body: { "license_key": "...", "machine_fingerprint": "...", "plugin_id": "..." }
→ { "valid": true, "expires_at": "2025-12-31T00:00:00Z" }
→ { "valid": false, "error": "expired" | "invalid" | "machine_mismatch" }
POST /activate
Body: { "license_key": "...", "machine_fingerprint": "...", "plugin_id": "...", "email": "..." }
→ { "token": "...", "offline_token": "..." }
POST /licenses (admin)
Body: { "plugin_id": "...", "email": "...", "max_machines": 3 }
→ { "license_key": "XXXX-XXXX-XXXX-XXXX", ... }
GET /health
→ { "status": "ok" }
How offline mode works
- Plugin calls
validate()on startup. - If the server is reachable, the response is cached at
~/.archergate/licenses/{plugin_id}.jsonwith an HMAC signature. - If the server is unreachable and the cache is under 30 days old,
validate()returnsOk. - After 30 days without server contact,
validate()returnsNetworkError.
The 30-day window means touring producers with spotty internet aren't locked out during a show.
How anti-tamper works
The SDK has multiple independent defense layers:
- Signed cache files: Each
.jsoncache has a.sigcompanion. Editing the JSON (e.g. extendingexpires_at) invalidates the HMAC. - Validation receipts:
validate_with_receipt()returns a cryptographic proof that the check actually ran. You can verify this at any point in your code. - Heartbeat counter: A global atomic counter increments every time validation runs. If it's 0, the function was never called.
- Machine fingerprint binding: Licenses are tied to hardware. Copying the cache file to another machine doesn't work.
None of this stops a determined reverse engineer with a debugger. But it stops casual crackers who hexedit a single byte to flip a bool, and it makes automated cracking tools fail. That's the realistic bar for indie plugins.
License
MIT