ESC
> PressHaven alpha
Home › Docs ›Getting Started › Dashboard Guide

Dashboard Guide

Every page of the PyQt6 operator dashboard: what it is for, what to try and what to watch for

The dashboard in dashboard/ is a PyQt6 desktop app that configures, deploys and operates both stacks, on this machine or on remote hosts over SSH. It also acts as a teaching tool: every page has an in-app guide (press F1), and the Knowledge Base page has guided labs. This page describes each page and the setup flow around them. For the setup steps in order, see Getting Started.

Launching

cd dashboard
./run.sh

On the first run, run.sh creates venv/ by itself. You do not have to install anything with pip by hand:

  1. If notify-send is installed, a desktop notification appears straight away. This matters when the app is started from the desktop launcher, where nothing else shows until Qt is available.
  2. It creates the venv, upgrades pip and installs PyQt6 on its own.
  3. It opens a graphical progress window (setup_progress.py) while the rest of requirements.txt installs (PyQt6-WebEngine, PyQt6-Charts).

On every launch, run.sh also checks the X11 keyboard layout (see Troubleshooting) and then runs main.py. To rebuild the environment from scratch, delete venv/ and run ./run.sh again.

Dashboard.desktop is an XDG launcher entry with Terminal=false. Its Exec, Path and Icon lines contain absolute paths from the author's machine. Change them to your checkout's path before copying the file to ~/.local/share/applications/.

First-Run Wizard

The wizard opens until a first run completes (on a fresh checkout, or after deleting state.json). To run it again, go to Connectors & Config → Re-run setup wizard. A re-run loads the existing .env values rather than clearing them, so you can use it to fix a single field. A step strip at the top of each page shows which steps are done, which one is current and which are left.

StepWhat it does
WelcomeIntroduction. Also shows the dependency banner if docker, the Compose plugin, ssh or rsync is missing.
Remote hosts (optional)Marks ids and/or siem as remote and asks for each one's SSH host, port, user, key and remote path.
Edge .envEdits ids/.env. For a local target with no .env yet, the form starts from .env.example. For a remote target, the file is fetched over SSH and saved back to the remote. A missing remote file gives an empty form. If the fetch fails, the local file is shown instead, with a note explaining why.
SIEM .envThe same for siem/docker/.env.
Certificates (optional)Generate all certificates now creates the SIEM CA and service certificates, then the edge nginx certificate. You can also do this later on the PKI & Certificates page.
DoneWrites state.json and opens the main window.

Warning Banners

Banners appear above every page, so a problem shows up on any page you are on.

  • Missing dependency. Shown when docker or the Compose plugin is missing (both are required), or ssh or rsync is missing (needed only for remote features). The banner offers an install command for your distribution. The commands are listed under Prerequisites.
  • Host settings. Shown when a host lacks a kernel setting that a stack needs but cannot set for itself: vm.overcommit_memory=1 for Redis on the edge host, and vm.max_map_count=262144 for Elasticsearch on the SIEM host. Every target in use is checked, including remote ones over SSH. The banner shows the commands that fix it.

The left rail groups the pages into five sections. Each section shows its main pages and keeps the rest in an overflow list. You can edit the rail layout, and the View menu always lists every page.

ShortcutAction
Ctrl+KCommand palette: jump to any page by name. Also a toolbar button.
F1Help for the current page: what it is for, what to try, what to notice.
Ctrl+1…9Open the Nth visible page in the rail.
Ctrl+RRefresh the current page.
Ctrl+FFocus the Forensics Analysis search box.
GroupIn the railIn overflow
OverviewOverview—
MonitorLive Events, Global Visualization, SIEM AnalyticsLog Pipeline, Workload Telemetry, Forensics Analysis
Threat OperationsAttack Simulation, Adversary Sessions, Network IDS (Suricata), Detection PolicyPattern Database, Signature Simulation, Pool Scaling, Segmentation Validation, Pool State Store
ManageWorkloads, WordPress Studio, WordPress Update, Connectors & ConfigPKI & Certificates, Backup & Recovery
ReportingKnowledge BaseReporting

