Skip to content

Releases: J000K3R/probeglass

v0.2.2

Choose a tag to compare

@github-actions github-actions released this 18 Oct 15:07

Container image: ghcr.io/j000k3r/probeglass:0.2.2

Every change since the first release, in full. This is
CHANGELOG.md
as it stands at this tag.


Changelog

All notable changes to this project are documented in this file.

The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.

What each release holds, one line each. Every version below is written out in
full; the release page for a tag carries its own section of this file, so what is
here and what the release says are the same document.

Version Released In one line
[0.2.2] 2026-10-18 A symbol on every sensor, place and group — ours, yours, or searched for online — and one set of measurements for the whole dashboard
[0.2.1] 2026-10-16 A sensor under maintenance says so
[0.2.0] 2026-10-16 Maintenance windows, a second interface language, and the container as the only thing that ships
[0.1.0] 2026-10-12 The first release: sensors, history, incidents, alerts, accounts, and the dashboard

[0.2.2] - 2026-10-18

Added

  • Dependencies between sensors — a power cut is one outage, not thirty. A sensor
    can name another as the one it sits behind, and while that one is down the sensor is
    excused: it opens no incident of its own, sends no alert, and the checks it fails
    in the meantime do not count against its uptime. Its status still says what the probe
    found, and its card carries a badge saying the downtime is a consequence rather than
    an outage of its own.

    • Chains work: router → switch → the things on the switch. Circles and a parent
      that does not exist are refused when the sensor is saved.
    • Only a confirmed outage counts. A parent that is merely flaky — one lost ping —
      excuses nothing, or a single dropped packet on the router would quietly stop thirty
      sensors from alerting.
    • The chain is walked, not just the first link, so a sensor two levels down is
      excused by the same router.
    • A sensor behind a parent that recovers while it is still failing earns its own
      incident back
      : it uses up its retries again and the new outage is dated from
      after the parent came back.
    • Set in the sensor editor, where the picker leaves out the sensor being edited, and
      in the configuration file as depends_on. A file may declare them in any order.

    This is the same mechanism as a maintenance window and not a second one. A window is
    something a person said in advance; a parent that is down is something that happened
    to the sensor rather than by it, and both mean the same thing to the arithmetic. So
    the marker became the general one: results.maint is results.excused now, with
    excused_reason beside it, and the rollup counts are named for what they are. The
    boundary handling is shared, which is most of why this is not a parallel copy of the
    window feature.

  • A symbol on every sensor, place and group — one of ours, or a picture of your own.
    A sensor, a site and a group's heading can each carry an icon, drawn beside the name
    in every view: the cards, the list, the tree and the wall, and in the heading of the
    sensor's own window. In the sensor editor the symbol stands in the name row itself,
    as a button the size of the field: choosing one is a click on the picture that will
    be drawn, not a trip to a field called "Icon" further down the form.

    • Two kinds of symbol. Twenty-six drawings ship inside the binary — router,
      switch, server, NAS, container, cloud, printer, camera — and they follow the theme,
      so one file is right in both themes and under all six accents. Beyond those, an
      image can be uploaded: PNG, JPEG or GIF, at most 64 KiB and 512 pixels a side.
    • Uploaded images live in the database, not on disk. "One SQLite file, and
      copying it is the whole backup" is a promise this project makes in three places,
      and an icon in a directory beside the database would quietly make it false — the
      copy would come back without them. They are small: a hundred at the cap are six
      megabytes.
    • No SVG, and that is not a preference. An SVG is not an image but a document:
      it may carry script and external references, and it would be served from this
      dashboard's own origin, where that script would run with the session cookie of
      whoever looked at it. What an upload may be is decided by reading the file, never
      by its name or the type the browser claimed for it.
    • An image that something is still wearing cannot just disappear. Deleting one
      is refused while sensors, sites or groups point at it, and the refusal says how
      many. Saying "clear" as well takes it off them and deletes it in the same
      transaction.
    • Groups have settings, and are still not rows. A group exists because somebody
      typed its name on a sensor: no foreign key, no create step, and nothing to keep in
      step when a sensor is renamed. What is stored about a group is its symbol, the
      colour of its heading and its place in the order. Forgetting a group removes those
      and leaves every sensor exactly where it was.
    • A group's colour is one of six names, never a hex value, for the reason the
      accent setting is one: every colour in this interface exists twice, once per
      theme, and a stored #f59e0b would be the dark theme's amber drawn on somebody's
      white page.
    • Built-in drawings are drawings and nothing else. They are the files that ship
      in the binary and are served from the dashboard's own origin, so a test holds every
      one of them to that: no <script>, no onload, no external reference.
    • The configuration file takes both, as icon: builtin:router on a sensor or a site.
      It has to be able to: a sensor the file declares is written from the file whole on
      every start, so a column the file could not name would be cleared each time the
      daemon came up. probeglass doctor checks the same references, because a file
      doctor accepts has to be a file serve applies.
    • The backup carries all of it — the columns, the group settings, and the uploaded
      images with their bytes. The image id is the one row in that document that keeps
      its identity through a restore: a sensor's icon column holds upload:7 as plain
      text with no foreign key behind it, so an image that came back under a different
      number would leave every reference pointing at whatever else landed there.
    • The four example sensors a fresh installation starts with carry a symbol, and so
      does the demo data set, so the feature is on the first dashboard anybody looks at
      rather than in a settings page nobody opened.

    Sensors and sites got a column each and groups a small table of their own; both are
    migration 9 and apply themselves on the next start. A group was deliberately not
    turned into a row with sensors pointing at it: that would make creating a group a
    step of its own and reach into the configuration file, the backup, the example data
    and every delete path, and a heading somebody typed is not worth that.

  • The picker searches Dashboard Icons when the symbol
    you want is not one of the twenty-six.
    A field at the top of the picker takes a
    name, and the results come back with their pictures beside them.

    Choosing one imports it: the picture is downloaded once and stored as an ordinary
    uploaded icon — same table, same limits, same backup. That is the whole design and it
    is deliberate. Drawing it from the CDN would put somebody else's server in the path
    of every page load and take the image out of the one SQLite file a backup copies, so
    what is taken from the catalogue is a picture, once, and nothing after that depends
    on it being reachable.

    • The server asks, the browser never does. The catalogue's index is fetched and
      cached in memory by the daemon and revalidated with a conditional request on every
      search, so an icon added upstream is found by the search looking for it and the
      usual search costs an empty response rather than 1.2 MB. The previews are served
      through this installation's own route, which is also why the content policy still
      allows images from this origin and nowhere else.
    • A container with no route out says so. The answer to a search carries an
      offline flag rather than failing, and the field says the catalogue cannot be
      reached and points at the site. The built-in drawings and everything already
      uploaded keep working.
    • Only PNGs are taken, and they go through the same decode an upload does — no
      SVG, ever, and a picture that would be refused as an upload is refused here too.
    • A picture larger than an icon may be is made to fit, not refused. The
      catalogue's logos are not all 512 square — a wide one is 623×512, one is
      1123×512 — and the limit that keeps uploads small would otherwise turn a search
      result into an error. An imported picture is reduced to what the dashboard draws
      (an area average, never enlarged); a file somebody picked themselves is still
      refused when it is too big, because shrinking their own file without asking
      would be a surprise. The same goes for a picture over the byte limit: it is read
      from the CDN whole and reduced until it fits, rather than cut off at the icon
      limit — a file cut in half cannot be decoded at all, and the refusal then quotes
      the length of the cut instead of the picture's.

    The catalogue is the work of Dashboard Icons
    (Apache-2.0); the pictures are the logos of the projects they belong to, and the
    picker credits both.

