Status Page
Your kuploy-cloud deployment ships with a public status page at
/status (e.g. https://console.example.com/status). It shows real-time
component health and lets you publish incidents to your customers.
It works alongside the central platform status page at
kuploy.app/status (or whatever your
LICENSE_HUB_URL points to), which covers the upstream platform you
depend on (licensing hub, billing, central registry).
What Customers See
The page is public, no sign-in. Three sections, top to bottom:
| Section | Content |
|---|---|
| Status banner | "All systems operational" / "Degraded" / "Major outage" |
| Active incidents | Any incident you've posted that isn't resolved yet |
| Components | One row per component with the last 90 days of uptime |
| Past incidents | Resolved incidents from the last 14 days |
The page refreshes every 30 seconds. Customers don't need an account to view it.
Components Tracked
Out of the box:
| Component | Probe |
|---|---|
| Dashboard | HTTP GET /api/health on this deployment |
| Database | SELECT 1 against the primary Postgres |
| Email Hosting | Stalwart management API ping (only if configured) |
| Container Registry | Registry /v2/ ping (only if configured) |
| Build Runner | Queue-health probe — flags when >50 deployments have been running for >1h |
| Custom Domain DNS | Resolves one registered custom domain (only if any are registered) |
Email Hosting, Container Registry, and Custom Domain DNS are hidden when not configured — they only appear on the public page once there is something to probe. Dashboard, Database, and Build Runner always show.
How the Probes Run
kuploy-cloud runs the probe in-process, on an internal scheduler
(the same mechanism used by the license sync and stuck-build detector).
There is no cron to configure, no Vercel, no Kubernetes CronJob. Once
the tenant pod is up, probes start firing every 5 minutes automatically.
Cadence is controlled by the STATUS_PROBE_INTERVAL_SECONDS env var
(clamped 60..3600; default 300 = 5 min). Change it and redeploy.
There's still a /api/cron/status-probe HTTP route gated by
CRON_SECRET — kept for manual ops use. You don't need to schedule it;
the in-process loop is authoritative.
Publishing Incidents
When something is wrong and you want to communicate it to customers proactively:
- Sign in as a platform admin
- Admin → Status — Incidents
- New incident: title, severity, optional component, and the public-facing description
- As the situation evolves, post updates from the same row to advance through Investigating → Identified → Monitoring → Resolved
- Posting an update with status Resolved moves the incident to "Past incidents (14 days)"
Incidents you post show up immediately on the public /status page; no
deploy needed.
You don't toggle "operational" or "down" by hand — those come from the probes. Incidents add the human story on top: what happened, what you're doing about it, when it's resolved.
Severities
| Severity | Use for |
|---|---|
| Minor | Single non-critical component degraded, with workarounds |
| Major | Customer-visible disruption affecting normal use |
| Critical | Significant downtime or data risk |
| Maintenance | Planned maintenance windows you've announced in advance |
The Upstream Platform Row
Your status page shows an Upstream platform row at the top whenever
the licensing hub's /api/status is reachable. The URL is resolved in
this order:
PLATFORM_STATUS_URL— explicit overrideLICENSE_HUB_URL+/api/status— same hub you license againsthttps://kuploy.app/api/status— default
This lets customers see "the upstream is fine, the issue is local" — or the opposite — without leaving your status page.
To hide the row entirely (e.g. air-gapped deployments), set
PLATFORM_STATUS_URL="" (empty).
Recommended Workflow
A practical flow that works well with this system:
- Discover an issue (alert, customer report, log).
- Acknowledge publicly within minutes by posting a
Minor/Majorincident with status Investigating. Customers stop guessing. - Update at least every 30 minutes while active, even if the only update is "still investigating, no new info" — silence is worse than no updates.
- Resolve with a one-line root-cause summary so customers can read it later in the 14-day past-incidents list.
Notifying Your Team on Incidents
Incidents you publish can also fan out to your configured notification channels — Slack, Discord, Email, Telegram, etc. — using the same pipeline that handles usage and support-ticket events.
Three events are available:
- Status: Incident Created — fires when you publish a new incident
- Status: Incident Updated — fires on each update (investigating / identified / monitoring)
- Status: Incident Resolved — fires when you resolve an incident
All three default OFF (unlike support-ticket events) so existing channels don't suddenly receive a new class of notifications. Opt in per channel from Account → Billing → Notification Channels.
See Billing Notifications for channel setup.
Upstream Platform Status Alerts
Your deployment automatically monitors the upstream licensing hub's
overall status (via LICENSE_HUB_URL). When the hub's state transitions
— e.g. operational → major outage, or outage → operational — a
Platform Status Changed notification fires through your configured
channels.
This event is on by default for every channel, so operators are
alerted immediately when the upstream they depend on goes down or
recovers. Disable per channel if you'd rather check the /status
page manually.
JSON API for Third-Party Monitoring
Your deployment also exposes a public JSON endpoint at /api/status
(no authentication). It returns the same data the /status page
renders — overall state, per-component health, active and recent
incidents — in a machine-readable format.
Use it with services like UptimeRobot, BetterStack, Pingdom, or any
tool that polls a URL and alerts on non-"operational" values. Example:
curl -s https://your-tenant.example.com/api/status | jq .overall
# "operational"
The link is deliberately not shown on the public /status page to
keep the customer-facing surface clean. It's documented here for
operators who need it.
Customizing the Page
The status page picks up your tenant branding automatically from Admin → Theme & Branding:
| Theme field | Where it appears on /status |
|---|---|
| Site name | Header title and browser tab (<Tenant> — Status) |
| Logo | Header, next to the site name |
| Favicon | Browser tab icon |
| Theme colors (HSL) | Page chrome (background, borders, links, accents) |
| Footer copyright | Footer line above "Status snapshot refreshes…" |
| Custom CSS | Injected globally; can override anything on the page |
Component state colors (green/yellow/orange/red for operational/degraded/partial/major) are deliberately not themed — those are universal conventions and customizing them would confuse customers reading the page.
Custom Domain
The status page is served from /status on whichever hostname your
kuploy-cloud instance answers. If you've configured a custom domain for
your tenant deployment (e.g. cloud.example.com), the page is
automatically reachable at https://cloud.example.com/status with no
extra setup — the route isn't special.
Want a dedicated status.example.com hostname instead? Point an A or
CNAME record at your tenant deployment and the /status route will
answer on that host too. No code change needed.
Related Pages
- Admin Dashboard — where the incident editor lives
- Email Hosting — the Stalwart probe and live-status card
- Billing Notifications — for channel-based alerts (incident events are opt-in per channel)