Pages that poll (Log Pipeline, Pool Scaling, Workload Telemetry) refresh only while they are visible. Docker, SSH and Redis calls run on background threads, so a slow or unreachable remote host does not freeze the window.

Overview

The landing page. It shows the current risk score, one health line for each stack and a list of recent security events. It takes its data from the shared docker compose ps poller and the app-wide security-event feed, so it starts no background work of its own. The quick-action tiles jump to the relevant page.

Monitor

Live Events

A stream of every decision the reverse proxy's pattern analyzer makes. It does not depend on Kibana or the SIEM. Each request writes a burst of log lines (scoring signals, routing steps, the final score and one outcome line), and the page collapses each burst into a single row with the outcome, the final score, the signals that fired and the request latency. When first opened, it fills in recent history from one docker compose logs read.

Global Visualization

A diagram of both stacks' containers and how they connect, with a details panel for the selected node.

Colour / stateMeaning
healthyRunning with a passing healthcheck.
runningRunning; the service has no healthcheck.
unhealthyRunning but failing its healthcheck.
exited (ok)A one-shot job that finished with exit code 0, such as a seed or init job.
exited (bad)Exited with a non-zero code.
created (amber)Created but not started.
downNo container.
  • Nodes show uptime. A red !N badge counts the log lines that contain error or a word starting with fail or fault (case-insensitive). Click the badge to see only those lines, read with --tail=all.
  • Each node has two quick icons: ⬇ exports its logs to a file, and ↗ opens its web UI.
  • The details panel has Restart, View logs, Open web UI and Open shell. The shell runs docker exec -it … sh -c 'exec bash || exec sh', over SSH for remote targets.

A green vector_outbound node only means the container is running. It does not show whether logs are reaching the SIEM; use Log Pipeline for that.

SIEM Analytics

An embedded browser that opens Kibana at https://<SIEM host or localhost>:5601/. You can edit the address bar.

  • Autologin fills in Kibana's login form with the SIEM stack's ELASTIC_USERNAME / ELASTIC_PASSWORD. If it cannot read them, it does nothing and the normal login form stays usable.
  • Remember credentials (on by default) keeps a persistent browser profile, so you stay logged in across restarts. Every other embedded browser in the app uses a private (off-the-record) profile.
  • Bookmarks open the saved dashboards (Attack Patterns, Threat Decisions & Decay) and Discover. Export PDF… saves a full-page screenshot of every bookmarked page, each with a short explanation of what it shows. See Kibana Dashboards.

Log Pipeline

Shows whether the edge's Vector shipper is actually delivering logs to the SIEM. It combines four checks: shipping is configured (ELK_ENABLED / VECTOR_HOST), the shipper container is running, its recent log has no delivery errors since its last passing healthcheck, and vector_inbound is running on the SIEM side. It refreshes every 15 s. To check it works, stop vector_inbound and the page should turn to failing.

Workload Telemetry

Live resource use per container for the selected target, in an htop-style table: CPU, memory, PIDs, network and block I/O, and on-disk log size. Three graphs show CPU %, memory and log size over time, with one line per container plus a bold average line. Attack markers make it easy to see what a scenario cost.

Forensics Analysis

