Files
nix-config/packages/system/nebula-ui/templates/sign.html
mjallen18 3234029ae5 hmm
2026-04-07 22:02:54 -05:00

105 lines
3.6 KiB
HTML

{% extends "base.html" %}
{% block content %}
<h1>Sign Certificate</h1>
<div class="card">
<h2>New Host Certificate</h2>
<p style="color:var(--muted); font-size:13px; margin-bottom:20px;">
Fill in the details below. The CA on this host will sign a new certificate.
Scan the QR codes with the mobile Nebula app or copy the PEM values.
</p>
{% if error %}
<div class="alert alert-error">{{ error }}</div>
{% endif %}
<form method="post" action="/sign">
<div style="display:grid; grid-template-columns:1fr 1fr; gap:16px;">
<div class="field">
<label for="name">Host Name *</label>
<input type="text" id="name" name="name" placeholder="e.g. laptop" required
value="{{ result.name if result else '' }}">
</div>
<div class="field">
<label for="ip">Overlay IP / Mask *</label>
<input type="text" id="ip" name="ip" placeholder="e.g. 10.1.1.5/24" required
value="{{ result.ip if result else '' }}">
</div>
</div>
<div style="display:grid; grid-template-columns:1fr 1fr; gap:16px;">
<div class="field">
<label for="groups">Groups <span style="color:var(--muted)">(comma-separated, optional)</span></label>
<input type="text" id="groups" name="groups" placeholder="e.g. laptops,users">
</div>
<div class="field">
<label for="duration">Duration <span style="color:var(--muted)">(optional, e.g. 8760h0m0s)</span></label>
<input type="text" id="duration" name="duration" placeholder="default: CA lifetime">
</div>
</div>
<button type="submit" class="btn btn-primary">Sign Certificate</button>
</form>
</div>
{% if result %}
<div class="card">
<h2>Certificate Issued</h2>
{# cert info summary #}
{% if result.cert_info %}
{% set details = result.cert_info.get("details", {}) %}
<div class="stat-grid" style="margin-bottom:20px;">
<div class="stat-box">
<div class="label">Name</div>
<div class="value" style="font-size:14px; padding-top:2px;">{{ details.get("name", result.name) }}</div>
</div>
<div class="stat-box">
<div class="label">IP</div>
<div class="value" style="font-size:14px; padding-top:2px;">{{ (details.get("ips", [result.ip]) | first) }}</div>
</div>
{% if details.get("groups") %}
<div class="stat-box">
<div class="label">Groups</div>
<div class="value" style="font-size:14px; padding-top:2px;">{{ details.get("groups") | join(", ") }}</div>
</div>
{% endif %}
{% if details.get("notAfter") %}
<div class="stat-box">
<div class="label">Expires</div>
<div class="value" style="font-size:13px; padding-top:2px; word-break:break-all;">{{ details.get("notAfter") }}</div>
</div>
{% endif %}
</div>
{% endif %}
<p style="color:var(--muted); font-size:12px; margin-bottom:16px;">
Scan each QR code separately with the Nebula mobile app, or use the PEM text below.
The private key is shown only once — store it securely.
</p>
<div class="qr-grid">
<div>
<div class="qr-box">
<div class="qr-label">Host Certificate</div>
{{ result.cert_qr | safe }}
</div>
<details style="margin-top:10px;">
<summary>Certificate PEM</summary>
<pre>{{ result.cert_pem }}</pre>
</details>
</div>
<div>
<div class="qr-box">
<div class="qr-label">Host Key (Private)</div>
{{ result.key_qr | safe }}
</div>
<details style="margin-top:10px;">
<summary>Key PEM</summary>
<pre>{{ result.key_pem }}</pre>
</details>
</div>
</div>
</div>
{% endif %}
{% endblock %}