2026-06-09 17:31:10 -07:00
2026-06-09 17:31:10 -07:00
2026-06-09 17:31:10 -07:00
2026-06-09 17:31:10 -07:00
2026-06-09 17:31:10 -07:00
2026-06-09 17:31:10 -07:00

🔥 Flare

Ephemeral, zero-dependency script telemetry for real-world automation.

Run one Python file, open the dashboard URL it prints, source one wrapper line into a script, and watch that script report back in real time.

Flare is built for short-lived operational work:

  • deployments
  • provisioning
  • migrations
  • maintenance windows
  • demos and labs
  • one-off admin scripts

It is intentionally not a long-term logging stack. There is no database, no accounts, no agents, and no setup beyond python3 flare.py.


What Flare Is

Flare gives scripts and small automation jobs a disposable telemetry dashboard.

Instead of hoping a job is still alive, your script can emit structured updates like:

  • starting
  • installing packages
  • waiting for service
  • completed
  • failed

Those updates appear live in the browser, grouped by host.

Flare is a disposable telemetry dashboard.


Why It Exists

Most observability tooling is too heavy for quick operational work.

If all you want is a live view into a script, standing up a whole logging or monitoring platform is overkill.

Flare id the opposite:

  • fast to start
  • easy to discard

Quick Start

python3 flare.py

That is all you need.

On startup, Flare prints:

  • a ready-to-open dashboard URL
  • wrapper import lines for bash / bash+python / PowerShell
  • exportable environment variables if you want to post manually
  • the exact per-run GET and POST capability URLs baked into this launch

Open the dashboard URL in a browser, then paste one of the printed wrapper lines into a script.


Basic Workflow

  1. Start Flare
  2. Open the dashboard URL from the startup banner
  3. Source one wrapper into your script
  4. Call helper functions like mon, mon_detail, mon_complete, or mon_error
  5. Watch events arrive live in the browser
  6. Export JSON or CSV if you want to keep the record

All runtime data lives in memory only.


Project Layout

flare/
├── flare.py    # server, wrappers, in-memory pub/sub
└── flare.html  # browser dashboard

flare.py uses only the Python standard library.


Wrapper Options

Pick whichever wrapper fits the target environment.

Wrapper Command shape Requirements
wrapper.sh eval "$( curl -s <printed-wrapper-url> )" bash, python3
wrapper.bash eval "$( curl -s <printed-wrapper-url> )" bash 4+, curl, openssl
wrapper.ps1 iex (irm <printed-wrapper-url>) PowerShell 5.1+ or pwsh 7+

All wrappers bake in the current runs:

  • event destination URL
  • session/topic identifier
  • bearer token
  • HMAC secret, unless disabled

Your script only needs to call helper functions.

mon "message"
mon_complete "message"
mon_error "message"
mon_detail "message" '{"key":"value"}'
  • mon — normal running/progress update
  • mon_complete — successful completion
  • mon_error — failure / error state
  • mon_detail — progress update with structured JSON detail

Example:

mon "starting backup"
mon_detail "installing packages" '{"packages":["nginx","fail2ban"]}'
mon_complete "backup finished"

Summary Channel

There is one reserved mon_detail title with special dashboard behavior:

mon_detail "flare-summary" '{"site":"phx-1","phase":"patching","owner":"shane"}'

Events sent with title flare-summary are treated as summary metadata for that host. They populate the main detail area instead of appearing as a normal log entry.

That is useful for:

  • current phase
  • change ticket / runbook identifiers
  • target version
  • site / cluster / environment
  • host-specific notes you want pinned in view

Example: Bash Script

#!/usr/bin/env bash
set -euo pipefail

# Use the exact printed wrapper URL from flare.py
eval "$( curl -sf http://SERVER:8080/REPLACE_WITH_PRINTED_GET_PATH/wrapper.bash )" || {
  echo "flare unavailable, stubbing functions" >&2
  mon() { echo "[flare] $1" >&2; }
  mon_complete() { mon "$1"; }
  mon_error() { mon "$1"; }
  mon_detail() { mon "$1"; }
}

mon_detail "flare-summary" '{"role":"db","change":"CHG-1234"}'
mon "starting server hardening"
mon_detail "system update" '{"action":"apt-get upgrade"}'

apt-get update -qq
apt-get upgrade -y -qq

mon "configuring firewall"
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw --force enable

mon_complete "hardening finished"

Example: Cloud-Init / First Boot

#cloud-config
runcmd:
  - |
    eval "$( curl -sf http://SERVER:8080/REPLACE_WITH_PRINTED_GET_PATH/wrapper.bash )"
    mon_detail "flare-summary" '{"phase":"first boot","source":"cloud-init"}'
    mon "cloud-init starting on $(hostname)"
    apt-get update -qq && apt-get upgrade -y -qq
    mon "packages updated"
    mon_complete "$(hostname) ready"

Use the exact printed wrapper URL in real usage.


Example: PowerShell