A grep-style search across all containers of every configured target at once, local and remote. It runs docker compose logs --tail=N for each selected target and keeps docker's per-service colours in the results. Matching is done on the text with colour codes removed, so a code cannot split a search term. Options:

  • Regex mode, a time range (docker's --since) and search history.
  • Named saved searches.
  • Collapsing repeated lines into one (×N).
  • Export to plain text or JSON Lines.

Threat Operations

Attack Simulation

An embedded browser on the shop, a pattern-preset dropdown and a live pattern-analyzer log. The proxy routes the browser like any other visitor, so a request may end up on production or on a honeypot pool.

  • Run pattern (curl) sends the preset's real request, with its headers and body. Run pattern (browser) opens the preset's URL in the embedded browser as a plain GET, using the browser's current session. These are separate buttons on purpose: an earlier version sent both requests from one click, and the log showed two different signal profiles for what looked like a single run.
  • What is this? explains the selected preset.
  • The Pattern analyzer tab shows a timeline of colour-coded event cards, newest first. Tick some cards and use Copy selected to copy them as text with their real log timestamps.
  • A Postman-style request builder (method, URL, headers, body) can be filled from a preset, edited, and sent with curl. It shows the raw status, headers and body.
  • Reset local score + cookies clears the embedded browser's cookie jar. Unpoison host IP clears the IP reputation that your own test runs have built up for your host.

Adversary Sessions

Lists every proxy session (session:* in session_store) with its IP, risk score, request count, verdict and honeypot pool. For the selected session it shows a plain-language summary, the IP's reputation entry, and a timeline of the suspicious requests that built up its score.

Network IDS (Suricata)

Two tabs. Alerts shows recent eve.json alerts with counts by severity, top signatures and top source IPs. Rules lists local.rules with sid, message, class and state. You can switch rules off or on (they are commented out in the file) and save, which restarts Suricata to load the edited file. See Suricata Network IDS.

Detection Policy

A form for the edge .env settings that decide who gets diverted, so you do not have to edit the raw file. It covers score decay and half-life, IP-reputation weight and shared-address handling. Each value is checked before saving. Only the changed keys are written back, and comments in the file are kept. A sentence under the form explains what the current decay settings do to a maxed-out score. nginx reads these values at startup, so the page offers to restart reverse_proxy after saving.

Pattern Database

A browsable, filterable catalogue of every pattern: Lua CVE patterns, generic signatures, header and upload rules, scanner rules, Attack Simulation presets and Suricata SIDs. Select a row to see its trigger, source, score path and lesson. The catalogue is read from patterns/patterns.json, the same file this documentation site uses (see Pattern Database). The checkboxes and the add / edit / duplicate / remove / revert / export actions change only the plugin registry (patterns/registry.json). A pattern switched off here is also dropped from Attack Simulation and Segmentation Validation runs.

Signature Simulation

Follows one browser characteristic, the screen size, all the way to the proxy's consent-gated, one-way gdpr_signature. You can resize the mock browser window on the left, and its size is the value that gets signed. Five stages are shown on the right. The two client-side stages (collect the characteristics, RSA-encrypt them into a gdpr_token) are reproduced in full. The two server-side stages (append the client IP, hash with a secret salt) are described but not shown, because only the resulting signature ever leaves the proxy. To see the idea at work, resize the window and run again: the signature changes, and returning to an earlier size gives the earlier signature back. See Device & GDPR Signature.

Pool Scaling

Shows the honeypot pool registry without running a test or reading raw Redis keys. It covers:

  • the pool count and the state of each pool;
  • the resource budget in use (memory, CPU, pool cap) and the reason growth stopped;
  • each pool's sessions and idle time;
  • pool_manager's recent build, hand-off and scale-down events.

Segmentation Validation

Opens 3 to 10 embedded browsers, each with its own private profile and cookie jar, to show how pools handle several users at once. A cookie-less request is matched to a session by a passive fingerprint, so each window also gets its own User-Agent suffix and Accept-Language; otherwise the proxy would see them as one client.

  • Open shop in all loads the shop in every window. Attack from all sends the same pattern from each window. Refresh pool state re-reads the pools.
  • Once a window's score passes the threshold, its session is bound to a pool. pool_manager builds one pool per session until it reaches its resource limit; after that, sessions share pools round-robin.
  • In the database-proxy layer, one production shop serves every window and each diverted session goes to its own honeypot database. The run then offers only the patterns that layer isolates, and tells windows apart in each database's MySQL query log by their WooCommerce session key.
  • The run can be saved as a PDF report that includes pool memory and CPU use over time, showing pools being built and later scaled down.

Pool State Store

Every key in the edge Redis (session_store): sessions, threat_ips, suricata_alerts and the rest. The table shows each key's type, TTL and size; click a row to see the full value. A bar chart shows the current threat_ips score for each IP. A dropdown chooses the local or remote edge target. The key layout is described in Lua Internals.

Manage

Workloads

Start, restart, stop and purge each project, local and remote, with the live status next to the buttons and the command output below.

  • A progress bar follows a start. The "all N up" count includes one-shot jobs that exited with code 0.
  • The log tail runs all the time. It also feeds the error badges on Global Visualization, so those keep counting whichever page is open. Download logs saves it to a file.
  • Purge runs docker compose down -v, which deletes the project's volumes, so it asks for confirmation first.
  • The Honeypot layer dropdown chooses between the WordPress-proxy level (a separate decoy stack per session) and the Database-proxy level (one shop, a decoy database per session). See Honeypot Layers.
  • You can save a start or stop as a PDF report, with Global Visualization screenshots and warnings from any failed seed jobs. See Service Start/Stop Reports.

WordPress Studio

The production wp-admin, embedded, plus a button that copies your changes out to every honeypot pool, with a progress bar and a status row per pool. The embedded browser adds the studio passthrough headers and the internal-test secret to every request, so nginx always sends wp-admin to production and never diverts an edit into a honeypot. The copy step runs the same allow-listed script as honeypot_content_sync (--once N). It copies pages, posts, products and safe settings. It never copies user accounts, orders or secrets. See WordPress Management.

WordPress Update

Checks for newer WordPress core and WooCommerce versions, then upgrades every instance in five steps:

  1. Turn the maintenance page on. This is a Redis flag with a TTL; while it is set, the edge returns 503.
  2. Update production's files and database.
  3. Re-sync the files into every pool volume.
  4. Migrate each static pool's database.
  5. Turn the maintenance page off.

If maintenance mode cannot be turned on, the run stops before touching production. Once it is on, a failed step does not stop the run; each failure is reported on its own row. The flag is always cleared at the end, and its TTL brings the site back even if the dashboard crashes mid-update.

Connectors & Config

  • .env editor for both projects, with a Local / Remote switch (a remote file is edited over SSH). Secrets are masked and have a Generate button. Refresh reloads the file. Keys that exist in .env.example but not in your .env are marked (new, from .env.example), which shows what an update added.
  • Remote targets: see below.
  • General tab: the status poll interval, and tray notifications. When these are on, the tray icon alerts you when a container becomes unhealthy or exits with an error.
  • Export / import of the whole configuration as one JSON file.
  • Re-run setup wizard.
Exported settings contain plaintext secrets

The export file includes both .env files in plain text: database, Redis, Elastic and signing secrets. Treat it like the .env files themselves.

PKI & Certificates

Regenerates certificates: all of them, the SIEM CA and every service certificate, a single service's certificate, or the edge nginx self-signed certificate. The vector-agent certificate is copied to the edge automatically. Generate certificates before the first start. The edge certificate is self-signed, so use curl -k or accept the browser warning.

Backup & Recovery

Lists the database dumps and WordPress file archives that backup_service writes under /backups, plus the end of its backup.log. From here you can:

  • restore either kind of backup onto the live production stack;
  • label (rename), delete, export or import a backup;
  • use Reset demo store, which re-runs the seed script (scripts/seed_production_db.sh) to rebuild a clean WooCommerce/Elementor shop after patterns have been run against it.

ids/backups/manage_backups.sh does the same from the command line and shares the same labels.json labels file.

Reporting

Knowledge Base

The dashboard's teaching layer, with four tabs:

  • Start here: how the system works in five steps, plus a tour of every page with links that open it.
  • Guided labs: checklists that walk through the pages. Ticked steps are saved.
  • Glossary: searchable terms.
  • Pattern lessons: one per preset, covering the attack class, OWASP Top 10, MITRE ATT&CK mapping, how the attack works and how to defend against it.
LabCovers
1. Bring the system upGenerate certificates, start ids then siem on Workloads, wait for every node in Global Visualization to turn green, then read the glossary entries for Honeypot, Reverse proxy and SIEM.
2. Watch a normal visitorReset the local score, browse the shop in Attack Simulation, and check that the requests route to PRODUCTION with a low score.
3. Fire an SQL injectionRun the CVE-2024-27956 (WP Automatic SQLi) preset with curl, read each signal and its points, check that the result is HONEYPOT, then find the session's score in Pool State Store.
4. Investigate in the SIEMFind the CVE under Top CVEs Detected in Attack Patterns, filter Discover by your IP, then search the raw logs for the CVE ID.
5. Tune the detectorDivert the browser, wait one half-life (five minutes: 100 decays to 50, below the threshold) and watch it return to production. Then repeat with THREAT_DECAY_ENABLED=false and think about why never forgiving a score causes false positives.
6. Divert sessions and watch the poolsNote the pool budget, attack from every Segmentation Validation window, check that each session gets a different pool, then read the build and hand-off events in Pool Scaling.
7. Switch the honeypot layerRun the same CVE with the WordPress-proxy layer and then with the Database-proxy layer, and compare which attack types each layer can isolate.
8. Derive a device signatureDerive a signature, resize the window and derive again, then return to the first size. The first signature comes back, which is how a visitor is recognised again after clearing cookies.

Reporting

One-click PDF exports: an auto-generated "Implementation" chapter built from excerpts of the live source tree, an architecture overview, and the Pattern/CVE matrix. A preview lists what will be included; entries whose source file is missing in your checkout are skipped.

Remote Targets

Each project (ids, siem) can run locally or on a remote host. Set the host, port, user, SSH key and remote path in Connectors & Config, then use Test connection.

  • Upload .env to remote… copies just the .env with scp.
  • Upload entire project… copies the project with rsync and shows progress. Backups, logs and volumes are left out. If the remote directory is not empty, it asks before overwriting. This needs rsync installed locally as well as on the remote.
  • Once a target is set up, every page that touches Docker or Redis (Workloads, shells, logs, Pool State Store, Suricata, Detection Policy, host-settings checks) runs its commands over SSH.

State and Settings Files

FileHolds
dashboard/state.jsonWindow geometry, the last open page, remote target settings, the poll interval, the tray toggle, the theme, the rail layout, the honeypot layer choice, Forensics search history and saved searches, recent security events and completed lab steps. It is gitignored and contains no .env contents. Delete it to get the first-run wizard again. Older files still load: keys the app does not recognise are ignored, and missing keys fall back to their defaults.
ids/.env, siem/docker/.envThe real configuration. The dashboard edits these directly, or the remote copies over SSH.
dashboard/venv/Created by run.sh. Safe to delete.

Troubleshooting

SymptomCause and fix
The app aborts at startup inside QtWebEngine on X11The X11 keyboard layout/variant cannot be compiled by xkeyboard-config (for example layout sk with variant qwertz), and QtWebEngine treats that as fatal. run.sh detects this and falls back to the layout with no variant, printing a warning. If you start main.py directly, run setxkbmap <layout> first.
Nothing happens when using the desktop launcherThe paths in Dashboard.desktop still point to the author's machine. Fix Exec, Path and Icon. On a first run, wait for the setup notification and the progress window.
Embedded browsers are blank or crashMissing Qt/Chromium system libraries. See Prerequisites.
command not found for docker, ssh or rsyncUse the install command in the dependency banner, then restart the app.
Global Visualization is green but Kibana is emptyOpen Log Pipeline. See also Runbooks.