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

106 lines
3.4 KiB
HTML

{% extends "base.html" %}
{% block content %}
<h1>Network Overview</h1>
{% if stats is none %}
<div class="card">
<div class="no-data">
Could not reach the Nebula stats endpoint at <code class="mono">{{ request.app.state.stats_url if request.app.state is defined else "configured URL" }}</code>.
Make sure <code class="mono">stats.enabled</code> and <code class="mono">stats.listen</code> are set in your Nebula config.
</div>
</div>
{% else %}
{# ── top-level counters ── #}
{% set meta = stats.get("meta", {}) %}
{% set network = stats.get("network", {}) %}
<div class="stat-grid">
<div class="stat-box">
<div class="label">Nebula Version</div>
<div class="value" style="font-size:15px; padding-top:4px;">{{ meta.get("version", "—") }}</div>
</div>
{% set peers = hostmap.get("Hosts", {}) if hostmap else {} %}
<div class="stat-box">
<div class="label">Active Peers</div>
<div class="value">{{ peers | length }}</div>
</div>
{% set counters = stats.get("counters", {}) %}
<div class="stat-box">
<div class="label">Tx Bytes</div>
<div class="value">{{ "{:,}".format(counters.get("send_bytes", 0)) }}</div>
</div>
<div class="stat-box">
<div class="label">Rx Bytes</div>
<div class="value">{{ "{:,}".format(counters.get("recv_bytes", 0)) }}</div>
</div>
<div class="stat-box">
<div class="label">Tx Packets</div>
<div class="value">{{ "{:,}".format(counters.get("send_packets", 0)) }}</div>
</div>
<div class="stat-box">
<div class="label">Rx Packets</div>
<div class="value">{{ "{:,}".format(counters.get("recv_packets", 0)) }}</div>
</div>
</div>
{# ── raw stats JSON ── #}
<details style="margin-bottom:20px;">
<summary>Raw stats JSON</summary>
<pre>{{ stats | tojson(indent=2) }}</pre>
</details>
{% endif %}
{# ── hostmap ── #}
<div class="card">
<h2>Peer Hostmap</h2>
{% if hostmap is none %}
<div class="no-data">Hostmap unavailable — stats endpoint not reachable.</div>
{% else %}
{% set hosts = hostmap.get("Hosts", {}) %}
{% if not hosts %}
<div class="no-data">No peers connected.</div>
{% else %}
<table>
<thead>
<tr>
<th>Overlay IP</th>
<th>Remote Addrs</th>
<th>Index</th>
<th>Relay?</th>
</tr>
</thead>
<tbody>
{% for overlay_ip, host in hosts.items() %}
<tr>
<td class="mono">{{ overlay_ip }}</td>
<td>
{% for addr in host.get("RemoteAddrs", []) %}
<span class="mono badge badge-gray" style="margin-right:4px;">{{ addr }}</span>
{% else %}
<span class="badge badge-gray">none</span>
{% endfor %}
</td>
<td class="mono">{{ host.get("LocalIndex", "—") }}</td>
<td>
{% if host.get("Relay") %}
<span class="badge badge-blue">relay</span>
{% else %}
<span class="badge badge-gray">no</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<details style="margin-top:16px;">
<summary>Raw hostmap JSON</summary>
<pre>{{ hostmap | tojson(indent=2) }}</pre>
</details>
{% endif %}
</div>
{% endblock %}