Codync
免費、開源的 1:1 替代方案,取代 Grok Bot 與 Muse。從 iPhone、Mac 或 Linux 桌面將 Claude Code、Codex、Cursor 與 40+ 程式碼代理人作為持續機器人傳訊。群組聊天、主題串…
AI 翻譯
尚未收集儲存庫資訊。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
A small, self-hosted watchdog for your homelab.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Website: j000k3r.github.io/probeglass-website — what it does, with pictures ·
Documentation: j000k3r.github.io/probeglass-docs — installation, configuration, the sensor and channel references, the HTTP API, and troubleshooting
ProbeGlass is a single-container monitoring daemon: it probes your services on a schedule, keeps their history, draws the graphs, and shouts at you when something breaks. It is built to stay out of the way — one binary, one SQLite file, a few megabytes of RAM — while still answering the questions you actually ask during an outage: what is down, since when, and how often has it happened?
Every picture below is the real dashboard, filled with the sample data the setup wizard creates for you — not a mock-up.
One page, five views of the same sensors. The cards above are the default. A denser list, a tree that folds by site and group, a wall of tiles, and the map are one click apart in the top bar.
| One sensor. Its charts, uptime and incidents for the window you pick — an hour to ninety days — and the raw probes they are drawn from. | The tree. Everything the installation holds, folded by site and by group, which is how you find one sensor among a hundred. |
The wall puts every sensor of a site on one screen with its recent history as a heartbeat, which is what you want on a monitor on the wall of the room the rack is in.
The map draws the world from public-domain data embedded in the binary — no tile server, no request to anywhere, and it therefore also works on a network with no internet. A tile URL in Settings puts real tiles underneath it, and the borders and names are a switch.
Zoomed in, the provinces and their names appear, the water comes with them, and the bigger cities fill in what a province-sized name cannot name.
⚖️ A hobby project, vibe coded, and nobody is liable for anything
ProbeGlass is not a product, and it is not written by a professional software developer. It is one person's homelab watchdog: spare time, their own machines, and a codebase written in dialogue with an AI coding agent (Claude Code). It is shared in the hope that somebody else is looking for something similar — that is the whole of its ambition, and it is not an argument against any of the other monitoring tools out there.
There is no company behind it, no support contract, no paid tier and no SLA, and no promise that a bug gets fixed or that a breaking change waits for a major version. The issue tracker is read and patches are welcome — what is not on offer is a timeline.
It has had no design review and no security audit, and not every line has been read by a second human. Most of the code was written by the agent and then run, measured and corrected; some of it was written or reworked by hand. Expect the rough edges that come with that, and please report them.
It is MIT licensed and provided "as is", without warranty of any kind — which covers data loss, a container that will not start, and the case this project exists to catch: a service that was down for a day while the dashboard said it was fine. Do not make it your only line of defence. If a missed alert would cost you money, keep a second, independent check on the things that matter most.
How it came about, how it is written today, and what that means for you: Who makes this, and how.
Where to go next: Why another monitor? · Features · Quick start · Sensors · Alerts · Configuration · HTTP API · Operating · Development · Status · License
There are other monitoring tools, and this is not an argument against any of them. There is also no shortage of them. It is simply that most of them are a lot bigger than a homelab needs, in memory and in moving parts. ProbeGlass makes the opposite bet:
| ProbeGlass | Typical container-based monitor | |
|---|---|---|
| Memory at idle | ~3 MB | 200–400 MB |
| Runtime deps | none (static binary) | Node.js, or a JVM, or a full stack |
| Frontend build | none — plain ES modules, embedded in the binary | npm, a bundler, a CDN |
| Dependencies | pure Go, including SQLite (no CGO) | native modules |
| Data | one SQLite file you can copy | a database server or a volume full of JSON |
The whole program is a Go binary with the dashboard baked in via embed.FS.
There is no build step between editing a .js file and reloading the page, and
building the image needs nothing but the Go toolchain — no npm, no bundler, no
frontend pipeline to keep alive.
/status/<token>
for the people who use the homelab. You give it a title, a logo, a background
image, a theme, an accent and one of three layouts; group the services into
sections you name (or build them from the dashboard groups in one step); and
choose which uptime windows, logos, heartbeats, incidents and causes each
shows. The background can be uploaded — PNG, JPEG or GIF, up to 4096×4096 and
12 MiB — and lives in the database and the backup beside everything else; an
upload is used instead of the URL until you remove it. The
link can be rotated or switched off; status messages with their own colour and
symbol sit at the top, and an administrator gets an edit link back to the
panel. No target, option or credential is ever drawn.git clone https://github.com/j000k3r/probeglass.git
cd probeglass
docker compose up -d
Then open http://localhost:8080 and create the first account in the setup wizard.
docker run -d \
--name probeglass \
--restart unless-stopped \
-p 8080:8080 \
-v probeglass-data:/data \
--cap-add NET_RAW \
ghcr.io/j000k3r/probeglass:0.2.3
Every release is published under three tags: 0.2.3, the exact version;
0.2, which follows the 0.2.x patch releases; and latest, which follows the
newest release of all. dev is a build of whatever is in the tree today.
NET_RAW is only needed for ICMP ping sensors. Without it, ProbeGlass falls
back to an unprivileged UDP ping and tells you in the sensor result if that is
not available either.
Building the image yourself needs BuildKit (docker buildx), because the
Dockerfile pins its builder to $BUILDPLATFORM and cross-compiles to the target
architecture rather than emulating it. BuildKit is bundled with Docker Desktop
and is the default on current Docker engines; with Homebrew's docker formula
it is a separate brew install docker-buildx. Without it, make run builds and
serves the same binary natively.
make run # builds the binary and serves :8080, data in ./data
make seed # fills ./data with demo sensors and a week of synthetic history
make test # runs the test suite
docker run --rm -p 8080:8080 -v probeglass-demo:/data \
ghcr.io/j000k3r/probeglass:0.2.3 seed --demo --days 7
docker run --rm -p 8080:8080 -v probeglass-demo:/data \
ghcr.io/j000k3r/probeglass:0.2.3 serve --listen :8080
The demo set brings invented sensors of several types, a week of plausible history with outages in it, and no alert channels — a seeded install never sends you anything, which is the right default for something you are only looking at. Delete the volume when you are done.
A sensor is a name, a type, a target, an interval, and a handful of options that depend on the type. Everything is editable in the UI; the same objects can be declared in YAML.
| Type | Target | Useful options |
|---|---|---|
http | a URL | method, expected_status, headers, user_agent, basic_auth_user/basic_auth_pass, bearer_token, body, body_contains, body_not_contains, body_regex, expected_headers, max_body_bytes, follow_redirects, insecure_skip_verify, cert_warn_days |
tcp | host:port | tls, server_name, insecure_skip_verify, send (supports \r and \n), expect |
ping | host or IP | count (echo requests, default 3) |
dns | hostname | record_type (A, AAAA, CNAME, MX, TXT, NS, SRV, PTR), resolver, expected, expect_all |
Common to all types: interval, timeout, retries (how many consecutive
failures before an incident opens), group, tags, reminder_every,
enabled, and the list of notification channels.
sensors:
- name: Router
type: ping
target: 192.168.1.1
interval: 30s
retries: 3
group: Network
- name: Nextcloud
type: http
target: https://cloud.example.org/status.php
interval: 60s
timeout: 10s
options:
expected_status: 200
body_contains: '"installed":true'
channels: [telegram]
- name: DNS resolves the web host
type: dns
target: cloud.example.org
interval: 5m
options:
record_type: A
expected: 10.0.0.42
| Channel | Required fields |
|---|---|
| Telegram | bot token, chat ID |
| Discord | webhook URL |
| Matrix | homeserver URL, access token, room ID |
| ntfy | topic (plus server URL, optional token and priority) |
| Gotify | server URL and app token (plus optional priority) |
| Slack | webhook URL |
| Webhook | URL (plus optional method and HMAC secret) |
Every channel takes an optional title_template and body_template — Go
text/template strings rendered against the sensor name, type, target, status,
message, latency, incident start, and duration. The built-in wording differs per
event (down, reminder, recovery, test), and a template that fails to parse or
execute falls back to it rather than losing the alert.
Generic webhooks POST a JSON payload and, when a secret is configured, sign the
exact request body with HMAC-SHA256 in the X-ProbeGlass-Signature header.
The event name travels in X-ProbeGlass-Event (down, up, reminder, or
test).
Credentials are never returned by the API — the UI shows a StoredMarker
placeholder instead — and the Telegram bot token is stripped from error
messages, so a failed send cannot leak it into your logs.
The dashboard stores its settings in the database; the process reads its configuration from four places. Later sources win:
-config PATH, else $PROBEGLASS_CONFIG, else
<data_dir>/probeglass.yaml if that file existsPROBEGLASS_* environment variableslisten: ":8080"
data_dir: /data
base_url: https://probeglass.lan # used in links inside alerts
log_level: info # debug | info | warn | error
log_format: text # text | json
trust_proxy: false # honour X-Forwarded-* from a reverse proxy
retention:
raw: 7d # individual probe results
hourly: 90d # hourly rollups (daily rollups are kept forever)
Every key has an environment variable: PROBEGLASS_LISTEN,
PROBEGLASS_DATA_DIR, PROBEGLASS_DB, PROBEGLASS_BASE_URL,
PROBEGLASS_LOG_LEVEL, PROBEGLASS_LOG_FORMAT,
PROBEGLASS_ADMIN_PASSWORD, PROBEGLASS_TRUST_PROXY,
PROBEGLASS_RETENTION_RAW, PROBEGLASS_RETENTION_HOURLY.
Durations accept Go syntax (30s, 5m, 2h) plus the day and week suffixes
these settings are naturally written in (7d, 90d, 2w), or a bare number of
seconds.
PROBEGLASS_ADMIN_PASSWORD creates an administrator account named admin on
a database that has no accounts at all, and is ignored afterwards — handy for
automated deployments, harmless afterwards.
See docs/CONFIGURATION.md for the full reference.
The dashboard is a client of the same API you can script against. Authenticate
with the session cookie or, for scripts, with X-API-Key (or
Authorization: Bearer). Generate a key in Settings → API key. The key is
not tied to an account and has full administrator rights, so treat it like a
root password.
curl -H "X-API-Key: $PG_KEY" http://localhost:8080/api/summary | jq
curl -H "X-API-Key: $PG_KEY" localhost:8080/api/sensors/1/series?range=24h | jq
curl -H "X-API-Key: $PG_KEY" localhost:8080/api/sensors/1/uptime?range=30d | jq
A route's method is also its permission boundary. Reads are open to every
signed-in role; acting on an outage needs the operator role; changing the
configuration, the API key or the accounts needs the admin role. The few routes
that touch only the caller's own account — GET/PUT /api/settings,
PUT /api/password, /api/me/totp/* and POST /api/onboarding/tour — sit at
viewer, because they are nobody else's business.
| Method | Path | Purpose |
|---|---|---|
GET | /healthz | liveness, no auth |
GET | /api/version | version, commit, build date |
GET | /api/session | whether setup is needed, and who you are |
POST | /api/setup | create the first account (username, password, mode) |
POST | /api/login, /api/login/totp | sign in, and finish sign-in with a TOTP or recovery code |
POST | /api/logout | sign out |
GET | /api/summary | everything the dashboard needs in one call |
GET | /api/events | SSE stream of live status changes |
GET | /api/sensors | list sensors |
POST | /api/sensors | create a sensor (admin) |
GET | /api/sensors/{id} | read one sensor |
PUT/DELETE | /api/sensors/{id} | update or delete (admin; updates are partial) |
PATCH | /api/sensors/{id} | pause or resume; accepts only enabled (operator) |
POST | /api/sensors/validate | validate a draft without saving |
POST | /api/sensors/{id}/probe | run one probe now |
GET | /api/sensors/{id}/results | recent raw samples |
GET | /api/sensors/{id}/series | downsampled series for charts |
Mutating requests are checked against Origin, so a browser on another site
cannot drive the API even with a valid cookie.
/data/probeglass.db,
WAL mode). Back up that file, or the whole volume, and you have backed up
everything — byte for byte, which is still the right backup when you want
everything. For a portable copy that can be trimmed, Settings → Backup writes
the installation out as one JSON file and reads one back in, and takes a
byte-exact safety copy of the database before it restores anything. The file
holds secrets in clear text; SECURITY.md says what and why.HEALTHCHECK that runs probeglass healthcheck, so docker ps shows the real state without needing a shell in
the image.docker exec probeglass probeglass doctor says what: the configuration, the data directory, the database's
integrity and schema, the stored sensors, and whether the daemon is answering.
It opens the database read-only and never sends an alert, so it is safe on a
database you are worried about.base_url and trust_proxy: true so links in alerts
and the client IP the API sees are correct. The session cookie deliberately
has no Secure flag, because homelab installs are usually plain HTTP on the
LAN; terminate TLS at your proxy if you need it.cmd/probeglass entrypoint: serve, version, healthcheck, doctor, seed
internal/api HTTP handlers, sessions, accounts, middleware, SSE
internal/totp RFC 6238 one-time passwords, written out in full
internal/doctor read-only inspection for `probeglass doctor`
internal/sensor one engine per sensor type
internal/notify alert channels, templating, delivery
internal/scheduler one goroutine per sensor, incident lifecycle
internal/store SQLite schema, queries, rollups, retention
internal/model shared types and options
internal/config YAML, environment, flags, validation
internal/web embedded dashboard (HTML, CSS, plain ES modules)
make on its own lists every task. The useful ones are make run,
make dev, make test, make test-race, make cover, make lint,
make docker, and make rename MODULE=github.com/you/probeglass.
CI runs gofmt, go vet, go test -race, a build for each of the three
architectures the image ships, and golangci-lint. There is no frontend build
step.
See docs/ARCHITECTURE.md for how the pieces fit together, CONTRIBUTING.md for how to send a patch, and docs/ROADMAP.md for what is planned next.
The user-facing documentation lives in its own repository and is published from
there: https://j000k3r.github.io/probeglass-docs/. This repository keeps
the documents that belong with the code. The container image is published to the
GitHub Container Registry, ghcr.io/j000k3r/probeglass, by the release workflow.
Version 0.2.3 — the foundation is in place and works, the feature set is still growing. The dashboard ships in English and German, the switch is in Settings and in the account menu, and the UI is built on a message catalogue, so the next language is a dictionary file and a picker entry. The container image is the only thing a release publishes.
This is a hobby project with no warranty and no support commitment, and the code is written in dialogue with an AI coding agent. Who makes this, and how is the honest version, and it is worth two minutes before you install this anywhere that matters.
MIT — see LICENSE. In plain words: use it, change it, ship it, keep the notice — and accept that it comes with no warranty of any kind and that nobody is liable for anything it does. It is a hobby project, not a product.
local or external) and optional coordinates; it
groups the tree and the wall, and with coordinates it is drawn on the map.
Optional throughout — a sensor without a site behaves exactly as it did before
sites existed.? that opens one sentence about
what it is for and one example, instead of a paragraph under the form.probeglass doctor on the command line, and
the same checks in the dashboard under Settings → Diagnostics, with the
docker exec command to run it yourself.VACUUM INTO safety copy beside the database,
and replaces only what the file names, so a configuration rollback never wipes
history. The file carries every secret in clear text — password hashes, TOTP
secrets, the API key and every channel's credentials — because a backup with
masked credentials restores a channel that cannot send anything. See
SECURITY.md.PUID:PGID before it opens anything — see SECURITY.md.GET | /api/sensors/{id}/uptime | uptime and response-time statistics |
GET | /api/sensors/{id}/incidents | outage history for one sensor |
GET | /api/incidents | all incidents, newest first; filter with state, sensor, range/since, q |
POST | /api/incidents/{id}/ack | acknowledge an outage, with a note |
DELETE | /api/incidents/{id}/ack | take the acknowledgement back |
POST | /api/sensors/{id}/ack | acknowledge whatever that sensor has open |
GET | /api/search | search sensors, sites, channels, incidents, probe messages, settings and (for admins) accounts |
PUT | /api/sensor-order | reorder the dashboard (admin) |
GET/POST | /api/sites | list the places sensors live, or create one (create is admin) |
PUT/DELETE | /api/sites/{name} | rename or delete; a delete is refused while sensors are on it, or takes ?unassign=1 (admin) |
PUT | /api/map | the installation-wide tile URL, attribution and borders switch (admin) |
GET | /api/channels | list alert channels |
POST | /api/channels | create a channel (admin) |
GET | /api/channel-types | field descriptions and the per-type setup recipe, drives the UI forms |
PUT/DELETE | /api/channels/{id} | update or delete (admin) |
POST | /api/channels/test, /api/channels/{id}/test | send a test alert (admin) |
GET/PUT | /api/settings | the account's interface preferences |
POST | /api/onboarding/tour | remember how far the guided tour got |
PUT | /api/password | change your own password |
POST | /api/me/totp/start, /api/me/totp/confirm, /api/me/totp/disable, /api/me/totp/recovery | enrol, confirm or remove two-factor authentication |
GET | /api/me/totp/qr | the enrolment QR code, as a PNG |
POST | /api/doctor | run the self-check and return its report |
POST/DELETE | /api/api-key | rotate or remove the API key (admin) |
GET/POST | /api/users | list and create accounts (admin) |
PUT/DELETE | /api/users/{id} | change a role, disable or delete an account (admin) |
POST | /api/users/{id}/password | reset somebody's password (admin) |
GET/DELETE | /api/examples | count or remove the sample sensors (delete is admin) |
GET | /api/backup | download the installation as JSON — ?scope=config|history&days=7|30|90|all (admin) |
POST | /api/restore | read a backup back in; the file is the request body (admin) |