Changed

  • The settings say which channel the installation is on. Settings → Help and
    m...
Read more

v0.2.1

Choose a tag to compare

@github-actions github-actions released this 16 Oct 12:05

Container image: ghcr.io/j000k3r/probeglass:0.2.1

Every change since the first release, in full. This is
CHANGELOG.md
as it stands at this tag.


Changelog

All notable changes to this project are documented in this file.

The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.

What each release holds, one line each. Every version below is written out in
full; the release page for a tag carries its own section of this file, so what is
here and what the release says are the same document.

Version Released In one line
[Unreleased] — Nothing yet
0.2.1 2026-10-16 A sensor under maintenance says so
[0.2.0] 2026-10-16 Maintenance windows, a second interface language, and the container as the only thing that ships
[0.1.0] 2026-10-12 The first release: sensors, history, incidents, alerts, accounts, and the dashboard

[Unreleased]

Nothing yet.

0.2.1 - 2026-10-16

Added

  • A sensor inside a maintenance window says so. Its card and its row carry a
    violet Maintenance badge beside the status, the card is ringed in the same
    colour, and the tree, the wall and the map pick it up too. The status itself does
    not change: a box that is not answering is still red, because that is true — what
    the badge adds is the sentence somebody needs in order to decide whether to get up.

    This was a gap rather than a change of mind. 0.2.0's API published the flag from the
    day the feature landed and the dashboard used it in one place, the "running now" mark
    in the window list, and nowhere on a sensor — so a window did everything it promised
    and nothing on screen admitted it. Reported by the first person to use the feature.

