Skip to content
Thomas Mangin edited this page Jul 13, 2026 · 5 revisions

Pre-Alpha. This page describes behavior that may change.

The web UI is the same engine as the CLI with a different surface. It reads and writes the same config tree, runs the same YANG validators, and uses the same user database. This is the long version of the Web UI tour.

Ze Web UI

Starting the server

The web server is part of the Ze daemon. You enable it from the command line or in the config.

ze start --web 3443
environment {
    web {
        enabled true;
        server main {
            ip   0.0.0.0;
            port 3443;
        }
    }
}

When no certificate is configured, Ze generates an ECDSA P-256 self-signed certificate on first start, with SANs for localhost, 127.0.0.1, ::1, and the listen address. Put a real certificate in front of the port before you expose it.

The --insecure-web flag turns off authentication and forces the listener back to 127.0.0.1. It exists for development. Do not use it on a public interface.

Authentication

The web server uses the same user database as the SSH CLI. You can log in two ways.

Browser sessions go through /login. On success, Ze sets a ze-session cookie that is Secure, HttpOnly, and SameSite=Strict. Each user has at most one active session: logging in from a second browser invalidates the first.

API clients use HTTP Basic. Send Accept: application/json (or append ?format=json to the URL) and Ze authenticates the request without creating a session.

Both login paths run through the same AAA chain as the SSH CLI, so RADIUS and TACACS+ administrators can sign in to the web UI. Local users remain the fallback, used when the remote servers are unreachable or do not recognise the account.

curl -k -u admin:password https://localhost:3443/show/bgp/?format=json

Every authenticated response carries the security headers you would expect: HSTS (max-age=63072000), Content-Security-Policy: default-src 'self', X-Frame-Options: DENY, X-Content-Type-Options: nosniff, and Cache-Control: no-store.

Role-based access control

A session's authorization profile decides what it can reach. A read-only session (a profile that denies the edit section) is blocked from every configuration-editing surface: the config edit form and the /admin/ console return 403 Forbidden, and the edit controls are hidden from the navigation so they are never offered in the first place.

The same authorizer enforces both layers. The route gate that returns the 403 and the handler that would apply a mutation consult one authorizer, so page visibility and mutation enforcement never diverge. Read paths are unaffected: a read-only user still browses the config tree, runs show and monitor, and downloads the running config.

Deployments with a single admin and no authorization assignments are unaffected: with nothing to enforce, the gate allows edits.

URL scheme

The URL pattern is verb-first and three-tier.

Tier Pattern Method Description
View /show/<yang-path> GET Read-only config tree view.
View /monitor/<yang-path> GET Same as /show with auto-polling.
Config /config/edit/<path> GET Editable config tree.
Config /config/set/<path> POST Set a leaf value.
Config /config/add/<path> POST Create a list entry.
Config /config/delete/<path> POST Delete a leaf value.
Config /config/add-form/ GET Add new entry overlay form.
Config /config/changes GET Commit bar HTML with pending change count.
Config /config/commit/ GET/POST Diff and commit.
Config /config/discard/ POST Discard pending changes.
Config /config/compare/ GET Compare pending against committed.
Config /config/diff GET Diff modal with content.
Config /config/diff-close GET Closed diff modal (empty state).
Config /config/download GET Download the committed config as a text attachment.
Config /config/upload POST Replace the whole config from an uploaded file.
Fragment /fragment/detail GET HTMX fragment for detail panel.
SSE /events GET SSE endpoint for real-time config change notifications.
Admin /admin/<yang-path> GET/POST Administrative commands.
Auth /login POST Login (no auth).
Static /assets/ GET CSS, JS, images (no auth).

/ redirects to /show/.

Navigation

The left panel is a Finder-style column browser, the kind macOS users will recognise. You click into a container, a new column slides in to the right, and you keep going until you hit a leaf or a list. Three columns are visible at a time, scrolling horizontally as you go deeper.

Named containers (lists with YANG keys, like peer and group) appear above unnamed ones (local, timer), separated by a horizontal rule. Lists with unique constraints render as a table in the detail panel, with the key and unique fields as columns. You rename, edit, and delete entries inline. The + new button under every list opens a server-rendered form, with YANG types validated before the entry is created.

When you are inside a list entry, the detail panel shows a context heading at the top (PEER upstream) so you do not need the breadcrumb to know where you are.

Editing, diffing, committing

Each authenticated user gets an independent draft session. Your edits are tracked per user and never affect other users until you commit.