# Use the exact wrapper URL printed by flare.py
iex (irm http://SERVER:8080/REPLACE_WITH_PRINTED_GET_PATH/wrapper.ps1)

mon_detail "flare-summary" '{"phase":"patching","window":"nightly"}'
mon "starting updates"
mon_detail "patching" '{"phase":"download"}'
mon_complete "updates complete"

Security Model

Flare is still lightweight, but it is more deliberate than a naive callback endpoint.

1. Per-run session values

Each launch generates fresh values unless you provide your own:

  • bearer token
  • HMAC secret
  • topic/session identifier
  • randomized browser-facing GET base path
  • randomized POST ingest path

2. Randomized GET base path

Browser-facing resources live under a per-run random path, for example:

/<GET_PATH>/
/<GET_PATH>/flare.html
/<GET_PATH>/wrapper.sh
/<GET_PATH>/wrapper.bash
/<GET_PATH>/wrapper.ps1
/<GET_PATH>/events?topic=...

That makes sessions harder to casually enumerate and keeps one runs browser-facing resources scoped to that run.

3. Randomized POST path

Event ingest lives at a separate per-run path, for example:

/<POST_PATH>

That separates “can view” from “can submit.” Knowing the dashboard URL does not automatically reveal the POST target.

4. Bearer auth

Event streaming and publish operations are tied to a token.

5. HMAC-signed event envelopes

Wrappers sign their event content before sending it. The server validates those signatures before accepting events, and the dashboard can also surface verification status for received events.

That means Flare is not just trusting any JSON that happens to hit the endpoint with the right shape.


Why the Paths Exist

Flare uses capability-style per-run URLs.

In plain English:

  • the dashboard should not live at a predictable public root
  • wrappers should be scoped to the current run
  • event streaming should belong to the same run-specific namespace
  • message ingest should be isolated from browser-facing resources

That is why the startup banner prints the exact dashboard URL, exact wrapper URLs, and exact POST target for that run.

You are not meant to memorize or handcraft these paths. Just copy what Flare prints.


Dashboard Features

The dashboard is intentionally lightweight and host-oriented.

Current behavior includes:

  • real-time SSE event streaming
  • host-tab grouping of activity
  • running / complete / error visibility
  • structured detail rendering
  • reserved flare-summary metadata area
  • JSON export
  • CSV export
  • direct open from the startup banner URL
  • client-side session behavior with no database backend

The dashboard URL is preconfigured with the session values it needs for that one run.


CLI Options

python3 flare.py [OPTIONS]

  --host HOST        Bind address (default: 0.0.0.0)
  --port PORT        Port (default: 8080)
  --token TOKEN      Bearer token (generated if omitted)
  --secret SECRET    HMAC secret (generated if omitted)
  --topic TOPIC      Session/topic name (generated if omitted)
  --html PATH        Path to flare.html (auto-detected if omitted)
  --get-path PATH    Browser-facing GET base path (generated if omitted)
  --post-path PATH   POST ingest path (generated if omitted)
  --no-secret        Disable HMAC signing
  --verbose          Debug / validation logging

Notes

  • --topic still exists internally, but the dashboard is host-oriented in practice.
  • --get-path lets you pin the browser-facing path if you do not want a generated one.
  • --post-path lets you pin the ingest path for controlled testing.
  • --verbose is useful when testing signatures and request behavior.

Endpoints

Flares stable shape is:

Method Path Auth Purpose
GET /<GET_PATH>/ No Dashboard
GET /<GET_PATH>/flare.html No Dashboard file
GET /<GET_PATH>/wrapper.sh No Bash + Python wrapper
GET /<GET_PATH>/wrapper.bash No Pure Bash wrapper
GET /<GET_PATH>/wrapper.ps1 No PowerShell wrapper
GET /<GET_PATH>/events?topic=...&auth=...&since=all Token SSE event stream
POST /<POST_PATH> Token Publish signed or unsigned event envelope

In normal usage, you should not need to hit these by hand. The startup banner and wrappers handle it for you.


Tests

Two test helpers are included in this repo layout:

  • http_test.py — direct HTTP tests for weird paths, params, headers, methods, auth, SSE, and POST validation
  • src_test.py — source the real wrappers, then exercise mon, mon_detail, mon_complete, and mon_error

Both use one environment variable:

export __FLARE_SRC='http://SERVER:8080/PRINTED_GET_PATH/wrapper.sh'

Then run:

python3 http_test.py
bash src_test.py

http_test.py derives the dashboard, wrapper, SSE, and POST targets from the wrapper exports. src_test.py exercises both wrapper.sh and wrapper.bash from that same seed URL.


Architecture

┌──────────────┐      source wrapper       ┌─────────────┐
│ Remote Host  │ ◄──────────────────────── │  flare.py   │
│ or Script    │                           │   server    │
│              │                           │             │
│ mon()        │ ───── signed POST ──────► │  in-memory  │
│ mon_detail() │                           │   storage   │
│ mon_error()  │                           │   + SSE     │
│ mon_complete()                           │             │
└──────────────┘                           └──────┬──────┘
                                                  │
                                                  │ SSE
                                                  ▼
                                           ┌─────────────┐
                                           │  flare.html │
                                           │  dashboard  │
                                           └─────────────┘

Everything is intentionally ephemeral. If you need to keep the output, export JSON or CSV from the dashboard before shutting it down.


Tips

Graceful fallback

If Flare is unavailable, stub the functions and let the script continue.

Use the printed URLs

Because the GET and POST paths are generated per run, copying the banner output is the safest workflow.

Export before exit

Flare does not persist anything. If the session matters, export it before shutting the server down.


License

Do whatever you want with it.

S
Description
an ephemeral monitoring server written in python - pulls down shell script/powershell
Readme 57 KiB
Languages
HTML 50.6%
Python 46.6%
Shell 2.8%