{% extends "base.html" %} {% block title %}Licences{% endblock %} {% block content %}
Admin / Licences

Self-hosted licences

Signed keys for customers running Vigil on their own hosts. Paddle sales issue keys automatically; issue manual ones here for invoices, POs and air-gapped sites.

{% if not signing %}
The licence signing key file is missing on this server (LICENSE_PRIVATE_KEY_FILE), so keys cannot be signed.
{% endif %}

Installations waiting for your approval {{ pending|length }}

Every self-hosted install registers itself with its licence and its own key fingerprint. Nothing can be changed on that installation until you approve it here{% if reauth %} — approval needs your password{% if needs_totp %} and a fresh 2FA code{% endif %}{% endif %}. The key you approve is bound to that fingerprint, so copying it to another machine does nothing.

{% if pending %} {% for a in pending %}{% endfor %}
RequestedLicence · customerInstallationApprove
{{ a.requested_at|timeago }}
from {{ a.ip or '?' }}
{{ a.license_id }}{% for r in rows if r.license_id == a.license_id %}
{{ r.customer }} {{ r.email }}
{% endfor %}
{{ a.hostname or '?' }}
{{ a.instance_url or '' }} · v{{ a.version or '?' }}
fp {{ a.fingerprint }}
{% if reauth %} {% if needs_totp %} {% endif %}{% endif %}
{% else %}

Nothing pending. New requests also arrive by email.

{% endif %}
Air-gapped customer? Paste their activation request code

Issue a licence

List price: ${{ price }}/month per instance (Enterprise limits). Annual deals: price × 10.

Signing public key (verify bundles with openssl)
{{ pubkey }}
{% for r in rows %}{% else %}{% endfor %}
LicenceCustomerExpiresLast seen
{{ r.license_id }}{% if r.paddle_subscription_id %} paddle{% endif %}{% if r.revoked %} revoked{% endif %}{{ r.customer }}
{{ r.email }}{% if r.notes %} · {{ r.notes }}{% endif %}
{{ r.expires|dt }}{{ r.last_seen_at|timeago }}{% if r.last_instance %}
{{ r.last_instance[:40] }}
{% endif %}{% if r.last_stats %}
{{ r.last_stats.get('servers', '?') }} servers · {{ r.last_stats.get('monitors', '?') }} monitors
{% endif %}
Key
Claim key (installs register with it; read-only until approved)
{{ r.key }}
{% for a in acts.get(r.license_id, []) %}
{{ a.status }} {{ a.hostname or '?' }} {{ a.fingerprint[:12] }} seen {{ a.last_seen_at|timeago }} {% if a.status == 'approved' %}
bound key (air-gapped: send this to the customer)
{{ a.bound_key }}
{% endif %}
{% endfor %}
No licences issued yet.
{% endblock %}