Text and number fields auto-save one second after you stop typing, in addition to saving on blur and Enter. The commit bar at the bottom of the page tracks the count of pending changes. Click "Review and Commit" to see a diff and either commit or discard.

Conflicts with another user are detected at commit time. The conflict report names the paths and shows both your value and the other user's value. You resolve them and try again.

If a colleague commits while you have the page open, a Server-Sent Events stream pushes a notification banner with their username and a Refresh button. The SSE broker supports up to 100 concurrent clients.

The editor manager allows up to 50 concurrent draft sessions. Idle sessions (no activity for one hour) are evicted when capacity is reached.

Config download and upload

You can move the whole configuration through the browser. GET /config/download streams the committed config as a ze.conf text attachment. Any authenticated session may download it, and the download is audit-logged.

POST /config/upload replaces the entire configuration from an uploaded file. The upload is validated exactly like a commit: an invalid config is rejected with the validation error (HTTP 400) and nothing is applied. A valid config is applied, the reload fires, and the action is audit-logged. Upload is an edit action, so read-only sessions are refused. The body is capped to reject oversized uploads.

The CLI bar

Every page has a CLI bar at the bottom that takes the same grammar as the SSH shell. The bar carries the current URL path as context, so a set or delete runs against whatever you are looking at. Tab completion is context-aware: at /show/bgp/peer/upstream/, typing set and Tab offers the children of that peer entry, not root-level items.

Command Effect
edit <path> Navigate to a config path.
set <leaf> <value> Set a value at the current context.
delete <leaf> Delete a value at the current context.
show [path] Display config text at the current or given path.
top / up Navigate to root or up one level.
commit / discard Apply or abandon pending changes.
who List active web editing sessions.
help List available commands.

There is also a terminal mode for when you want a scrollback shell in the browser.

Admin command tree

The /admin/ tree exposes administrative RPCs through the same finder-style column navigation as the config tree. GET renders the navigation and command forms; POST executes the command. The tree is derived from the ze-bgp-api YANG RPCs.

Group Subcommands
peer list, show, summary, capabilities, statistics, add, remove, teardown, clear-soft, flush
route update, borr, eorr, raw
cache list, retain, release, expire, forward
system commit, subscribe, unsubscribe, events

Leaf commands (those with no sub-commands) render a parameter form in the detail panel. POST to /admin/<group>/<command> executes the command and returns the result.

Workbench V2 (default)

The Workbench is now the default web UI. It provides:

  • Two-level navigation: top bar for domains (Dashboard, BGP, Config, System, Specs), sidebar for sub-pages.
  • Dashboard: hostname, uptime, version, memory usage at a glance. Live BGP summary data and SSE log stream.
  • Domain pages: per-peer detail with capabilities, statistics, flush, and teardown controls. Configured interfaces with canonical kernel types.
  • Integrated CLI page: full terminal-mode CLI in the browser.
  • Structured log viewer: parses and displays JSON log output with filtering.
  • Theme: unified CSS custom properties, switchable at runtime.

The previous Finder-style UI is still accessible by setting ZE_WEB_UI=finder. The --web-only flag on ze cli launches the daemon with only the web UI (no interactive CLI session).

Localization and small screens

The UI ships an English base catalog and a French locale. The locale is chosen from the browser's Accept-Language header, and any key missing from a non-English catalog falls back to English, so a partial translation never renders a blank label.

The stylesheet carries a small-screen layout down to 390px (iPhone-class portrait), with a horizontal-scroll guard so the page body never scrolls sideways. Wide content scrolls inside its own container instead.

Display decorators

Some leaves are annotated at render time with a friendlier form beside the raw value:

Value Annotation
An IP address Its reverse-DNS (PTR) hostname.
A standard community in ASN:value form Its well-known RFC name (for example 65535:65281 shows as no-export).

Decoration is best-effort: a failed DNS lookup, or a community with no well-known name, simply shows the raw value with no annotation. These join the existing ASN-name decorator, which annotates an AS number with its organization name.

Looking Glass pagination

The Looking Glass route-list API accepts limit and offset query parameters to page through large tables (for example ?limit=50&offset=100). Without them a request returns the full list unchanged. limit=0 means unlimited, an offset past the end returns an empty list, and a non-numeric or negative value is rejected with HTTP 400.

See also

Adapted from main/docs/features/web-interface.md and main/docs/guide/web-interface.md.

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally