1{{ define "title" }}mTLS certificates — settings{{ end }}
2{{ define "navextra" }}<a href="/settings/keys">SSH keys</a> <a href="/settings/mtls">mTLS</a> <a href="/settings/token">API tokens</a>{{ end }}
3{{ define "srv_settings_mtls.html" }}{{ template "head" . }}
4<div class="container">
5 <h2 style="margin-bottom: 4px">mTLS client certificates</h2>
6 <p style="font-size: 13px; color: #666; margin-bottom: 16px">
7 Register client TLS certificates to authenticate with
8 <code>arche+mtls://</code> remotes without a bearer token. The server
9 identifies you by the SHA-256 fingerprint of the certificate.
10 </p>
11 {{ if .Error }}
12 <p class="error">{{.Error}}</p>
13 {{ end }} {{ if .Certs }}
14 <table style="margin-bottom: 24px">
15 <thead>
16 <tr>
17 <th>Label</th>
18 <th>Fingerprint (SHA-256)</th>
19 <th>Added</th>
20 <th></th>
21 </tr>
22 </thead>
23 <tbody>
24 {{ range .Certs }}
25 <tr>
26 <td>
27 {{ if .Label }}{{.Label}}{{ else }}<span style="color: #aaa">—</span>{{ end }}
28 </td>
29 <td style="font-family: monospace;
30 font-size: 11px;
31 max-width: 300px;
32 overflow: hidden;
33 text-overflow: ellipsis;
34 white-space: nowrap">{{.Fingerprint}}</td>
35 <td style="font-size: 12px; color: #888">{{.AddedAt.Format "2006-01-02"}}</td>
36 <td>
37 <button onclick="deleteCert({{.ID}})"
38 style="background: #c0392b;
39 font-size: 12px;
40 padding: 2px 8px">Delete</button>
41 </td>
42 </tr>
43 {{ end }}
44 </tbody>
45 </table>
46{{ else }}
47 <p style="color: #888; margin-bottom: 24px">No mTLS certificates registered.</p>
48 {{ end }}
49 <details>
50 <summary style="cursor: pointer; font-size: 13px; color: #555">Add certificate</summary>
51 <p style="font-size: 12px; color: #666; margin: 8px 0">
52 Generate a self-signed certificate with:
53 <br />
54 <code style="background: #f4f4f4; padding: 2px 6px; border-radius: 2px">
55 openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -keyout
56 client.key -out client.crt -days 3650 -nodes -subj "/CN=arche-client" </code>
57 <br />
58 Then paste the contents of <code>client.crt</code> below and store
59 <code>client.crt</code> and <code>client.key</code> at
60 <code>~/.config/arche/mtls/</code>.
61 </p>
62 <form method="post" action="/settings/mtls" style="margin-top: 12px">
63 <div class="field">
64 <label>Label (optional)</label>
65 <input type="text"
66 name="label"
67 style="width: 280px"
68 placeholder="e.g. work laptop" />
69 </div>
70 <div class="field">
71 <label>Certificate (PEM — paste contents of client.crt)</label>
72 <textarea name="cert_pem"
73 rows="6"
74 required
75 style="width: 500px;
76 padding: 6px 8px;
77 border: 1px solid #ccc;
78 border-radius: 3px;
79 font-family: monospace;
80 font-size: 12px"
81 placeholder="-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----"></textarea>
82 </div>
83 <button type="submit">Add certificate</button>
84 </form>
85 </details>
86</div>
87<script>
88 function deleteCert(id) {
89 if (!confirm("Delete this mTLS certificate?")) return;
90 fetch("/settings/mtls/" + id, { method: "DELETE" }).then(function (r) {
91 if (r.ok) {
92 location.reload();
93 } else {
94 alert("Delete failed");
95 }
96 });
97 }
98</script>
99{{ template "foot" . }}
100{{ end }}