Fixed

  • Switching the language no longer races the settings page. The page is rebuilt
    when the language changes, and the redraw was not waited for, so a control could be
    replaced under whoever was using it. The rebuild is awaited now.
  • Long sensor names are no longer broken mid-word. The card's header wraps the
    badges onto a second line rather than squeezing the name until "Internet gateway"
    comes out as "Inter net gate way".

[0.2.0] - 2026-10-16

Added

  • Maintenance windows. Tell the installation in advance that a box is allowed
    to be away — the nightly snapshot, the Saturday the disk gets swapped — and the
    checks that fail in that period open no incident, send no alert, and are left out
    of the uptime figure.

    • A window covers one sensor or a whole group, repeats weekly on chosen
      days
      or covers one stretch of time, and is created in Settings →
      Monitoring → Maintenance windows. A weekly window is read in the zone the
      person making it is in; the form fills that in from the browser, because a
      container has no idea where its operator lives.
    • The probe keeps running. A window is not a pause: the result is still
      recorded, so a box that comes back early shows up in its chart as having come
      back. What is suppressed is the claim that somebody needs to do something.
    • The arithmetic follows the marker into the rollups. A sample left out of
      today's figure has to stay left out of next month's too, and the raw rows are
      gone by then — so the count is carried into the hourly and daily tables by the
      rollup itself, in two columns rather than one, because a window is a period and
      not a promise and the box may come back early.
    • An outage that was already open when a window begins is closed with a note
      saying why, and nothing is sent — the message that opened it already went out.
      If the box stays away, a new outage opens once it has failed its way past the
      retries again, dated from after the window. A recovery inside a window is
      silent, because no "down" was ever sent.
    • A window applies from the moment it is saved. The checks already recorded
      are not rewritten, which is stated in the documentation rather than left to be
      discovered.
  • A second interface language, and the switch for it. German joins English.

    Every word the dashboard draws now comes out of a message catalogue rather than
    out of the markup, so the next language is one file and one entry in a list,
    and no code at all:

    • internal/web/assets/i18n.<code>.js beside the English reference in
      i18n.js, holding the same keys in the same order with the same placeholders.
      A test compares the two key by key, in order, and compares both against the
      keys the interface actually asks for — in index.html and in every t('…')
      call in the scripts — so a missing word and a mistyped one both fail the build
      rather than reaching the screen.
    • The code in the two lists that already say what the interface offers: the Go
      whitelist that validates a stored preference, and the available list the
      picker is drawn from.
  • The switch, in Settings and in the account menu, taking effect on the view
    you are already looking at rather than on the next page load. Each language is
    named in its own language — "Deutsch", not "German" — because the reader who
    needs that entry is the one who cannot read the rest of the list.

  • Dates, numbers and relative times follow it too. Intl reads the browser's
    language rather than the document's, so every formatter is now handed the chosen
    one explicitly, and "5 min ago" under a card is a catalogue message like any
    other word.

Changed

  • A stored language follows the account, like the theme, the accent, the
    density and the layout, rather than the installation. An installation that has
    never chosen one behaves exactly as before and reads English.

Removed

  • The binary releases for darwin, windows, freebsd and linux. 0.1.0 shipped
    seven zip files; a release now ships the container image and nothing else. The
    archives promised a second way to run ProbeGlass that no document described,
    and two things would not have survived it: the docker sensor talks to the
    Docker Engine over a unix socket, which Windows does not have, and doctor
    tells you to run it with docker exec. What is gone is the publishing of other
    platforms, not the ability to compile — make build still builds for whatever
    machine you are on.

    The checksums.txt file and its Sigstore signature went with the archives,
    because there was nothing left to check a download of. The release workflow no
    longer requests an OIDC token at all. The image itself is not signed; if that
    is wanted it would be a small addition of its own.

Notes

Three surfaces are deliberately still English, and are meant to stay that way:

  • the watchdog's own page, which has to be readable in exactly the situation
    where the dashboard's scripts did not load;
  • the doctor findings, which are the CLI's output;
  • the channel types and their setup recipes, which the server sends as its own
    text.

The probe messages the server writes into the history — HTTP 200 OK, no such host — are data rather than interface and read the same in every language.

[0.1.0] - 2026-10-12

The first release: a working foundation that monitors, records, and alerts, with
the structure in place to grow. What follows is the whole of it — the feature set
it lands with, and every change made on the way to the tag.

Added

  • Sensors — HTTP(S), TCP (with optional TLS handshake and send/expect
    exchange), ICMP ping, and DNS (A, AAAA, CNAME, MX, TXT, NS, SRV, PTR, with an
    optional custom resolver). Each type validates its own target and options, in
    the UI as well as on save.
  • Dashboard — live status grid fed by Server-Sent Events, per-sensor
    response-time charts, uptime bars, sparklines, incident timeline, search,
    grouping, and tags. Theme (auto/dark/light), accent colour, density, and
    layout are selectable in Settings.
  • History — three resolutions with retention: raw samples for 7 days, hourly
    rollups for 90 days, daily rollups forever. Exactly one resolution answers any
    given range, so no probe is counted twice; gaps are reported as gaps.
  • Incidents — a state machine per sensor: a configurable number of
    consecutive failures before an incident opens, repeat alerts while it stays
    open, and a recovery alert naming how long the sensor was down. State is
    rebuilt from the database on restart, so a restart neither loses an outage nor
    re-announces one.
  • Alerts — Telegram, Discord, Matrix, ntfy, Slack, and generic webhooks with
    HMAC-SHA256 request signing. Per-sensor channel assignment, per-sensor reminder
    intervals, custom title and body templates with a safe fallback when a template
    is broken, and a test button per channel.
  • Authentication — first-run setup screen, bcrypt password hashing,
    HMAC-signed session cookies, an API key for scripts, cross-site protection for
    cookie-authenticated writes, and an in-memory login rate limit.
  • Configuration — YAML file, PROBEGLASS_* environment variables, and
    command-line flags with a documented precedence order, plus day and week
    duration suffixes for retention settings.
  • Declarative sensors and channels — declare them in the configuration file
    and they are re-applied on every start.
  • API — a documented JSON API for sensors, history, incidents, channels,
    settings, and an SSE event stream. Sensor updates are partial: a body changes
    only the fields it sends, and an explicit empty value clears a field.
  • CLI — serve, version, healthcheck (used by the image's
    HEALTHCHECK, so no shell is needed), and seed --demo for a synthetic week
    of history.
  • Packaging — multi-arch container image (amd64...
Read more

v0.2.0

Choose a tag to compare

@github-actions github-actions released this 16 Oct 11:37

Container image: ghcr.io/j000k3r/probeglass:0.2.0

Every change since the first release, in full. This is
CHANGELOG.md
as it stands at this tag.


Changelog

All notable changes to this project are documented in this file.

The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.

What each release holds, one line each. Every version below is written out in
full; the release page for a tag carries its own section of this file, so what is
here and what the release says are the same document.

Version Released In one line
[Unreleased] — Nothing yet
[0.2.0] 2026-10-16 Maintenance windows, a second interface language, and the container as the only thing that ships
[0.1.0] 2026-10-12 The first release: sensors, history, incidents, alerts, accounts, and the dashboard

[Unreleased]

Nothing yet.

[0.2.0] - 2026-10-16

Added

  • Maintenance windows. Tell the installation in advance that a box is allowed
    to be away — the nightly snapshot, the Saturday the disk gets swapped — and the
    checks that fail in that period open no incident, send no alert, and are left out
    of the uptime figure.

    • A window covers one sensor or a whole group, repeats weekly on chosen
      days
      or covers one stretch of time, and is created in Settings →
      Monitoring → Maintenance windows. A weekly window is read in the zone the
      person making it is in; the form fills that in from the browser, because a
      container has no idea where its operator lives.
    • The probe keeps running. A window is not a pause: the result is still
      recorded, so a box that comes back early shows up in its chart as having come
      back. What is suppressed is the claim that somebody needs to do something.
    • The arithmetic follows the marker into the rollups. A sample left out of
      today's figure has to stay left out of next month's too, and the raw rows are
      gone by then — so the count is carried into the hourly and daily tables by the
      rollup itself, in two columns rather than one, because a window is a period and
      not a promise and the box may come back early.
    • An outage that was already open when a window begins is closed with a note
      saying why, and nothing is sent — the message that opened it already went out.
      If the box stays away, a new outage opens once it has failed its way past the
      retries again, dated from after the window. A recovery inside a window is
      silent, because no "down" was ever sent.
    • A window applies from the moment it is saved. The checks already recorded
      are not rewritten, which is stated in the documentation rather than left to be
      discovered.
  • A second interface language, and the switch for it. German joins English.

    Every word the dashboard draws now comes out of a message catalogue rather than
    out of the markup, so the next language is one file and one entry in a list,
    and no code at all:

    • internal/web/assets/i18n.<code>.js beside the English reference in
      i18n.js, holding the same keys in the same order with the same placeholders.
      A test compares the two key by key, in order, and compares both against the
      keys the interface actually asks for — in index.html and in every t('…')
      call in the scripts — so a missing word and a mistyped one both fail the build
      rather than reaching the screen.
    • The code in the two lists that already say what the interface offers: the Go
      whitelist that validates a stored preference, and the available list the
      picker is drawn from.
  • The switch, in Settings and in the account menu, taking effect on the view
    you are already looking at rather than on the next page load. Each language is
    named in its own language — "Deutsch", not "German" — because the reader who
    needs that entry is the one who cannot read the rest of the list.

  • Dates, numbers and relative times follow it too. Intl reads the browser's
    language rather than the document's, so every formatter is now handed the chosen
    one explicitly, and "5 min ago" under a card is a catalogue message like any
    other word.

Changed

  • A stored language follows the account, like the theme, the accent, the
    density and the layout, rather than the installation. An installation that has
    never chosen one behaves exactly as before and reads English.

Removed

  • The binary releases for darwin, windows, freebsd and linux. 0.1.0 shipped
    seven zip files; a release now ships the container image and nothing else. The
    archives promised a second way to run ProbeGlass that no document described,
    and two things would not have survived it: the docker sensor talks to the
    Docker Engine over a unix socket, which Windows does not have, and doctor
    tells you to run it with docker exec. What is gone is the publishing of other
    platforms, not the ability to compile — make build still builds for whatever
    machine you are on.

    The checksums.txt file and its Sigstore signature went with the archives,
    because there was nothing left to check a download of. The release workflow no
    longer requests an OIDC token at all. The image itself is not signed; if that
    is wanted it would be a small addition of its own.

Notes

Three surfaces are deliberately still English, and are meant to stay that way:

  • the watchdog's own page, which has to be readable in exactly the situation
    where the dashboard's scripts did not load;
  • the doctor findings, which are the CLI's output;
  • the channel types and their setup recipes, which the server sends as its own
    text.

The probe messages the server writes into the history — HTTP 200 OK, no such host — are data rather than interface and read the same in every language.

[0.1.0] - 2026-10-12

The first release: a working foundation that monitors, records, and alerts, with
the structure in place to grow. What follows is the whole of it — the feature set
it lands with, and every change made on the way to the tag.

Added

  • Sensors — HTTP(S), TCP (with optional TLS handshake and send/expect
    exchange), ICMP ping, and DNS (A, AAAA, CNAME, MX, TXT, NS, SRV, PTR, with an
    optional custom resolver). Each type validates its own target and options, in
    the UI as well as on save.

  • Dashboard — live status grid fed by Server-Sent Events, per-sensor
    response-time charts, uptime bars, sparklines, incident timeline, search,
    grouping, and tags. Theme (auto/dark/light), accent colour, density, and
    layout are selectable in Settings.

  • History — three resolutions with retention: raw samples for 7 days, hourly
    rollups for 90 days, daily rollups forever. Exactly one resolution answers any
    given range, so no probe is counted twice; gaps are reported as gaps.

  • Incidents — a state machine per sensor: a configurable number of
    consecutive failures before an incident opens, repeat alerts while it stays
    open, and a recovery alert naming how long the sensor was down. State is
    rebuilt from the database on restart, so a restart neither loses an outage nor
    re-announces one.

  • Alerts — Telegram, Discord, Matrix, ntfy, Slack, and generic webhooks with
    HMAC-SHA256 request signing. Per-sensor channel assignment, per-sensor reminder
    intervals, custom title and body templates with a safe fallback when a template
    is broken, and a test button per channel.

  • Authentication — first-run setup screen, bcrypt password hashing,
    HMAC-signed session cookies, an API key for scripts, cross-site protection for
    cookie-authenticated writes, and an in-memory login rate limit.

  • Configuration — YAML file, PROBEGLASS_* environment variables, and
    command-line flags with a documented precedence order, plus day and week
    duration suffixes for retention settings.

  • Declarative sensors and channels — declare them in the configuration file
    and they are re-applied on every start.

  • API — a documented JSON API for sensors, history, incidents, channels,
    settings, and an SSE event stream. Sensor updates are partial: a body changes
    only the fields it sends, and an explicit empty value clears a field.

  • CLI — serve, version, healthcheck (used by the image's
    HEALTHCHECK, so no shell is needed), and seed --demo for a synthetic week
    of history.

  • Packaging — multi-arch container image (amd64, arm64, armv7) on a
    distroless, non-root base with the dashboard embedded; static binaries for
    Linux, macOS, Windows, and FreeBSD; CI running formatting, vetting,
    go test -race, a seven-platform build, and golangci-lint.

  • The examples a fresh installation starts with stand at two places. The four
    invented sensors carried a week of past but nowhere to be, so the map — the one
    screen a new installation had nothing at all to say about — was empty behind the
    button that draws it. They stand on the two places the demo data set uses, a
    "Homelab" and a rented server somewhere else, each with real coordinates, because
    a pin in the Gulf of Guinea is what a missing coordinate pair would look like and
    is the one thing on that map that reads as a bug. Both carry the example mark with
    the sensors, so the removal button takes them along rather than leaving two empty
    pins behind, and the panel that counts the example data counts them now: a place
    the removal would leave holding a sensor of your own stays, and the number on the
    button is that same number. The names and the coordinates are asked of the demo
    data set rather than copied from it, which matters the first time somebody loads
    that data after a fresh install: the loader leaves a place that is already there
    alone, so the two sets fold into one pin each instead of drawing a second on...

Read more

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 12 Oct 09:30