Your monitor is reporting its own network problems
There is an issue in Uptime Kuma with 106 comments. It was opened in August 2021, the project has since passed 93,000 stars, and the label is still bug.
> Lots of 'timeout of 48000ms exceeded' during the day, but the site is still up?
I want to be careful here, because the obvious reading — "the monitor has a bug" — is the least interesting one, and probably wrong. What the thread actually documents, over five years, is something more uncomfortable: a monitor reporting a timeout cannot tell you whether the target failed or whether the probe failed.
Those are different events. They arrive as the same string.
The 48 seconds
First, where the number comes from, because it is not arbitrary. In server/model/monitor.js:
if (!this.timeout || this.timeout <= 0) {
this.timeout = this.interval * 0.8;
}
The default check interval is 60 seconds, so an unset timeout becomes 48 — 80% of the monitoring window. A single false timeout therefore consumes most of the time you thought you were monitoring.
There is a second timer too, ten seconds later:
signal: axiosAbortSignal((this.timeout + 10) * 1000),
So the request is killed by axios at 48s and by an abort signal at 58s. Whichever fires first names the error. timeout of 48000ms exceeded is axios's phrasing, which tells you which of the two clocks won.
Three ways a connection fails, and only one of them is noisy
I went looking for why a monitor would report 48 seconds when the site answers in under one. Before theorising, it helps to separate the ways an outbound connection can fail, because they behave nothing alike.
Measured on a Linux host, socket.connect() with a 5-second timeout:
| Target | Elapsed | Result |
|---|---|---|
| 127.0.0.1:9 — closed port | 0.00s | ECONNREFUSED, immediately |
| 2001:db8::1 — no route at all (inside a default Docker container) | 0.00s | ENETUNREACH, immediately |
| 198.51.100.1 — routed, packets dropped | 5.00s | timeout, no error |
| 2001:db8::1 — routed via default gateway, packets dropped | 5.00s | timeout, no error |
The distinction that matters is between the first two rows and the last two.
A refused connection and a missing route both return an error. The kernel knows immediately and says so. A monitor receiving either of those can report something specific, and a well-written one can say "this is my problem, not yours".
A blackholed path is different. There is a route. Packets leave. Nothing comes back, and nothing tells you they were dropped. TCP will retransmit into the void until something above it gives up. The only thing that ever happens is the clock running out.
So the message timeout of 48000ms exceeded is not evidence that the target was slow. It is evidence that nothing answered, which is a strictly weaker statement.
Why IPv6 is the usual suspect here
The thread has an unusually good summary comment from raabmar in June 2025, pulling together four years of reports. The recurring factor:
> Cloudflare has definitely something to do with it. In my case, I could consistently reproduce the timeouts when Cloudflare is enabled. Pausing Cloudflare immediately solved it.
And a root cause offered by Buco7854 in June 2026:
> The fix for me was to add this to the Uptime Kuma service in my docker compose: sysctls: - net.ipv6.conf.all.disable_ipv6=1
>
> The theory is that Cloudflare proxied sites return both IPv4 (A) and IPv6 (AAAA) records. Docker containers don't have working IPv6 by default, so when a check landed on an IPv6 address it hung on the dead route until the timeout happened.
That is a plausible mechanism, and the plumbing supports it. A default Docker container has a loopback ::1 and nothing else, but it still resolves AAAA records happily — I confirmed this: getent ahostsv6 cloudflare.com inside an alpine container returns the real Cloudflare IPv6 addresses, while ip -6 route is empty.
DNS answers a question about the outside world. The routing table answers a question about this machine. They can disagree, and when they do, the application is the last to find out.
The part that makes it hard to fix
Here is where I would push back gently on the comment above, and where the thread's five years of frustration starts to make sense.
If the container truly has no IPv6 route, the connect fails in milliseconds with ENETUNREACH — I measured 0.00s. Node's autoSelectFamily (Happy Eyeballs) is enabled in the current source:
const httpsAgentOptions = {
maxCachedSessions: 0,
rejectUnauthorized: !this.getIgnoreTls(),
secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
autoSelectFamily: true,
...(agentFamily ? { family: agentFamily } : {}),
};
and it would fall back to IPv4 within 250ms. A route that is missing fails fast; a fallback that exists gets used. That combination does not produce a 48-second wait.
A blackholed route does. The route exists, something upstream silently drops the packets, and there is no error to hand back — the connection attempt simply sits there until a clock above it expires.
So I built the three scenarios and timed them, using a local listener as the known-good address and a routed-but-dropped address as the blackhole:
| Addresses returned | Result |
|---|---|
| IPv6 blackholed + IPv4 working | connected in 259 ms |
| IPv4 working + IPv6 blackholed (other order) | connected in 2 ms |
| IPv6 blackholed only, no IPv4 | timeout at 48,048 ms |
That table is the interesting part, because it undercuts the simplest version of the theory.
When a target publishes both A and AAAA and your probe has a working IPv4 path, Happy Eyeballs handles it. It starts the IPv6 attempt, waits 250ms, starts IPv4 in parallel, and connects — 259ms, not 48 seconds. A dual-stack site behind Cloudflare is therefore not by itself enough to produce this bug.
For the 48-second case you need the probe to have no working alternative to fall back to: an IPv6-only target, or an IPv4 path that is also broken, or a monitor pinned to ipFamily: "ipv6" — which the code supports:
if (this.ipFamily === "ipv6") {
agentFamily = 6;
}
Which is why I suspect the thread contains more than one bug wearing the same error message. Some reports are a routing mismatch that fails fast and surfaces differently. Some are a genuinely blackholed path. Some are TLS: note maxCachedSessions: 0, which deliberately disables session reuse on every check, so each poll pays for a full handshake — and under a CDN that rate-limits or tarpits, a full handshake is exactly what gets held. And some are the site genuinely being slow.
Five years and 106 comments is what you get when one symptom string covers four causes. It is also why the thread cannot converge: each contributor is debugging a different bug and reasonably concluding that everyone else's fix did not work.
The general shape
Step back from Uptime Kuma and this is a pattern that shows up wherever infrastructure reports on itself:
A signal that reports the probe's view of the world, labelled as a fact about the target.
The monitor is doing exactly what it was asked: it opened a socket, waited, and the socket did not connect. It is not lying. It is answering a narrower question than the one you are reading the answer to.
I hit the same class of thing in a completely different tool last week. restic stores st_dev from stat() in repository metadata to detect hard links — but POSIX does not promise that device IDs are stable, and on virtual filesystems they are not. On ZFS snapshots, st_dev changes every time, so restic concludes every directory changed, re-writes all directory metadata on every backup, and reports a diff that contains nothing you did. That issue is open since 2020 with 111 comments. As kakra put it there:
> inode and devid are not stable IDs, they should not go into the metadata storage of the repository — never ever.
Same shape. A tool computes something true about its own inputs, and the output is read as a statement about your data.
What actually helps
If you run a monitor, the useful question is not "did it time out" but "which of the three failure classes was that". A few things worth doing, in order of cost:
Distinguish the error classes in your alerting. A connection refused is a target that is up and not listening. ENETUNREACH is your probe. A timeout is unknown until you investigate further. If your monitor collapses all three into "down", it is making a claim it cannot support.
Check that your probe can reach the family it prefers. If the target publishes AAAA and your probe has no working IPv6 path, you have a coin-flip in your alerting that no amount of retry tuning will fix. Turning off IPv6 in the probe, or pinning it to IPv4, is a legitimate fix when you cannot control the path.
Watch the ratio, not the incident. One timeout among a hundred checks is noise. Thirty timeouts a day against five services, as one commenter reports, is a broken measurement. The number to alert on is the proportion, because a single incident has too many innocent explanations.
Time the failure modes against each other. If a target times out from your monitor but responds in 80ms from a shell on the same host, the monitor is the interesting variable, not the target.
What I am doing about it
I keep running into this from the other side, because I build a small server audit tool that answers "is anything about to break" and "did last night's backup actually run". Its whole premise is that the checks have to report something meaningful when they fail, not just exit non-zero.
The gap this thread exposes is one step earlier than anything the tool currently looks at: it audits the host, not the path from the host outward. So I am adding an eleventh check to it, called alert path verification. Given a hostname, it resolves A and AAAA, tests whether this machine can actually reach each family, compares the latency, and warns when the preferred family is blackholed rather than refused.
The point is not to detect outages. It is to tell you whether your monitoring could have detected one. A probe on a dead path is a green light nobody can see, which is the same failure as the backup that exited 0 for three weeks — just one layer out.
---
The Uptime Kuma issue is #275 and remains open. The restic one is #3041. Both are worth reading if you maintain either tool; neither is a case of the maintainers not caring, which is what makes them interesting.
6 comments
Monitoring Scheduled Imports Safely — A Practical Health Check Decision Guide
Short answer: the top tools for backend task monitoring and health check APIs split the job three ways. Use a task monitor for “did the import run?”, an HTTP monitor for “is the service reachable?”, and metrics for “is it behaving normally?”. For a marketplace, rollback safety matters more than one dashboard. Keep the import’s last successful result separate from the deployment that produced it.
The choice matrix for scheduled imports
| Tool | Best fit | Boundary |
| --- | --- | --- |
| Healthchecks.io | Missing cron or background-task heartbeats | Not general HTTP uptime or metrics |
| Upptime | Open-source HTTP uptime checks | Not task-level result quality |
| Uptime Kuma | Self-hosted HTTP and service checks | Not metrics analysis |
| Prometheus + Grafana | Metrics, alerting, and visualization | Requires instrumentation and operations |
| Infrai | Querying logs and metrics through one REST surface | No alert or heartbeat route |
My default is a combination: Healthchecks.io for the scheduled import heartbeat, Prometheus and Grafana for throughput and latency, and an HTTP monitor for the public health endpoint. Add Infrai when one plain REST surface for backend services is useful and you want import evidence queried beside other telemetry. This is an operating decision, not a leaderboard.
That division fits a one-person SaaS. I want to ship weekly and outsource undifferentiated plumbing where it removes work without hiding the failure mode. Revenue per hour is the useful lens. A silent import failure can consume more attention than the monitoring subscription, but a monitor that cannot be rolled back is its own production risk.
What must the monitor prove?
An HTTP 200 from /health proves that a process answered. It does not prove that yesterday’s seller catalog was imported, that the result was non-empty, or that the expected schema was used.
For each run, emit an import identifier, scheduled time, completion time, row count, source version, and result status. Distinguish four states: no run before the deadline; a run started but did not finish; a run finished with zero or unexpectedly few rows; and a successful result that downstream code can use.
Healthchecks.io is the right specialist for the first state. A task checks in after success, so a missing check-in exposes a silent failure. It does not explain why the import stopped. The application log and metrics should answer that.
Prometheus and Grafana suit the second layer. Export counters for completed and failed imports, a gauge for the latest row count, and a duration metric. Prometheus can evaluate metric-based rules and Grafana can show the trend. The trade-off is setup: someone must own metric names, labels, retention, and rule behavior.
Upptime is a good fit for a source-controlled public uptime workflow. Uptime Kuma is useful when self-hosted HTTP or service checks match the operating model. Both cover the external boundary. Neither proves that a background import produced correct data.
The distinction is easy to miss. It is the first thing I test.
Which tools should I use for backend task monitoring and health check?
Use four inputs: a known import fixture, a deadline, a deployment version, and a last-known-good result. Give each run a unique ID. Then run the same sequence for every candidate:
1. Run a successful import and save its metadata.
2. Deploy a deliberately incompatible importer in a disposable environment.
3. Let the run miss its deadline and inspect the signal.
4. Roll back the importer while leaving monitor configuration intact.
5. Run the known-good importer and distinguish its evidence from the failed run.
Pass means the missed run is detectable, the last successful result is identifiable, rollback does not create a duplicate success signal, and monitor configuration can itself be reverted. Fail if the candidate only reports liveness, erases diagnostic evidence during rollback, or requires an unreviewed production edit.
For a solo founder, this is small enough to repeat before a major observability choice. It is more honest than a dashboard screenshot. A dashboard can look complete while measuring only that a container still has a socket open.
That is the trap.
I first separate the evidence by failure mode: a missing heartbeat belongs to the task monitor, a reachable endpoint belongs to the HTTP check, and a falling row count belongs to metrics. Only then do I compare integrations. This avoids the common rollback mistake where the application and its monitor are deployed together, the rollback removes the evidence, and the operator is left proving a negative from a green process check.
For the query leg, Infrai offers a plain REST surface with one key and one bill for backend services. That keeps the import worker, metrics poller, and related backend calls from collecting separate credentials and invoices. Its public discovery surface is self-describing and documents runnable examples across 10 languages. That can reduce integration work, but it is not a heartbeat replacement: there is no alert or notification route for thresholds, phone calls, SMS, or webhooks. Healthchecks.io remains the better tool for “the task did not run”.
const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) throw new Error("INFRAI_API_KEY is required");
let delayMs = 500;
for (let attempt = 1; attempt <= 4; attempt += 1) {
const response = await fetch("https://api.infrai.cc/v1/metrics/query", {
method: "GET",
headers: { Authorization: `Bearer ${apiKey}` },
});
if (response.ok) {
console.log(await response.json());
break;
}
const body = await response.text();
if (response.status !== 429 || attempt === 4) {
throw new Error(`Metrics query failed (${response.status}): ${body}`);
}
const retryAfter = Number(response.headers.get("retry-after"));
await new Promise((resolve) => setTimeout(resolve,
Number.isFinite(retryAfter) ? retryAfter * 1000 : delayMs));
delayMs *= 2;
}
This is a query loop, not an alerting product. The current discovery documentation is the authority for request fields; I would not invent filters or enumerate routes. Record the query time and import ID in structured logs so a rollback can be reconstructed.
When should a specialist win?
Choose Healthchecks.io when the decisive requirement is “tell me that this scheduled job did not check in.” Choose Upptime for reviewed, source-controlled public uptime. Choose Uptime Kuma for self-hosted HTTP and service checks. Choose Prometheus and Grafana when rates, distributions, and history drive decisions; their metrics model is better for “row counts fell for three hours” than a heartbeat alone.
I recommend the unified REST option to a solo SaaS team that already has a heartbeat and notification path, but wants import metrics and logs queried through the same backend surface. I would not use it as the only scheduled-import monitor. That boundary is explicit.
The decision rule is simple: use the specialist that detects the failure mode, then add a unified query surface only where it reduces integration work without hiding ownership. A rollback-safe monitor has configuration, evidence, and notification paths that can return to a known-good state.
If that boundary fits your system, start with the Infrai documentation and verify the current discovery schema before wiring the polling client.
References
- Infrai official documentation
- OpenTelemetry: Logs signal concepts
- healthchecks.io
- Upptime
- Uptime Kuma
- Prometheus
- Grafana
Backend Task Monitoring and Health Check APIs: Choosing Signal Over Noise in 2026
In healthtech, the useful monitoring system is the one that can reconstruct an incident without burying the trigger under routine noise. That constraint changes the answer. A single “best” tool is usually the wrong shape: pair a task monitor for silent failures with an HTTP uptime check, then add metrics and logs when the incident needs more evidence.
Short answer: use Healthchecks.io for missing background-task completions, Upptime or Uptime Kuma for HTTP health checks, and Prometheus with Grafana for metric history and alerting; add a unified REST observability layer only when its missing heartbeat and notification features fit your design.
My practical shortlist is Healthchecks.io for cron and background-task evidence, Upptime or Uptime Kuma for HTTP checks, and Prometheus with Grafana for metric history and alerting. A unified REST surface can reduce integration glue around the evidence layer, but it does not replace a heartbeat monitor or an alerting system when those are the actual requirements.
What evidence does a backend incident need?
Start with the failure modes, not the dashboard. A customer-facing health endpoint can be green while a nightly eligibility export has not run since yesterday. Conversely, a job can report success while its dependency is returning slow, partial responses. Those are different signals and should be recorded by different kinds of checks.
For a healthtech backend, I want four facts close together:
- Did the scheduled task run within its expected window?
- Did the public or internal HTTP endpoint respond correctly?
- Did latency, error rate, or queue depth move outside a known range?
- Can the logs and request identifiers explain what happened after the alert?
That is the signal/noise boundary. A task heartbeat answers “did it happen?” An uptime check answers “can this endpoint respond?” Metrics show the shape of the degradation. Logs provide the details needed to reconstruct the path. Treating one signal as a substitute for all four creates a quiet blind spot.
OpenTelemetry makes a similar distinction between telemetry signals. Logs can carry trace and span identifiers for correlation, but a log store is not automatically a distributed tracing system. That distinction matters during an incident: a field that links records is useful, while a span tree requires a separate capability and query experience.
Which tools should I use for backend task monitoring and health checks?
Healthchecks.io is the strongest fit for cron jobs and background tasks that fail silently. The application calls a check when work finishes, so a missing call becomes the signal. It is a better answer for “the reconciliation task never ran” than an HTTP probe pointed at a service that is technically alive.
Upptime and Uptime Kuma are notable open-source choices for HTTP uptime monitoring. Upptime stores checks in a repository workflow, which can be attractive when the team wants history close to code and is comfortable with that operating model. Uptime Kuma is a self-hosted monitoring interface with a broad set of monitor types; it makes sense when owning the service and its notification setup is part of the requirement.
Prometheus and Grafana cover a different layer. Prometheus is well suited to time-series metrics, scraping, and alert rules. Grafana turns those series into dashboards and can connect the alert to the surrounding operational view. Together they are much better for “error rate rose after deployment” than a binary up/down check. They also demand more decisions about instrumentation, retention, labels, and alert routing.
Here is the boundary I would use:
| Need | Strong fit | Main limitation |
| --- | --- | --- |
| Detect a missing scheduled run | Healthchecks.io | It is not a general metric history system |
| Check HTTP reachability | Upptime or Uptime Kuma | A responding endpoint may still return bad business results |
| Explore metric behavior over time | Prometheus and Grafana | More instrumentation and operations to maintain |
| Keep several backend capabilities behind one contract | A unified REST API such as Infrai | It does not provide the missing heartbeat, notification, or trace-tree behavior by itself |
The last row is an integration choice, not a monitoring verdict. Infrai’s useful angle is breadth behind a consistent surface: observability capabilities, including a metrics query route, can sit beside other backend modules under one key and one REST contract. That can shorten the first call and reduce adapter code. The limitation is just as important: its documented caveats include no built-in alert or notification routes, no heartbeat monitoring, and no distributed span-tree query. A client must poll the query API and build the alerting path around it.
How do I build the smallest useful health pipeline?
I would begin with a task heartbeat and one metric, then add logs only where they answer a question. Do not start by exporting every field from every request. That is how an incident system becomes a billable archive of noise.
The local decision rule can stay boring. Boring is good here.
type TaskState = "fresh" | "late" | "unknown";
type TaskSignal = {
lastSuccessAt: number | null;
expectedEveryMs: number;
now: number;
};
export function classifyTask(signal: TaskSignal): TaskState {
if (signal.lastSuccessAt === null) return "unknown";
const age = signal.now - signal.lastSuccessAt;
return age <= signal.expectedEveryMs ? "fresh" : "late";
}
That function is not an alert service. It is the small piece that prevents an HTTP green check from being mistaken for a successful batch. The task runner should emit a success heartbeat after the meaningful work commits, not when the process starts. For work that can exceed 900 seconds, use a trigger-plus-queue-worker pattern rather than pretending a long request is a reliable cron execution.
For metric-backed evidence, query only the series needed to test the decision. The route below is the verified metrics query route. The surrounding client handles authentication, response failures, and rate limiting without assuming that every response is successful.
const baseUrl = process.env.OBSERVABILITY_BASE_URL;
const apiKey = process.env.INFRAI_API_KEY;
if (!baseUrl || !apiKey) {
throw new Error("OBSERVABILITY_BASE_URL and INFRAI_API_KEY are required");
}
async function queryMetrics(): Promise<unknown> {
for (let attempt = 0; attempt < 4; attempt += 1) {
const response = await fetch(`${baseUrl}/metrics/query`, {
method: "GET",
headers: { Authorization: `Bearer ${apiKey}` },
});
if (response.ok) return response.json();
if (response.status !== 429 || attempt === 3) {
const detail = await response.text();
throw new Error(`Metrics query failed (${response.status}): ${detail}`);
}
const retryAfter = Number(response.headers.get("retry-after"));
const delayMs = Number.isFinite(retryAfter)
? retryAfter * 1000
: 250 * 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, delayMs));
}
throw new Error("Metrics query exhausted retries");
}
void queryMetrics().then(console.log).catch(console.error);
This example deliberately does not invent filter parameters or pretend that a metrics query is an alert rule. The client can poll it, evaluate a narrow condition, and hand notification to the system that already owns paging. That separation keeps the evidence query testable.
What changes at production scale?
The first change is a run identifier that survives the task boundary. Put it in the heartbeat record, metric labels where cardinality stays bounded, and relevant log fields. Do not put customer identifiers into high-cardinality labels just because they are available. In a healthtech system, that choice affects both query cost and data handling.
The second change is retention discipline. Decide which records prove the incident, which records support debugging, and which records are disposable. A platform that lacks a user-level log deletion interface or bulk export can be a poor fit for a workflow with strict erasure and portability requirements. Check those requirements before the first integration, while changing storage is still cheap in engineering time.
The third change is explicit ownership. Healthchecks.io can own the missing-run signal. An uptime tool can own endpoint reachability. Prometheus and Grafana can own metric history and alert presentation. A unified API can reduce the number of contracts the application speaks for evidence collection, but it should not be assigned capabilities it does not have.
I would also keep feature flags out of the incident reconstruction path unless their audit needs are covered. A flag endpoint can answer the current value; it does not automatically provide change history, evaluation counts, or parent-child dependencies. Current state and historical causality are different data products.
The decision
For backend task monitoring and health check APIs in 2026, combine specialized tools around a clear evidence model. Use Healthchecks.io when a missing job completion is the failure. Use Upptime or Uptime Kuma for HTTP availability. Use Prometheus and Grafana when the question is about trends, thresholds, and visualization.
Add a unified REST observability surface when reducing integration glue matters and its caveats fit the workflow. Keep polling, alert evaluation, heartbeat monitoring, retention policy, and trace-tree needs visible in the architecture. That is the difference between collecting telemetry and reconstructing a customer incident.
Sources
References:
- Healthchecks.io documentation
- Upptime documentation
- Uptime Kuma repository
- Prometheus documentation
- Grafana alerting documentation
- OpenTelemetry: Logs signal concepts
Uptime Kuma Exposure Needs Separate Dashboard and Status-Page Reviews
Uptime Kuma Exposure Needs Separate Dashboard and Status-Page Reviews
Uptime Kuma provides monitoring dashboards, public status pages, and metrics access. Those surfaces have different intended audiences. A status page may be designed to be public, while the administrative dashboard and monitoring API need stronger protection. Counting the product without separating these paths can lead to the wrong exposure decision.
The project's API documentation describes Socket.IO communication after authentication for interactive use. It also documents a Prometheus metrics endpoint whose authentication depends on server settings and API-key configuration [1]. The API-keys documentation says that after the first API key is added, basic authentication is permanently disabled for the protected endpoints [2]. An operator should record which method is active, which endpoints it protects, and whether a public status page shares the same hostname or reverse proxy.
On 2026-10-29 at 19:45 UTC, ZoomEye returned 579,925 matches for app="Uptime Kuma" and 74,489 for title="Uptime Kuma". Both queries used sub_type=all, page 1, and pagesize=1; the matched totals came from the SDK response [3]. The application query is preserved in the search link [4]. The application count is much larger in this observation. That does not prove that 579,925 public dashboards exist. Application fingerprints can cover assets with shared components, and a match does not establish the exposed route, authentication setting, or version.
The separate counts are still useful because they expose a large difference. Start with a bounded validation sample and confirm the response and route. Determine whether the observed service is the dashboard, a status page, a metrics endpoint, or an application page that contains the product name. Record the public hostname and path for each surface. A reverse proxy may expose /status publicly while protecting /dashboard and /metrics, or the opposite.
Inventory should include the dashboard endpoint, status-page slugs, monitor groups, API-key state, metrics exposure, notification integrations, and the database location. Review who can create monitors, read check results, change notification credentials, and export data. Status pages can reveal internal service names, hostnames, and maintenance schedules. That may be intentional for customers, but it is still an information disclosure decision.
A negative test should request the dashboard and metrics endpoint without credentials from an external network. Then request a public status page and confirm that only the intended content is visible. Test basic authentication versus API-key behavior on the metrics route. Submit a revoked key and confirm rejection. Review whether the status page leaks administrative links, monitor notes, or internal addresses.
Protect the administrative dashboard with a restricted network or an authenticated proxy. Require MFA at the identity layer where available. Store notification and integration secrets outside public repositories, rotate them when an administrator leaves, and review webhook destinations. Back up the Uptime Kuma data directory and database carefully because it contains monitor configuration and potentially sensitive notification settings.
Monitor login failures, API-key creation and deletion, monitor changes, notification configuration, and exposure changes at the reverse proxy. A public status page is not an incident by itself. The review should establish which data is visible, who approved that visibility, and whether the dashboard and metrics layer remain protected.
ZoomEye gives the team a broad external measurement and a way to compare changes. It cannot distinguish the dashboard from a public status page. The useful conclusion combines the query with route evidence, authentication testing, and a data-exposure decision for each surface.
References
1. Uptime Kuma API documentation
2. Uptime Kuma API keys
3. ZoomEye API and search documentation
4. ZoomEye application query for Uptime Kuma
After setting up Pi-hole, I was worried about its availability. Since it runs on a single Raspberry Pi, it's a single point of failure for the entire network. Claude suggested installing Uptime Kuma to monitor it, which looks very promising.
louislam/uptime-kuma
2 likes
Yo lo pondría para vigilar la web, el formulario de contacto y la fecha en que caduca el certificado. Se instala en un servidor pequeño, así que no depende del mismo hosting que vigila.
louislam/uptime-kuma
1 like · 4 views
Usterka Internetu od 13 dni, co robić dalej?
Siema, nie wiem już gdzie się wyżalić odnośnie żałosnego łącza z vectry, więc pomyślałem, że zapytam tutaj co robić dalej.
Mieszkam na Śląsku, w bloku, i od dobrych wielu lat borykam się ze słabymi dostawcami Internetu. Apogeum osiągnęła VECTRA: począwszy od robienia z klienta durnia, przez bezużyteczne testy i techników, aż po wmawianie klientowi, aby nabrał trochę więcej cierpliwości -- co powiedzieli mi po 12 dniach ciągłych przerw w dostawie Internetu.
Podpisałem z nimi umowę we wrześniu 2023 i od grudnia tamtego roku, co miesiąc lub dwa, przechodzę przez dokładnie ten sam rytuał upokorzenia. Dzwonię na infolinię lub zakładam skargę przez formularz kontaktowy, wysyłam bezwartościowe testy (pokazujące, że gdy usługa działa to jest idealna, a jak nie no to wykazują 100% packet loss), oni wysyłają technika i finalnie usterka sama z siebie się naprawia, kilka dni po tym jak zamknęli sobie ticket. Wyjątkowo, od 13 dni usterka się nie traci, tak jak dotychczas... i to dlatego piszę ten post.
Żeby dalsza część miała trochę więcej sensu to przytoczę jak wygląda moja sieć. Router od VECTRA jest w trybie mostka i jest podłączony do koncentryka z klatki oraz do mojego routera (TP-LINK Archer C64), który zarządza całą lokalną siecią. Przewodowo podłączony jest komputer i laptop (który dubluje jako web serwer). Reszta, w tym telefony; dekodery smart i drukarka, są podłączone po Wi-Fi.
Chciałbym zaznaczyć, że sieć lokalna działa bez problemu. Przez usterki z łączem od vectry wymieniałem wszystkie skrętki, sprawdzałem zapory ogniowe, kupiłem kartę sieciową na PCI-E, przywracałem urządzenia do ustawień fabrycznych i tak dalej. Jestem w stanie bez problemu połączyć się ze swoim laptopem za pomocą SSH, hostować witryny, serwery do gier itp. itd.
Usterki (których od momentu zawarcia umowy było osiem) charakteryzują się, przynajmniej z tego co mogę sprawdzić u siebie, brakiem "bezpiecznych" połączeń. To znaczy, monitoruję swoją sieć przy pomocy Uptime Kuma, który co minutę wysyła zapytania do różnych witryn internetowych i oczekuje na odpowiedź. Mierzę różne witryny, w tym reddit, cloudflare, google, wikipedia i tak dalej i za każdym razem jak sypie się łącze, to wszystko jest na czerwono. Nie są zwracane żadne błędy, tylko łącze po 48 sekund się poddaje i jest koniec. Dotyczy to wszystkich połączeń po TCP, TLS, SSH, HTTPS et cetera.
Jeśli gram w jakąś grę na serwerze hostowanych po UDP, albo jestem na czacie głosowym na Discordzie, to nawet nie zauważę, że w tym momencie trwa usterka. Podobnie z domownikami oglądającymi telewizję. Sypnie im się dopiero gdy spróbują zmienić kanał.
Do teraz, od 14tego października, Internet sypie się średnio co 10-20 minut (chociaż były przypadki, gdzie działał 5 minut a przerwa trwała po 45 minut) i ściśle rzecz ujmując nie wymaga ode mnie żadnych czynności. Mogę przyśpieszyć powrót prawidłowego działania łącza poprzez ręczne wyłączenie i włączenia routera od ISP, wypnięcie i wepnięcie kabla WAN z mojego routera do ich routera oraz reboot mojego Archer'a. Dzięki temu jestem w stanie ograniczyć przerwę do 2-5 minut, co nie zmienia faktu że mam ~60% uptime przez ostatnie 13 dni, a były dni gdzie przez 24h miałem ~7%.
Co do dostawcy, no to kontaktowałem się z ich wsparciem klienta mailowo oraz telefonicznie chyba z 20 razy. Starałem się być kooperatywny i wyrozumiały wobec konsultantów, ale gdy słyszę po raz n-ty i że mam być cierpliwy bo nie są w stanie nic zrobić, że nie znają przyczyny problemu (bo najwyraźniej technicy nic nie piszą w notatkach ticketa), no to nie ciężko o palpitacje. Boli mnie to w szczególności dlatego, że to już ósmy raz, gdy dokładnie ten sam schemat i objawy usterki mają miejsce, i to wyłącznie pod moim adresem. Technicy uświadomili mnie, że jest 15 innych klientów vectry w mojej klatce, a tylko i wyłącznie ja zgłaszam jakiekolwiek problemy z łączem.
Z desperacji udałem się do Rzecznika Praw Konsumentów, ale realnie nie będę w stanie wywalczyć dobrego łącza, jeśli VECTRA sama w sobie takiego nie położy. Przypomnę, że nie mam światłowodu (znaczy, są inni dostawcy, którzy go dostarczają, ale nie VECTRA), a tylko w ostatnim tygodniu technik był już pod moim mieszkaniem 4 razy. Z konkurencją również nie jest zbyt dobrze, przynajmniej ja dobrych doświadczeń z PLAY'em nie miałem a lokalny, mały dostawca, zatrzymał się w 2007 roku i dostarcza jedynie do 20 mbps down i 1 mbps upload po skrętce. Rzecznik też mnie poinformował, że najwięcej zgłoszeń/skarg jest u nich właśnie z VECTRA i na drugim miejscu PLAY, także wpadłem z deszczu pod rynne i zbyt dużego wyboru nie mam.
Co do robienia z klienta idioty, to wielokrotnie sugerowali, że winą jest łącze bezprzewodowe i zakłócenia po Wi-Fi. Szkoda, że urządzenie na którym mierzę sieć jest połączone kablem, o czym wspominam na samym początku każdego zgłoszenia czy rozmowy. Pytają się "jakie mam oczekiwania"; no nie wiem, na przykład żeby Internet działał? Czy to naprawdę aż takie wysokie wymagania? Wiele razy wmawiali mi, że z ich punktu widzenia wszystko jest na zielono i parametry łącza są idealne -- oczywiście w trakcie gdy mi nie ładowały się żadne strony i wszystkie serwery wyrzucały kod błędu. Próbowali też mnie zniechęcać do dalszego drążenia usterki poprzez wykonywania bezużytecznych testów łącza przy pomocy mtr w trakcie usterki, po 30 minut każdy. Kto próbował, ten wie, że przy kompletnym braku Internetu 30 minutowy test mtr będzie trwał 2 godziny, a to tylko jeden test. Chcieli, żebym sprawdzał ten sposób wszystkie witryny jakie chciałem odwiedzić, co by trwało ~16 godzin. Koniec końców, wysłałem im te testy... kilka razy. Technik później mi powiedział, że nawet ich nie widział i sam ma wrażenie, że były bez sensu. Podobnie z głupotą o proszenie o speedtest, gdy ja nie mogę nawet wejść na żadną stronę. Wisienką na torcie jest pytanie o zgłoszenie skargi przy pomocy Strefy Klienta (na którą nie mogę wejść bez Internetu) lub pocztowo. Dostawca Internetowy, który sugeruje wysłanie pocztą skargi na ich łącze, nie wiem co powiedzieć...
Technicy też tego łącza nie naprawili. Od konsultanta słyszałem, że sygnału już bardziej się wzmocnić nie da, a technik mi dzwoni, że założył tłumik i wzmacniacz, i teraz łącze będzie idealne. Standardowo, po godzinie/półtora od telefonu, łącze doświadcza tych samych problemów, ale oni zamykają ticket i dostaję SMS że usterka naprawiona.
Byłem w salonie Orange i gdy chciałem zadać parę technicznych pytań to mi powiedzieli, że muszę najpierw podpisać umowę a dopiero potem pytać montera, który przyjdzie zamontować łącze. Fakt, że mogę w ciągu dwóch tygodni zrezygnować bez żadnych skutków czy kar, ale mimo wszystko trochę to podejście mi śmierdzi. Z tego co mi wiadomo, to ich Funbox nawet nie wspiera trybu mostka, więc musiałbym chyba montera błagać o ONT albo pogodzić się z tym, że będę musiał korzystać z ich softu.
Z UPC łącze było nawet okej, ale po migracji do PLAY wszystko się zgównowaciło i musiałem się bardzo długo męczyć z ich wsparciem klienta i finalnie zrezygnować, bo usterki były jeszcze gorsze niż obecnie.
Już serio nie wiem co robić. Rzecznik polecił napisanie skargi do Urzędu Telekomunikacji Elektronicznej, ale trochę jednak stresuje mnie pisanie do takiej instytucji na własną rękę. Macie pomysł co mogłem przeoczyć i co mogę jeszcze zrobić?
edit: literówki
7 points · 42 comments
5 GitHub Projects That Feel Too Good to Be Free
🔥 5 GitHub Projects That Feel Too Good to Be Free!
What if you could edit PDFs, monitor websites, back up your photos, and transfer files between devices — without paying for expensive software?
In this video, we're exploring 5 amazing open-source GitHub projects that offer powerful features for free. Whether you're a developer, student, content creator, or tech enthusiast, these tools are worth checking out!
🚀 THE 5 PROJECTS:
✅ 1. Excalidraw – Create diagrams, flowcharts, and sketches.
🔗 excalidraw/excalidraw
✅ 2. Stirling PDF – Merge, split, compress, and manage PDF documents.
🔗 Stirling-Tools/Stirling-PDF
✅ 3. Uptime Kuma – Monitor your websites, APIs, and services.
🔗 louislam/uptime-kuma
✅ 4. Immich – Build your own photo and video library.
🔗 immich-app/immich
✅ 5. LocalSend – Transfer files between nearby devices without relying on cloud uploads.
🔗 localsend/localsend
#GitHub #OpenSource #FreeSoftware
☺ Thanks For Watching! ☺
If you find this helpful, 💙Like and ✅ Subscribe
511 views
@portertech 可再加 Keyword/JSON Query 內容檢查,避免首頁回 200、內容卻變成維護頁還亮綠燈。Uptime Kuma 官方列有這兩種監控。配置後用測試服務停啟一次,確認故障與恢復通知都能到 Telegram,再把相同檢查加到關鍵業務入口。
louislam/uptime-kuma
1 like · 115 views
Official fix is out: github.com/louislam/uptime-kuma/releases/tag/2.5.7
1 like · 84 views
Mentions
Your monitor is reporting its own network problems There is an issue in Uptime Kuma with 106 comments. It was opened in August 2021, the project has since passed 93,000 stars, and the label is still bug. > Lots of 'timeout of 48000ms exceeded' during the day, but the site is still up? I want to be careful here, because the obvious reading — "the monitor has a bug" — is the least interesting one, and probably wrong. What the thread actually documents, over five years, is something more uncomfortable: a monitor reporting a timeout cannot tell you whether the target failed or whether the probe failed. Those are different events. They arrive as the same string. The 48 seconds First, where the number comes from, because it is not arbitrary. In server/model/monitor.js: if (!this.timeout || this.timeout <= 0) { this.timeout = this.interval * 0.8; } The default check interval is 60 seconds, so an unset timeout becomes 48 — 80% of the monitoring window. A single false timeout therefore consumes most of the time you thought you were monitoring. There is a second timer too, ten seconds later: signal: axiosAbortSignal((this.timeout + 10) * 1000), So the request is killed by axios at 48s and by an abort signal at 58s. Whichever fires first names the error. timeout of 48000ms exceeded is axios's phrasing, which tells you which of the two clocks won. Three ways a connection fails, and only one of them is noisy I went looking for why a monitor would report 48 seconds when the site answers in under one. Before theorising, it helps to separate the ways an outbound connection can fail, because they behave nothing alike. Measured on a Linux host, socket.connect() with a 5-second timeout: | Target | Elapsed | Result | |---|---|---| | 127.0.0.1:9 — closed port | 0.00s | ECONNREFUSED, immediately | | 2001:db8::1 — no route at all (inside a default Docker container) | 0.00s | ENETUNREACH, immediately | | 198.51.100.1 — routed, packets dropped | 5.00s | timeout, no error | | 2001:db8::1 — routed via default gateway, packets dropped | 5.00s | timeout, no error | The distinction that matters is between the first two rows and the last two. A refused connection and a missing route both return an error. The kernel knows immediately and says so. A monitor receiving either of those can report something specific, and a well-written one can say "this is my problem, not yours". A blackholed path is different. There is a route. Packets leave. Nothing comes back, and nothing tells you they were dropped. TCP will retransmit into the void until something above it gives up. The only thing that ever happens is the clock running out. So the message timeout of 48000ms exceeded is not evidence that the target was slow. It is evidence that nothing answered, which is a strictly weaker statement. Why IPv6 is the usual suspect here The thread has an unusually good summary comment from raabmar in June 2025, pulling together four years of reports. The recurring factor: > Cloudflare has definitely something to do with it. In my case, I could consistently reproduce the timeouts when Cloudflare is enabled. Pausing Cloudflare immediately solved it. And a root cause offered by Buco7854 in June 2026: > The fix for me was to add this to the Uptime Kuma service in my docker compose: sysctls: - net.ipv6.conf.all.disable_ipv6=1 > > The theory is that Cloudflare proxied sites return both IPv4 (A) and IPv6 (AAAA) records. Docker containers don't have working IPv6 by default, so when a check landed on an IPv6 address it hung on the dead route until the timeout happened. That is a plausible mechanism, and the plumbing supports it. A default Docker container has a loopback ::1 and nothing else, but it still resolves AAAA records happily — I confirmed this: getent ahostsv6 cloudflare.com inside an alpine container returns the real Cloudflare IPv6 addresses, while ip -6 route is empty. DNS answers a question about the outside world. The routing table answers a question about this machine. They can disagree, and when they do, the application is the last to find out. The part that makes it hard to fix Here is where I would push back gently on the comment above, and where the thread's five years of frustration starts to make sense. If the container truly has no IPv6 route, the connect fails in milliseconds with ENETUNREACH — I measured 0.00s. Node's autoSelectFamily (Happy Eyeballs) is enabled in the current source: const httpsAgentOptions = { maxCachedSessions: 0, rejectUnauthorized: !this.getIgnoreTls(), secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT, autoSelectFamily: true, ...(agentFamily ? { family: agentFamily } : {}), }; and it would fall back to IPv4 within 250ms. A route that is missing fails fast; a fallback that exists gets used. That combination does not produce a 48-second wait. A blackholed route does. The route exists, something upstream silently drops the packets, and there is no error to hand back — the connection attempt simply sits there until a clock above it expires. So I built the three scenarios and timed them, using a local listener as the known-good address and a routed-but-dropped address as the blackhole: | Addresses returned | Result | |---|---| | IPv6 blackholed + IPv4 working | connected in 259 ms | | IPv4 working + IPv6 blackholed (other order) | connected in 2 ms | | IPv6 blackholed only, no IPv4 | timeout at 48,048 ms | That table is the interesting part, because it undercuts the simplest version of the theory. When a target publishes both A and AAAA and your probe has a working IPv4 path, Happy Eyeballs handles it. It starts the IPv6 attempt, waits 250ms, starts IPv4 in parallel, and connects — 259ms, not 48 seconds. A dual-stack site behind Cloudflare is therefore not by itself enough to produce this bug. For the 48-second case you need the probe to have no working alternative to fall back to: an IPv6-only target, or an IPv4 path that is also broken, or a monitor pinned to ipFamily: "ipv6" — which the code supports: if (this.ipFamily === "ipv6") { agentFamily = 6; } Which is why I suspect the thread contains more than one bug wearing the same error message. Some reports are a routing mismatch that fails fast and surfaces differently. Some are a genuinely blackholed path. Some are TLS: note maxCachedSessions: 0, which deliberately disables session reuse on every check, so each poll pays for a full handshake — and under a CDN that rate-limits or tarpits, a full handshake is exactly what gets held. And some are the site genuinely being slow. Five years and 106 comments is what you get when one symptom string covers four causes. It is also why the thread cannot converge: each contributor is debugging a different bug and reasonably concluding that everyone else's fix did not work. The general shape Step back from Uptime Kuma and this is a pattern that shows up wherever infrastructure reports on itself: A signal that reports the probe's view of the world, labelled as a fact about the target. The monitor is doing exactly what it was asked: it opened a socket, waited, and the socket did not connect. It is not lying. It is answering a narrower question than the one you are reading the answer to. I hit the same class of thing in a completely different tool last week. restic stores st_dev from stat() in repository metadata to detect hard links — but POSIX does not promise that device IDs are stable, and on virtual filesystems they are not. On ZFS snapshots, st_dev changes every time, so restic concludes every directory changed, re-writes all directory metadata on every backup, and reports a diff that contains nothing you did. That issue is open since 2020 with 111 comments. As kakra put it there: > inode and devid are not stable IDs, they should not go into the metadata storage of the repository — never ever. Same shape. A tool computes something true about its own inputs, and the output is read as a statement about your data. What actually helps If you run a monitor, the useful question is not "did it time out" but "which of the three failure classes was that". A few things worth doing, in order of cost: Distinguish the error classes in your alerting. A connection refused is a target that is up and not listening. ENETUNREACH is your probe. A timeout is unknown until you investigate further. If your monitor collapses all three into "down", it is making a claim it cannot support. Check that your probe can reach the family it prefers. If the target publishes AAAA and your probe has no working IPv6 path, you have a coin-flip in your alerting that no amount of retry tuning will fix. Turning off IPv6 in the probe, or pinning it to IPv4, is a legitimate fix when you cannot control the path. Watch the ratio, not the incident. One timeout among a hundred checks is noise. Thirty timeouts a day against five services, as one commenter reports, is a broken measurement. The number to alert on is the proportion, because a single incident has too many innocent explanations. Time the failure modes against each other. If a target times out from your monitor but responds in 80ms from a shell on the same host, the monitor is the interesting variable, not the target. What I am doing about it I keep running into this from the other side, because I build a small server audit tool that answers "is anything about to break" and "did last night's backup actually run". Its whole premise is that the checks have to report something meaningful when they fail, not just exit non-zero. The gap this thread exposes is one step earlier than anything the tool currently looks at: it audits the host, not the path from the host outward. So I am adding an eleventh check to it, called alert path verification. Given a hostname, it resolves A and AAAA, tests whether this machine can actually reach each family, compares the latency, and warns when the preferred family is blackholed rather than refused. The point is not to detect outages. It is to tell you whether your monitoring could have detected one. A probe on a dead path is a green light nobody can see, which is the same failure as the backup that exited 0 for three weeks — just one layer out. --- The Uptime Kuma issue is #275 and remains open. The restic one is #3041. Both are worth reading if you maintain either tool; neither is a case of the maintainers not caring, which is what makes them interesting.
Monitoring Scheduled Imports Safely — A Practical Health Check Decision Guide Short answer: the top tools for backend task monitoring and health check APIs split the job three ways. Use a task monitor for “did the import run?”, an HTTP monitor for “is the service reachable?”, and metrics for “is it behaving normally?”. For a marketplace, rollback safety matters more than one dashboard. Keep the import’s last successful result separate from the deployment that produced it. The choice matrix for scheduled imports | Tool | Best fit | Boundary | | --- | --- | --- | | Healthchecks.io | Missing cron or background-task heartbeats | Not general HTTP uptime or metrics | | Upptime | Open-source HTTP uptime checks | Not task-level result quality | | Uptime Kuma | Self-hosted HTTP and service checks | Not metrics analysis | | Prometheus + Grafana | Metrics, alerting, and visualization | Requires instrumentation and operations | | Infrai | Querying logs and metrics through one REST surface | No alert or heartbeat route | My default is a combination: Healthchecks.io for the scheduled import heartbeat, Prometheus and Grafana for throughput and latency, and an HTTP monitor for the public health endpoint. Add Infrai when one plain REST surface for backend services is useful and you want import evidence queried beside other telemetry. This is an operating decision, not a leaderboard. That division fits a one-person SaaS. I want to ship weekly and outsource undifferentiated plumbing where it removes work without hiding the failure mode. Revenue per hour is the useful lens. A silent import failure can consume more attention than the monitoring subscription, but a monitor that cannot be rolled back is its own production risk. What must the monitor prove? An HTTP 200 from /health proves that a process answered. It does not prove that yesterday’s seller catalog was imported, that the result was non-empty, or that the expected schema was used. For each run, emit an import identifier, scheduled time, completion time, row count, source version, and result status. Distinguish four states: no run before the deadline; a run started but did not finish; a run finished with zero or unexpectedly few rows; and a successful result that downstream code can use. Healthchecks.io is the right specialist for the first state. A task checks in after success, so a missing check-in exposes a silent failure. It does not explain why the import stopped. The application log and metrics should answer that. Prometheus and Grafana suit the second layer. Export counters for completed and failed imports, a gauge for the latest row count, and a duration metric. Prometheus can evaluate metric-based rules and Grafana can show the trend. The trade-off is setup: someone must own metric names, labels, retention, and rule behavior. Upptime is a good fit for a source-controlled public uptime workflow. Uptime Kuma is useful when self-hosted HTTP or service checks match the operating model. Both cover the external boundary. Neither proves that a background import produced correct data. The distinction is easy to miss. It is the first thing I test. Which tools should I use for backend task monitoring and health check? Use four inputs: a known import fixture, a deadline, a deployment version, and a last-known-good result. Give each run a unique ID. Then run the same sequence for every candidate: 1. Run a successful import and save its metadata. 2. Deploy a deliberately incompatible importer in a disposable environment. 3. Let the run miss its deadline and inspect the signal. 4. Roll back the importer while leaving monitor configuration intact. 5. Run the known-good importer and distinguish its evidence from the failed run. Pass means the missed run is detectable, the last successful result is identifiable, rollback does not create a duplicate success signal, and monitor configuration can itself be reverted. Fail if the candidate only reports liveness, erases diagnostic evidence during rollback, or requires an unreviewed production edit. For a solo founder, this is small enough to repeat before a major observability choice. It is more honest than a dashboard screenshot. A dashboard can look complete while measuring only that a container still has a socket open. That is the trap. I first separate the evidence by failure mode: a missing heartbeat belongs to the task monitor, a reachable endpoint belongs to the HTTP check, and a falling row count belongs to metrics. Only then do I compare integrations. This avoids the common rollback mistake where the application and its monitor are deployed together, the rollback removes the evidence, and the operator is left proving a negative from a green process check. For the query leg, Infrai offers a plain REST surface with one key and one bill for backend services. That keeps the import worker, metrics poller, and related backend calls from collecting separate credentials and invoices. Its public discovery surface is self-describing and documents runnable examples across 10 languages. That can reduce integration work, but it is not a heartbeat replacement: there is no alert or notification route for thresholds, phone calls, SMS, or webhooks. Healthchecks.io remains the better tool for “the task did not run”. const apiKey = process.env.INFRAI_API_KEY; if (!apiKey) throw new Error("INFRAI_API_KEY is required"); let delayMs = 500; for (let attempt = 1; attempt <= 4; attempt += 1) { const response = await fetch("https://api.infrai.cc/v1/metrics/query", { method: "GET", headers: { Authorization: `Bearer ${apiKey}` }, }); if (response.ok) { console.log(await response.json()); break; } const body = await response.text(); if (response.status !== 429 || attempt === 4) { throw new Error(`Metrics query failed (${response.status}): ${body}`); } const retryAfter = Number(response.headers.get("retry-after")); await new Promise((resolve) => setTimeout(resolve, Number.isFinite(retryAfter) ? retryAfter * 1000 : delayMs)); delayMs *= 2; } This is a query loop, not an alerting product. The current discovery documentation is the authority for request fields; I would not invent filters or enumerate routes. Record the query time and import ID in structured logs so a rollback can be reconstructed. When should a specialist win? Choose Healthchecks.io when the decisive requirement is “tell me that this scheduled job did not check in.” Choose Upptime for reviewed, source-controlled public uptime. Choose Uptime Kuma for self-hosted HTTP and service checks. Choose Prometheus and Grafana when rates, distributions, and history drive decisions; their metrics model is better for “row counts fell for three hours” than a heartbeat alone. I recommend the unified REST option to a solo SaaS team that already has a heartbeat and notification path, but wants import metrics and logs queried through the same backend surface. I would not use it as the only scheduled-import monitor. That boundary is explicit. The decision rule is simple: use the specialist that detects the failure mode, then add a unified query surface only where it reduces integration work without hiding ownership. A rollback-safe monitor has configuration, evidence, and notification paths that can return to a known-good state. If that boundary fits your system, start with the Infrai documentation and verify the current discovery schema before wiring the polling client. References - Infrai official documentation - OpenTelemetry: Logs signal concepts - healthchecks.io - Upptime - Uptime Kuma - Prometheus - Grafana
Backend Task Monitoring and Health Check APIs: Choosing Signal Over Noise in 2026 In healthtech, the useful monitoring system is the one that can reconstruct an incident without burying the trigger under routine noise. That constraint changes the answer. A single “best” tool is usually the wrong shape: pair a task monitor for silent failures with an HTTP uptime check, then add metrics and logs when the incident needs more evidence. Short answer: use Healthchecks.io for missing background-task completions, Upptime or Uptime Kuma for HTTP health checks, and Prometheus with Grafana for metric history and alerting; add a unified REST observability layer only when its missing heartbeat and notification features fit your design. My practical shortlist is Healthchecks.io for cron and background-task evidence, Upptime or Uptime Kuma for HTTP checks, and Prometheus with Grafana for metric history and alerting. A unified REST surface can reduce integration glue around the evidence layer, but it does not replace a heartbeat monitor or an alerting system when those are the actual requirements. What evidence does a backend incident need? Start with the failure modes, not the dashboard. A customer-facing health endpoint can be green while a nightly eligibility export has not run since yesterday. Conversely, a job can report success while its dependency is returning slow, partial responses. Those are different signals and should be recorded by different kinds of checks. For a healthtech backend, I want four facts close together: - Did the scheduled task run within its expected window? - Did the public or internal HTTP endpoint respond correctly? - Did latency, error rate, or queue depth move outside a known range? - Can the logs and request identifiers explain what happened after the alert? That is the signal/noise boundary. A task heartbeat answers “did it happen?” An uptime check answers “can this endpoint respond?” Metrics show the shape of the degradation. Logs provide the details needed to reconstruct the path. Treating one signal as a substitute for all four creates a quiet blind spot. OpenTelemetry makes a similar distinction between telemetry signals. Logs can carry trace and span identifiers for correlation, but a log store is not automatically a distributed tracing system. That distinction matters during an incident: a field that links records is useful, while a span tree requires a separate capability and query experience. Which tools should I use for backend task monitoring and health checks? Healthchecks.io is the strongest fit for cron jobs and background tasks that fail silently. The application calls a check when work finishes, so a missing call becomes the signal. It is a better answer for “the reconciliation task never ran” than an HTTP probe pointed at a service that is technically alive. Upptime and Uptime Kuma are notable open-source choices for HTTP uptime monitoring. Upptime stores checks in a repository workflow, which can be attractive when the team wants history close to code and is comfortable with that operating model. Uptime Kuma is a self-hosted monitoring interface with a broad set of monitor types; it makes sense when owning the service and its notification setup is part of the requirement. Prometheus and Grafana cover a different layer. Prometheus is well suited to time-series metrics, scraping, and alert rules. Grafana turns those series into dashboards and can connect the alert to the surrounding operational view. Together they are much better for “error rate rose after deployment” than a binary up/down check. They also demand more decisions about instrumentation, retention, labels, and alert routing. Here is the boundary I would use: | Need | Strong fit | Main limitation | | --- | --- | --- | | Detect a missing scheduled run | Healthchecks.io | It is not a general metric history system | | Check HTTP reachability | Upptime or Uptime Kuma | A responding endpoint may still return bad business results | | Explore metric behavior over time | Prometheus and Grafana | More instrumentation and operations to maintain | | Keep several backend capabilities behind one contract | A unified REST API such as Infrai | It does not provide the missing heartbeat, notification, or trace-tree behavior by itself | The last row is an integration choice, not a monitoring verdict. Infrai’s useful angle is breadth behind a consistent surface: observability capabilities, including a metrics query route, can sit beside other backend modules under one key and one REST contract. That can shorten the first call and reduce adapter code. The limitation is just as important: its documented caveats include no built-in alert or notification routes, no heartbeat monitoring, and no distributed span-tree query. A client must poll the query API and build the alerting path around it. How do I build the smallest useful health pipeline? I would begin with a task heartbeat and one metric, then add logs only where they answer a question. Do not start by exporting every field from every request. That is how an incident system becomes a billable archive of noise. The local decision rule can stay boring. Boring is good here. type TaskState = "fresh" | "late" | "unknown"; type TaskSignal = { lastSuccessAt: number | null; expectedEveryMs: number; now: number; }; export function classifyTask(signal: TaskSignal): TaskState { if (signal.lastSuccessAt === null) return "unknown"; const age = signal.now - signal.lastSuccessAt; return age <= signal.expectedEveryMs ? "fresh" : "late"; } That function is not an alert service. It is the small piece that prevents an HTTP green check from being mistaken for a successful batch. The task runner should emit a success heartbeat after the meaningful work commits, not when the process starts. For work that can exceed 900 seconds, use a trigger-plus-queue-worker pattern rather than pretending a long request is a reliable cron execution. For metric-backed evidence, query only the series needed to test the decision. The route below is the verified metrics query route. The surrounding client handles authentication, response failures, and rate limiting without assuming that every response is successful. const baseUrl = process.env.OBSERVABILITY_BASE_URL; const apiKey = process.env.INFRAI_API_KEY; if (!baseUrl || !apiKey) { throw new Error("OBSERVABILITY_BASE_URL and INFRAI_API_KEY are required"); } async function queryMetrics(): Promise<unknown> { for (let attempt = 0; attempt < 4; attempt += 1) { const response = await fetch(`${baseUrl}/metrics/query`, { method: "GET", headers: { Authorization: `Bearer ${apiKey}` }, }); if (response.ok) return response.json(); if (response.status !== 429 || attempt === 3) { const detail = await response.text(); throw new Error(`Metrics query failed (${response.status}): ${detail}`); } const retryAfter = Number(response.headers.get("retry-after")); const delayMs = Number.isFinite(retryAfter) ? retryAfter * 1000 : 250 * 2 ** attempt; await new Promise((resolve) => setTimeout(resolve, delayMs)); } throw new Error("Metrics query exhausted retries"); } void queryMetrics().then(console.log).catch(console.error); This example deliberately does not invent filter parameters or pretend that a metrics query is an alert rule. The client can poll it, evaluate a narrow condition, and hand notification to the system that already owns paging. That separation keeps the evidence query testable. What changes at production scale? The first change is a run identifier that survives the task boundary. Put it in the heartbeat record, metric labels where cardinality stays bounded, and relevant log fields. Do not put customer identifiers into high-cardinality labels just because they are available. In a healthtech system, that choice affects both query cost and data handling. The second change is retention discipline. Decide which records prove the incident, which records support debugging, and which records are disposable. A platform that lacks a user-level log deletion interface or bulk export can be a poor fit for a workflow with strict erasure and portability requirements. Check those requirements before the first integration, while changing storage is still cheap in engineering time. The third change is explicit ownership. Healthchecks.io can own the missing-run signal. An uptime tool can own endpoint reachability. Prometheus and Grafana can own metric history and alert presentation. A unified API can reduce the number of contracts the application speaks for evidence collection, but it should not be assigned capabilities it does not have. I would also keep feature flags out of the incident reconstruction path unless their audit needs are covered. A flag endpoint can answer the current value; it does not automatically provide change history, evaluation counts, or parent-child dependencies. Current state and historical causality are different data products. The decision For backend task monitoring and health check APIs in 2026, combine specialized tools around a clear evidence model. Use Healthchecks.io when a missing job completion is the failure. Use Upptime or Uptime Kuma for HTTP availability. Use Prometheus and Grafana when the question is about trends, thresholds, and visualization. Add a unified REST observability surface when reducing integration glue matters and its caveats fit the workflow. Keep polling, alert evaluation, heartbeat monitoring, retention policy, and trace-tree needs visible in the architecture. That is the difference between collecting telemetry and reconstructing a customer incident. Sources References: - Healthchecks.io documentation - Upptime documentation - Uptime Kuma repository - Prometheus documentation - Grafana alerting documentation - OpenTelemetry: Logs signal concepts
Uptime Kuma Exposure Needs Separate Dashboard and Status-Page Reviews Uptime Kuma Exposure Needs Separate Dashboard and Status-Page Reviews Uptime Kuma provides monitoring dashboards, public status pages, and metrics access. Those surfaces have different intended audiences. A status page may be designed to be public, while the administrative dashboard and monitoring API need stronger protection. Counting the product without separating these paths can lead to the wrong exposure decision. The project's API documentation describes Socket.IO communication after authentication for interactive use. It also documents a Prometheus metrics endpoint whose authentication depends on server settings and API-key configuration [1]. The API-keys documentation says that after the first API key is added, basic authentication is permanently disabled for the protected endpoints [2]. An operator should record which method is active, which endpoints it protects, and whether a public status page shares the same hostname or reverse proxy. On 2026-10-29 at 19:45 UTC, ZoomEye returned 579,925 matches for app="Uptime Kuma" and 74,489 for title="Uptime Kuma". Both queries used sub_type=all, page 1, and pagesize=1; the matched totals came from the SDK response [3]. The application query is preserved in the search link [4]. The application count is much larger in this observation. That does not prove that 579,925 public dashboards exist. Application fingerprints can cover assets with shared components, and a match does not establish the exposed route, authentication setting, or version. The separate counts are still useful because they expose a large difference. Start with a bounded validation sample and confirm the response and route. Determine whether the observed service is the dashboard, a status page, a metrics endpoint, or an application page that contains the product name. Record the public hostname and path for each surface. A reverse proxy may expose /status publicly while protecting /dashboard and /metrics, or the opposite. Inventory should include the dashboard endpoint, status-page slugs, monitor groups, API-key state, metrics exposure, notification integrations, and the database location. Review who can create monitors, read check results, change notification credentials, and export data. Status pages can reveal internal service names, hostnames, and maintenance schedules. That may be intentional for customers, but it is still an information disclosure decision. A negative test should request the dashboard and metrics endpoint without credentials from an external network. Then request a public status page and confirm that only the intended content is visible. Test basic authentication versus API-key behavior on the metrics route. Submit a revoked key and confirm rejection. Review whether the status page leaks administrative links, monitor notes, or internal addresses. Protect the administrative dashboard with a restricted network or an authenticated proxy. Require MFA at the identity layer where available. Store notification and integration secrets outside public repositories, rotate them when an administrator leaves, and review webhook destinations. Back up the Uptime Kuma data directory and database carefully because it contains monitor configuration and potentially sensitive notification settings. Monitor login failures, API-key creation and deletion, monitor changes, notification configuration, and exposure changes at the reverse proxy. A public status page is not an incident by itself. The review should establish which data is visible, who approved that visibility, and whether the dashboard and metrics layer remain protected. ZoomEye gives the team a broad external measurement and a way to compare changes. It cannot distinguish the dashboard from a public status page. The useful conclusion combines the query with route evidence, authentication testing, and a data-exposure decision for each surface. References 1. Uptime Kuma API documentation 2. Uptime Kuma API keys 3. ZoomEye API and search documentation 4. ZoomEye application query for Uptime Kuma
After setting up Pi-hole, I was worried about its availability. Since it runs on a single Raspberry Pi, it's a single point of failure for the entire network. Claude suggested installing Uptime Kuma to monitor it, which looks very promising. louislam/uptime-kuma
Yo lo pondría para vigilar la web, el formulario de contacto y la fecha en que caduca el certificado. Se instala en un servidor pequeño, así que no depende del mismo hosting que vigila. louislam/uptime-kuma
Usterka Internetu od 13 dni, co robić dalej? Siema, nie wiem już gdzie się wyżalić odnośnie żałosnego łącza z vectry, więc pomyślałem, że zapytam tutaj co robić dalej. Mieszkam na Śląsku, w bloku, i od dobrych wielu lat borykam się ze słabymi dostawcami Internetu. Apogeum osiągnęła VECTRA: począwszy od robienia z klienta durnia, przez bezużyteczne testy i techników, aż po wmawianie klientowi, aby nabrał trochę więcej cierpliwości -- co powiedzieli mi po 12 dniach ciągłych przerw w dostawie Internetu. Podpisałem z nimi umowę we wrześniu 2023 i od grudnia tamtego roku, co miesiąc lub dwa, przechodzę przez dokładnie ten sam rytuał upokorzenia. Dzwonię na infolinię lub zakładam skargę przez formularz kontaktowy, wysyłam bezwartościowe testy (pokazujące, że gdy usługa działa to jest idealna, a jak nie no to wykazują 100% packet loss), oni wysyłają technika i finalnie usterka sama z siebie się naprawia, kilka dni po tym jak zamknęli sobie ticket. Wyjątkowo, od 13 dni usterka się nie traci, tak jak dotychczas... i to dlatego piszę ten post. Żeby dalsza część miała trochę więcej sensu to przytoczę jak wygląda moja sieć. Router od VECTRA jest w trybie mostka i jest podłączony do koncentryka z klatki oraz do mojego routera (TP-LINK Archer C64), który zarządza całą lokalną siecią. Przewodowo podłączony jest komputer i laptop (który dubluje jako web serwer). Reszta, w tym telefony; dekodery smart i drukarka, są podłączone po Wi-Fi. Chciałbym zaznaczyć, że sieć lokalna działa bez problemu. Przez usterki z łączem od vectry wymieniałem wszystkie skrętki, sprawdzałem zapory ogniowe, kupiłem kartę sieciową na PCI-E, przywracałem urządzenia do ustawień fabrycznych i tak dalej. Jestem w stanie bez problemu połączyć się ze swoim laptopem za pomocą SSH, hostować witryny, serwery do gier itp. itd. Usterki (których od momentu zawarcia umowy było osiem) charakteryzują się, przynajmniej z tego co mogę sprawdzić u siebie, brakiem "bezpiecznych" połączeń. To znaczy, monitoruję swoją sieć przy pomocy Uptime Kuma, który co minutę wysyła zapytania do różnych witryn internetowych i oczekuje na odpowiedź. Mierzę różne witryny, w tym reddit, cloudflare, google, wikipedia i tak dalej i za każdym razem jak sypie się łącze, to wszystko jest na czerwono. Nie są zwracane żadne błędy, tylko łącze po 48 sekund się poddaje i jest koniec. Dotyczy to wszystkich połączeń po TCP, TLS, SSH, HTTPS et cetera. Jeśli gram w jakąś grę na serwerze hostowanych po UDP, albo jestem na czacie głosowym na Discordzie, to nawet nie zauważę, że w tym momencie trwa usterka. Podobnie z domownikami oglądającymi telewizję. Sypnie im się dopiero gdy spróbują zmienić kanał. Do teraz, od 14tego października, Internet sypie się średnio co 10-20 minut (chociaż były przypadki, gdzie działał 5 minut a przerwa trwała po 45 minut) i ściśle rzecz ujmując nie wymaga ode mnie żadnych czynności. Mogę przyśpieszyć powrót prawidłowego działania łącza poprzez ręczne wyłączenie i włączenia routera od ISP, wypnięcie i wepnięcie kabla WAN z mojego routera do ich routera oraz reboot mojego Archer'a. Dzięki temu jestem w stanie ograniczyć przerwę do 2-5 minut, co nie zmienia faktu że mam ~60% uptime przez ostatnie 13 dni, a były dni gdzie przez 24h miałem ~7%. Co do dostawcy, no to kontaktowałem się z ich wsparciem klienta mailowo oraz telefonicznie chyba z 20 razy. Starałem się być kooperatywny i wyrozumiały wobec konsultantów, ale gdy słyszę po raz n-ty i że mam być cierpliwy bo nie są w stanie nic zrobić, że nie znają przyczyny problemu (bo najwyraźniej technicy nic nie piszą w notatkach ticketa), no to nie ciężko o palpitacje. Boli mnie to w szczególności dlatego, że to już ósmy raz, gdy dokładnie ten sam schemat i objawy usterki mają miejsce, i to wyłącznie pod moim adresem. Technicy uświadomili mnie, że jest 15 innych klientów vectry w mojej klatce, a tylko i wyłącznie ja zgłaszam jakiekolwiek problemy z łączem. Z desperacji udałem się do Rzecznika Praw Konsumentów, ale realnie nie będę w stanie wywalczyć dobrego łącza, jeśli VECTRA sama w sobie takiego nie położy. Przypomnę, że nie mam światłowodu (znaczy, są inni dostawcy, którzy go dostarczają, ale nie VECTRA), a tylko w ostatnim tygodniu technik był już pod moim mieszkaniem 4 razy. Z konkurencją również nie jest zbyt dobrze, przynajmniej ja dobrych doświadczeń z PLAY'em nie miałem a lokalny, mały dostawca, zatrzymał się w 2007 roku i dostarcza jedynie do 20 mbps down i 1 mbps upload po skrętce. Rzecznik też mnie poinformował, że najwięcej zgłoszeń/skarg jest u nich właśnie z VECTRA i na drugim miejscu PLAY, także wpadłem z deszczu pod rynne i zbyt dużego wyboru nie mam. Co do robienia z klienta idioty, to wielokrotnie sugerowali, że winą jest łącze bezprzewodowe i zakłócenia po Wi-Fi. Szkoda, że urządzenie na którym mierzę sieć jest połączone kablem, o czym wspominam na samym początku każdego zgłoszenia czy rozmowy. Pytają się "jakie mam oczekiwania"; no nie wiem, na przykład żeby Internet działał? Czy to naprawdę aż takie wysokie wymagania? Wiele razy wmawiali mi, że z ich punktu widzenia wszystko jest na zielono i parametry łącza są idealne -- oczywiście w trakcie gdy mi nie ładowały się żadne strony i wszystkie serwery wyrzucały kod błędu. Próbowali też mnie zniechęcać do dalszego drążenia usterki poprzez wykonywania bezużytecznych testów łącza przy pomocy mtr w trakcie usterki, po 30 minut każdy. Kto próbował, ten wie, że przy kompletnym braku Internetu 30 minutowy test mtr będzie trwał 2 godziny, a to tylko jeden test. Chcieli, żebym sprawdzał ten sposób wszystkie witryny jakie chciałem odwiedzić, co by trwało ~16 godzin. Koniec końców, wysłałem im te testy... kilka razy. Technik później mi powiedział, że nawet ich nie widział i sam ma wrażenie, że były bez sensu. Podobnie z głupotą o proszenie o speedtest, gdy ja nie mogę nawet wejść na żadną stronę. Wisienką na torcie jest pytanie o zgłoszenie skargi przy pomocy Strefy Klienta (na którą nie mogę wejść bez Internetu) lub pocztowo. Dostawca Internetowy, który sugeruje wysłanie pocztą skargi na ich łącze, nie wiem co powiedzieć... Technicy też tego łącza nie naprawili. Od konsultanta słyszałem, że sygnału już bardziej się wzmocnić nie da, a technik mi dzwoni, że założył tłumik i wzmacniacz, i teraz łącze będzie idealne. Standardowo, po godzinie/półtora od telefonu, łącze doświadcza tych samych problemów, ale oni zamykają ticket i dostaję SMS że usterka naprawiona. Byłem w salonie Orange i gdy chciałem zadać parę technicznych pytań to mi powiedzieli, że muszę najpierw podpisać umowę a dopiero potem pytać montera, który przyjdzie zamontować łącze. Fakt, że mogę w ciągu dwóch tygodni zrezygnować bez żadnych skutków czy kar, ale mimo wszystko trochę to podejście mi śmierdzi. Z tego co mi wiadomo, to ich Funbox nawet nie wspiera trybu mostka, więc musiałbym chyba montera błagać o ONT albo pogodzić się z tym, że będę musiał korzystać z ich softu. Z UPC łącze było nawet okej, ale po migracji do PLAY wszystko się zgównowaciło i musiałem się bardzo długo męczyć z ich wsparciem klienta i finalnie zrezygnować, bo usterki były jeszcze gorsze niż obecnie. Już serio nie wiem co robić. Rzecznik polecił napisanie skargi do Urzędu Telekomunikacji Elektronicznej, ale trochę jednak stresuje mnie pisanie do takiej instytucji na własną rękę. Macie pomysł co mogłem przeoczyć i co mogę jeszcze zrobić? edit: literówki
5 GitHub Projects That Feel Too Good to Be Free 🔥 5 GitHub Projects That Feel Too Good to Be Free! What if you could edit PDFs, monitor websites, back up your photos, and transfer files between devices — without paying for expensive software? In this video, we're exploring 5 amazing open-source GitHub projects that offer powerful features for free. Whether you're a developer, student, content creator, or tech enthusiast, these tools are worth checking out! 🚀 THE 5 PROJECTS: ✅ 1. Excalidraw – Create diagrams, flowcharts, and sketches. 🔗 excalidraw/excalidraw ✅ 2. Stirling PDF – Merge, split, compress, and manage PDF documents. 🔗 Stirling-Tools/Stirling-PDF ✅ 3. Uptime Kuma – Monitor your websites, APIs, and services. 🔗 louislam/uptime-kuma ✅ 4. Immich – Build your own photo and video library. 🔗 immich-app/immich ✅ 5. LocalSend – Transfer files between nearby devices without relying on cloud uploads. 🔗 localsend/localsend #GitHub #OpenSource #FreeSoftware ☺ Thanks For Watching! ☺ If you find this helpful, 💙Like and ✅ Subscribe
@portertech 可再加 Keyword/JSON Query 內容檢查,避免首頁回 200、內容卻變成維護頁還亮綠燈。Uptime Kuma 官方列有這兩種監控。配置後用測試服務停啟一次,確認故障與恢復通知都能到 Telegram,再把相同檢查加到關鍵業務入口。 louislam/uptime-kuma
Official fix is out: github.com/louislam/uptime-kuma/releases/tag/2.5.7