{% extends "base.html" %} {% block content %}

Network

Every device on your LAN, updated every 3 seconds.

{% if flash_msg %}
{{ flash_msg }}
{% endif %} {% if error_msg %}
{{ error_msg }}
{% endif %}
Devices
across all LAN segments
Online now
seen in the last ~minute
Reserved
static MAC→IP bindings
Customers
connected via a voucher

Devices

loading…
Device IP MAC Segment Status Type Customer Actions
Loading…

Reserved = always the same IP · Dynamic = from the customer pool · Seen only = no active lease. Make Static pins a device to its current IP; Release drops its lease so it picks up a new one.

Ports

The network ports on this device and what each one is doing.

{% for i in data.ifaces.list %} {% else %} {% endfor %}
Port Doing Link Address Type
{{ i.name }} {% if i.vlans %}
+ {{ i.vlans | length }} VLAN{{ '' if i.vlans|length == 1 else 's' }}
{% endif %}
{% if i.role == 'wan' %}Internet {% elif i.role == 'lan' %}Customers {% elif i.role == 'lan-intent' %}Configured {% else %}Unused{% endif %}
{{ i.role_detail }}
{% if i.carrier == 'up' %}● up{% if i.speed_mbps %} {{ i.speed_mbps }}M{% endif %} {% elif i.carrier == 'down' %}○ unplugged {% elif i.carrier == 'missing' %}✕ not detected {% else %}unknown{% endif %} {% if i.ipv4 %}{{ i.ipv4 }}{% else %}{% endif %} {% if i.is_usb %}USB{% elif i.driver %}onboard{% else %}—{% endif %} {% if i.driver %}
{{ i.driver }}
{% endif %}
No ports detected.
{# The picker. Guarded by confirm-or-auto-revert: picking a port with no path back to the operator would otherwise lock them out for real — the fallback only covers a MISSING port, not a wrong-but-present one. #} {% if data.ifaces.pending %}
⏳ Confirm the LAN port change
Moved to {{ data.ifaces.pending.new }}. If you don't confirm, it reverts to {{ data.ifaces.pending.old }} and reboots in about {{ (data.ifaces.pending.seconds_remaining // 60) + 1 }} min.
{% else %}

Customers move to this port. You'll need to confirm from the new port within 5 minutes or it reverts by itself.

{% endif %}

Primary LAN ({{ data.ifaces.effective or 'eth1' }})

Subnet, DHCP pool, and customer DNS for your main server-vendo network.

LAN Subnet

{% if data.lan.pending %} {# A change has been applied and is awaiting confirmation. The operator is seeing this because they reconnected to the AP on the NEW subnet and logged back in — so the new network already works for them. #}
⏱ LAN subnet change — pending your confirmation

You're now reaching this admin on the new network ({{ data.lan.pending.new }}, SBC at {{ data.lan.pending.new_sbc_ip }}). Since you got here, it's working — click Confirm to keep it. If anything's wrong, Revert to return to {{ data.lan.pending.old }}.

{% if data.lan.pending.expired %} The confirmation window has passed. The SBC will automatically revert and reboot on its next check — click Confirm right now if you want to keep the new network. {% elif data.lan.pending.seconds_remaining >= 60 %} Auto-revert in about {{ data.lan.pending.seconds_remaining // 60 }} minute{{ 's' if (data.lan.pending.seconds_remaining // 60) != 1 else '' }} if you don't confirm — so you can never get locked out. {% else %} Auto-revert in under a minute if you don't confirm — so you can never get locked out. {% endif %}

{% else %}

The network your customers live on; the SBC is the first address ({{ data.lan.sbc_ip }}). Change only if it clashes with your ISP network.

Private /24 only. Disruptive — your connection drops; reconnect and click Confirm within {{ data.lan.confirm_window_minutes }} min or it auto-reverts, so a wrong subnet can't lock you out.

Current: {{ data.lan.subnet }} (SBC at {{ data.lan.sbc_ip }}). Default is {{ data.lan.default }}.
{% endif %}

Customer DNS

DNS servers your customers use. Doesn't affect the SBC's own DNS.

Currently active: {{ data.lan_dns.value }}

DHCP Pool

IP range handed out to customers — a bigger pool means more simultaneous customers.

Must be inside the LAN subnet and skip the SBC's own IP. Existing leases keep their IPs until they renew.

Current pool: {{ data.lan_dhcp.start }}{{ data.lan_dhcp.end }} ({{ data.lan_dhcp.size }} address{{ '' if data.lan_dhcp.size == 1 else 'es' }}, {{ data.lan_dhcp.used }} in use) · lease {{ data.lan_dhcp.lease_hours }}h. {% if data.lan_dhcp.size and data.lan_dhcp.used >= data.lan_dhcp.size %} Pool full — new customers can't get an IP. Widen the range. {% elif data.lan_dhcp.size and data.lan_dhcp.used >= (data.lan_dhcp.size * 0.9) %} Pool nearly full. {% endif %}

Sub-vendo VLANs

Extra, fully-isolated customer networks on tagged VLANs over the same uplink. Needs a VLAN-capable switch.

{% if segments %}
{% for seg in segments %} {% endfor %}
VLAN Subnet Gateway Interface DHCP pool Online Actions
{{ seg.vlan }} {{ seg.subnet }} {{ seg.gateway }} {{ seg.iface }} {{ seg.pool_start }}{{ seg.pool_end }} {{ seg.online }} {# ADR-0020 — per-VLAN voucher centralization opt-in. Checkbox auto-submits its little form so the operator just clicks once. #}

Online is a snapshot from when this page loaded.

{% else %}
No sub-vendo VLANs yet.
{% endif %}

Activation-site access

Lets anyone on the hotspot reach the activation site (vendorawifi.com) without inserting a coin — so you can register + activate this SBC even at a location with no other internet. Only the listed site is reachable; everything else still hits the captive portal.

Comma- or space-separated; subdomains are included automatically. Default vendorawifi.com — add more only if the registration page loads assets from another domain.
{% if segments %}

ESP API credentials

The login each ESP uses to reach this controller's API. Must match the API username + password set on every ESP.

Shown here on purpose — you need it to set up each ESP.

Current username: {{ rosapi_user or 'vendora' }}. Update each ESP to match if you change it.
{% endif %} {% if segments %}

Sub-vendo fleet

loading…

Each sub-vendo's ESP status and connected customers. Refreshes every 10 seconds.

Loading fleet…

ESP-issued vouchers have their own page: open ESP Vouchers →

{% endif %} {% endblock %}