Add configuration to web UI #22

Closed
opened 2026-07-05 17:56:41 +01:00 by danny · 9 comments
danny commented 2026-07-05 17:56:41 +01:00 (Migrated from gitlab.keyop.co.uk)

We would like to be able to view the current configuration from the Web UI as well as the current connections. Ideally we should also be able to edit the configuration too and restart the service if needed, but that may need to be split out to a separate ticket.

We would like to be able to view the current configuration from the Web UI as well as the current connections. Ideally we should also be able to edit the configuration too and restart the service if needed, but that may need to be split out to a separate ticket.
danny commented 2026-07-05 17:57:56 +01:00 (Migrated from gitlab.keyop.co.uk)

changed the description

changed the description
danny commented 2026-07-06 09:28:27 +01:00 (Migrated from gitlab.keyop.co.uk)

mentioned in issue #25

mentioned in issue #25
danny commented 2026-07-06 09:28:49 +01:00 (Migrated from gitlab.keyop.co.uk)

Scope

Splitting per your own hedge in the description: this ticket covers viewing the config only.
Editing + restarting is split out to #25, since it's a meaningfully bigger and more sensitive
piece of work (no live-reload path exists today - "restart" means a real process restart via
systemctl --user restart, from an authenticated web request against a process holding real
capabilities - and any edit needs the same validation config.LoadFromFile already does before
it's ever written to disk or acted on). That deserves its own design pass rather than being
bolted onto a view-only page.

Plan

webUIServer currently only receives config.WebUI (used once, to build the session store, and
never stored) - not the full running *config.Configuration. Nothing else in the request path
has access to it either.

  • Wire the config through: change newWebUIServer/runWebUI to take the full appConfig *config.Configuration instead of just appConfig.WebUI (removing the now-redundant separate
    param), store it on webUIServer, update the one call site in NFQForwarderMain.
  • New routes, following the exact pattern the existing tunnels dashboard already uses:
    • GET /config (page, wrapped in requireSessionPage - same as the dashboard)
    • GET /api/config (JSON, wrapped in requireSessionAPI - same as /api/tunnels)
    • No CSRF needed - that's only for state-changing POSTs, which a view-only page doesn't have.
  • Display: a purpose-built DTO (matching the existing webUITunnel pattern) rather than
    raw-marshaling the config struct - global settings, the web UI's own settings, the defaults
    section, and a table of connections. Since LoadFromFile already resolves defaults into each
    Connection at load time, the connections table shows the effective, already-merged
    per-connection config for free - no extra resolution logic needed. New config.html template
    reusing status.html's existing .card/table CSS, plus a small nav link between the two pages
    so it reads as one coherent site rather than a bolted-on extra page.
  • Nothing displayed here is actually secret - confirmed from the config struct: there's no
    password/token field anywhere, SSH auth is key-file-based (a path, not embedded key
    material), and web UI auth delegates to PAM. The one thing worth a design note:
    SSHKeyPath/KnownHostsPath could contain a username in an absolute path if explicitly set -
    not a new exposure though, since anyone who can pass PAM auth for this OS account already has
    shell access to read the real config file directly; displaying it verbatim doesn't change the
    trust boundary.
  • Tests: following the established webui_handlers_test.go pattern - authenticated-200 and
    no-session-401/redirect for both the page and API routes.
  • Docs: docs/README.md's web UI section, CLAUDE.md's web UI design-notes bullet.

Work happening on branch issue22_webui_config; an MR will follow referencing this issue.

## Scope Splitting per your own hedge in the description: **this ticket covers viewing the config only**. Editing + restarting is split out to #25, since it's a meaningfully bigger and more sensitive piece of work (no live-reload path exists today - "restart" means a real process restart via `systemctl --user restart`, from an authenticated web request against a process holding real capabilities - and any edit needs the same validation `config.LoadFromFile` already does before it's ever written to disk or acted on). That deserves its own design pass rather than being bolted onto a view-only page. ## Plan `webUIServer` currently only receives `config.WebUI` (used once, to build the session store, and never stored) - not the full running `*config.Configuration`. Nothing else in the request path has access to it either. - **Wire the config through**: change `newWebUIServer`/`runWebUI` to take the full `appConfig *config.Configuration` instead of just `appConfig.WebUI` (removing the now-redundant separate param), store it on `webUIServer`, update the one call site in `NFQForwarderMain`. - **New routes**, following the exact pattern the existing tunnels dashboard already uses: - `GET /config` (page, wrapped in `requireSessionPage` - same as the dashboard) - `GET /api/config` (JSON, wrapped in `requireSessionAPI` - same as `/api/tunnels`) - No CSRF needed - that's only for state-changing POSTs, which a view-only page doesn't have. - **Display**: a purpose-built DTO (matching the existing `webUITunnel` pattern) rather than raw-marshaling the config struct - global settings, the web UI's own settings, the `defaults` section, and a table of connections. Since `LoadFromFile` already resolves defaults into each `Connection` at load time, the connections table shows the *effective*, already-merged per-connection config for free - no extra resolution logic needed. New `config.html` template reusing `status.html`'s existing `.card`/table CSS, plus a small nav link between the two pages so it reads as one coherent site rather than a bolted-on extra page. - **Nothing displayed here is actually secret** - confirmed from the config struct: there's no password/token field anywhere, SSH auth is key-*file*-based (a path, not embedded key material), and web UI auth delegates to PAM. The one thing worth a design note: `SSHKeyPath`/`KnownHostsPath` could contain a username in an absolute path if explicitly set - not a *new* exposure though, since anyone who can pass PAM auth for this OS account already has shell access to read the real config file directly; displaying it verbatim doesn't change the trust boundary. - **Tests**: following the established `webui_handlers_test.go` pattern - authenticated-200 and no-session-401/redirect for both the page and API routes. - **Docs**: `docs/README.md`'s web UI section, `CLAUDE.md`'s web UI design-notes bullet. Work happening on branch `issue22_webui_config`; an MR will follow referencing this issue.
danny commented 2026-07-06 09:43:46 +01:00 (Migrated from gitlab.keyop.co.uk)

mentioned in commit 5604aef9e6

mentioned in commit 5604aef9e613be258c6ab05e447ff00c4e18f398
danny commented 2026-07-06 09:44:11 +01:00 (Migrated from gitlab.keyop.co.uk)

mentioned in merge request !68

mentioned in merge request !68
danny commented 2026-07-06 13:40:43 +01:00 (Migrated from gitlab.keyop.co.uk)

mentioned in commit 646530d3cc

mentioned in commit 646530d3ccba7c24fa9a55d2e1f619ab615c466f
danny (Migrated from gitlab.keyop.co.uk) closed this issue 2026-07-06 13:40:44 +01:00
danny commented 2026-07-06 13:42:41 +01:00 (Migrated from gitlab.keyop.co.uk)

Fixed via MR !68 and released in v1.0.6 (https://gitlab.keyop.co.uk/keyop/go/nfq_forwarder/-/releases/v1.0.6). The web UI now has a read-only Configuration view (global settings, defaults, and each connection's effective config) alongside the existing connections dashboard. Editing the config + restarting the service was split out into #25, since it needs its own design/security pass.

Fixed via MR !68 and released in **v1.0.6** (https://gitlab.keyop.co.uk/keyop/go/nfq_forwarder/-/releases/v1.0.6). The web UI now has a read-only Configuration view (global settings, defaults, and each connection's effective config) alongside the existing connections dashboard. Editing the config + restarting the service was split out into #25, since it needs its own design/security pass.
danny commented 2026-07-07 11:43:06 +01:00 (Migrated from gitlab.keyop.co.uk)

mentioned in commit 6ecbdd9b1c

mentioned in commit 6ecbdd9b1ca8549c0a284bb73f29d22856929f07
danny commented 2026-07-07 11:43:42 +01:00 (Migrated from gitlab.keyop.co.uk)

mentioned in merge request !69

mentioned in merge request !69
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
keyop-go/nfq_forwarder#22
No description provided.