This document explains how to use JWT-based license key validation for self-hosted installations of ActionsManager.
ActionsManager Self-Hosted is currently a free beta preview. No paid plans are currently available, and features, limits, and license behavior may change before general availability.
Self-hosted installations include JWT-based license-key support for future/commercial tier behavior:
- Free Tier: Default tier with limited features (3 projects, 5 repos per project)
- Professional Tier: Future/commercial tier behavior; not currently sold during beta
- Enterprise Tier: Future/commercial tier behavior; not currently sold during beta
- License validation happens at startup: The application validates the license key when it starts
- Result is cached: The tier is cached for the lifetime of the application process
- No network calls: Validation is purely cryptographic using RS256 JWT signatures
- Graceful fallback: Invalid or expired licenses fall back to the free tier with clear error messages
- No secret required: Customers only need
LICENSE_KEY. The vendor's public key is embedded in the application.
Add the following to your .env file:
# Self-hosted installation mode
INSTALLATION_MODE=self-hosted
# License key (provided by vendor)
LICENSE_KEY=your_jwt_license_key_hereNo LICENSE_SECRET is required. License signatures are verified using an RSA public key embedded in the application.
The license system supports the following tier names:
"free"- Free tier"professional"or"pro"- Professional tier (both work)"enterprise"- Enterprise tier
cd backend
export LICENSE_KEY="your_license_key"
export INSTALLATION_MODE="self-hosted"
uvicorn main:app --host 0.0.0.0 --port 8000You should see output like:
============================================================
🚀 ActionsManager API Starting
📦 Installation Mode: self-hosted
🔑 License Tier: professional
============================================================
import os
os.environ['LICENSE_KEY'] = 'your_license_key'
os.environ['INSTALLATION_MODE'] = 'self-hosted'
import license
tier = license.get_installation_tier()
print(f"Current tier: {tier}")The system provides clear error messages for common issues:
⚠️ License validation failed: Invalid license key format
⚠️ Falling back to free tier
🔑 License Tier: free
⚠️ License validation failed: License key has expired
⚠️ Falling back to free tier
🔑 License Tier: free
⚠️ License validation failed: Invalid license key signature
⚠️ Falling back to free tier
🔑 License Tier: free
🔑 License Tier: free
(No error - just defaults to free tier)
- Cloud Mode (
INSTALLATION_MODE=cloud): Future Cloud/SaaS path; not part of the first public self-hosted beta. License keys are ignored and tiers are intended to be managed through GitHub Marketplace if that offering launches later. - Self-Hosted Mode (
INSTALLATION_MODE=self-hosted): License keys determine the tier.
- RS256 asymmetric signing: Licenses are signed with the vendor's private key and verified with a public key embedded in the application. Customers cannot forge licenses even with full access to the source code.
- No secret to protect: Customers do not hold any signing secret. The private key never leaves the vendor.
- Set expiration dates: Use the
expfield to limit license duration. - Restart required for changes: The tier is cached at startup; restart the application after updating
LICENSE_KEY.
- Check that
LICENSE_KEYenvironment variable is set correctly - Ensure there are no extra spaces or newlines in the key
- Ensure the token hasn't expired
- Check that
INSTALLATION_MODEis set to"self-hosted" - Verify there are no typos in the environment variable name
- Check application startup logs for error messages
- Restart the application after changing
LICENSE_KEY - The tier is cached at startup and doesn't change until the application restarts