get_logs needs a unit from an allowlist (router-*, kea, unbound, networkd, nftables, ddclient, acme, sshd, kernel). API tokens are valid for 1, 7, 30 (default) or 90 days, or without limit. The overview and the Changes page say which token made the unapplied changes. options.json (router://options) no longer holds the options' source paths: they differ between builds of a release, so a router rebuilding itself offline had to build the file and failed (found by the update test). Web UI: panels flow into columns on wide screens and the width is no longer capped; on phones the navigation is a menu button; the Advanced page uses panels; VLAN dropdowns show their chosen names; the duplicate WireGuard heading is gone. basic: a subtest for wan -> local rules. SPECS.md is now the only document (decisions, how each part works, and what is not done yet); PLAN.md is gone. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
66 lines
3.0 KiB
HTML
66 lines
3.0 KiB
HTML
{{define "content"}}
|
|
<div class="cols">
|
|
{{$d := .Data}}
|
|
<section>
|
|
<h2>Installed</h2>
|
|
<dl>
|
|
<dt>Version</dt><dd>{{or $d.Installed.Version "unknown"}}{{if $d.Installed.Rev}} <span class="muted">{{$d.Installed.Rev}}</span>{{end}}</dd>
|
|
<dt>Settings schema</dt><dd>{{$d.Installed.Schema}}</dd>
|
|
</dl>
|
|
</section>
|
|
|
|
{{if $d.Status.Running}}
|
|
<section class="busy"><h2>Updating…</h2><p>Verifying, importing and building the new version. This page refreshes on its own;
|
|
the web UI restarts when the new version is switched on.</p></section>
|
|
{{else if $d.Pending}}
|
|
<section class="pending"><h2>Waiting for confirmation</h2>
|
|
<p>A new configuration is active and not confirmed yet. Confirm it on the <a href="/">Overview</a>, or the router
|
|
goes back to the previous version.</p></section>
|
|
{{end}}
|
|
|
|
<section>
|
|
<h2>Install a bundle</h2>
|
|
<p>A <code>.bundle</code> file made with <code>nix run .#release</code>. It is installed only if it is signed with
|
|
this router's update key. The settings are kept (and migrated if the new version needs it); the new version
|
|
must be confirmed afterwards, or the router goes back.</p>
|
|
<form method="post" action="/update/upload?csrf={{.CSRF}}" enctype="multipart/form-data">
|
|
<p><label><input type="checkbox" name="force"> also install a version that is not newer</label></p>
|
|
<p><input type="file" name="bundle" required> <button>Upload and install</button></p>
|
|
</form>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Update server</h2>
|
|
<form method="post" action="/update/url" class="actions">
|
|
<input type="hidden" name="csrf" value="{{.CSRF}}">
|
|
<label>Address <input name="url" value="{{$d.URL}}" size="40" placeholder="https://updates.example.com/router"></label>
|
|
<button class="secondary">Save</button>
|
|
</form>
|
|
{{if $d.URL}}
|
|
<form method="post" action="/update/check" class="actions">
|
|
<input type="hidden" name="csrf" value="{{.CSRF}}">
|
|
<button class="secondary">Check for updates</button>
|
|
</form>
|
|
{{end}}
|
|
{{if $d.OfferErr}}<p class="error">Could not check: {{$d.OfferErr}}</p>{{end}}
|
|
{{with $d.Offer}}
|
|
<p>{{if .Newer}}Available: <strong>{{.Version}}</strong>{{if .Rev}} <span class="muted">{{.Rev}}</span>{{end}}.{{else}}Nothing newer: the server has {{.Version}}.{{end}}</p>
|
|
<form method="post" action="/update/install">
|
|
<input type="hidden" name="csrf" value="{{$.CSRF}}">
|
|
{{if not .Newer}}<p><label><input type="checkbox" name="force"> install it anyway</label></p>{{end}}
|
|
<button>{{if .Newer}}Install {{.Version}}{{else}}Install{{end}}</button>
|
|
</form>
|
|
{{end}}
|
|
<p class="hint">The server only has to serve static files: the <code>latest</code> file and <code>cache/</code> that
|
|
<code>nix run .#release</code> writes. The data is signed, so plain HTTP works too.</p>
|
|
</section>
|
|
|
|
{{if $d.Status.Log}}
|
|
<section>
|
|
<h2>Last update{{if $d.Status.Result}} — {{if eq $d.Status.Result "success"}}succeeded{{else}}failed ({{$d.Status.Result}}){{end}}{{end}}</h2>
|
|
<pre class="log">{{$d.Status.Log}}</pre>
|
|
</section>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|