TurboPanel Docs
Using TurboPanel

Notifications

When something happens that a person should know about — a server goes offline, a daemon key is revoked, access is granted — TurboPanel writes it to the bell of everyone concerned, and delivers it to any channel a rule routes it to: an email address, a chat room, a webhook. This chapter is the bell, Account → Notifications (/account/notifications), and what an operator can expect from delivery.

Private alpha — the catalogue is short on purpose

Only events that the platform actually raises are listed; today that is six. Each new emitter joins the catalogue in the same commit as the code that raises it, so what the rules matrix offers is always what can arrive.

The model

TermMeaning
EventOne thing that happened, with a stable code (server.offline), a severity (info, warning, critical) and a scope: it belongs to one organization, or to the instance as a whole.
InboxYour own rows behind the bell. A server event lands in the inbox of every member of that organization; the events that mirror the audit trail — deletes, key revokes, grant changes — reach only its owners and managers; an instance event reaches every instance administrator. No setup needed.
ChannelSomewhere outside the console a notification can be delivered. Yours (they follow your account across organizations), the organization's (managers edit them), or the instance's — an administrator's receivers that hear every event on the instance, managed through the admin API for now. Kinds: email, webhook, slack, discord, telegram.
RuleWhat a channel receives: every event at or above a severity floor, or a chosen list of events. A channel with no rule receives nothing.
DeliveryOne attempt ledger per event × channel: written before the send, retried on failure with backoff, abandoned after five attempts.

Three facts:

  • A channel's address is a credential. A webhook URL's path is the secret, and so is a bot token. They are stored sealed under the instance's data-encryption key and never shown again — the screen shows the origin, or the last few characters.
  • Addresses must be https with no credentials in the URL. That is the whole rule: a LAN receiver (an Alertmanager next to the control plane, a 10.x address, a bare hostname) is allowed on every runtime. A hosted instance cannot reach a private address, so a delivery there simply fails and is recorded as such.
  • Delivering never blocks the thing being reported. A webhook that is down does not stop a deploy or a sweep; it leaves a failed delivery that the maintenance tick retries.

The events

CodeSeverityScopeInboxWhen
server.offlinecriticalorganizationevery memberThe daemon stopped answering and the server was marked offline.
fleet.mass_disconnectcriticalinstanceadministratorsA whole sweep lost its fleet at once — usually the control plane's own network or broker.
server.deletedinfoorganizationowners and managersA server was deleted from the console.
server.daemon_key_revokedwarningorganizationowners and managersA server's daemon key was revoked.
access.grant_createdinfoorganizationowners and managersA permission grant was added.
access.grant_revokedwarningorganizationowners and managersA permission grant was removed.

The bell

The bell in the header (the avatar badge on the phone apps) shows your unread count, polled once a minute. Open it for the newest rows: a coloured dot for severity, the title and the sentence, when it happened. Mark all read clears the badge; × dismisses a row; a row that names a server opens that server. Notification settings at the bottom opens the preferences screen.

Add a channel

Account → Notifications. Two panels: Your channels and Organization channels (the organization you last opened; only a manager may add or edit there).

Pick the kind — Email, Webhook, Slack, Discord or Telegram — and give the channel a Name.

Enter the address: an email address — your own for a personal channel, a member's account email for an organization one (other addresses wait for a verification flow that does not exist yet); an https URL that accepts a JSON POST; a Slack or Discord incoming-webhook URL; or, for Telegram, your bot token, a slash, then the chat id (123456:ABC…/987654321). For a webhook you may add a signing secret.

Choose the rules: Every event at a floor (Everything, Warnings and up, Critical only), or switch to Chosen events and tick them. Add channel.

Each channel is then a row with its rules (change them and Save rules), Pause / Resume, Remove, and the outcome of the last delivery in the past week.

What a receiver gets

KindBody
WebhookJSON: event, severity, title, body, text (the one-line form), organizationId, target ({ type, id } or null), context (small non-secret facts), at. Headers X-TurboPanel-Event: <code> and, when the channel has a signing secret, X-TurboPanel-Signature: sha256=<hex> — HMAC-SHA256 of the raw body with the secret.
Slack{ "text": "…" } — the title, the sentence, then key=value facts in parentheses. Mattermost and Rocket.Chat read the same field.
Discord{ "content": "…" }, the same line.
TelegramsendMessage to the chat id with the same line.
EmailSubject [TurboPanel Critical] Server db-1 went offline; the sentence, the facts as a list, and an Open in TurboPanel button when the event has a target.

Verify a webhook signature by computing sha256= + hex(HMAC-SHA256(secret, raw body)) and comparing it to the header with a constant-time comparison.

Delivery and retries

One attempt is made at the moment of the event, with a five-second budget per channel; the retry sweep leaves a fresh row alone for two minutes so a slow attempt is never sent twice. A failure — a non-2xx answer, a timeout, a refused address — is recorded with a short code (http_503, timeout, network, address_scheme_not_https) and retried by the maintenance tick after 1, 5, 25 and 125 minutes; after the fifth failure the delivery is abandoned. Email deliveries ride the instance's mailer queue (self-hosted: RabbitMQ → the mailer service; High Availability: Mailgun) and are subject to its own retry. The channel row shows the last delivery's status and how many attempts it took.

Reference

ItemValue
Kindsemail · webhook · slack · discord · telegram (push is registered by the store apps, never typed)
Severitiesinfo < warning < critical
Rule* at a floor, or one row per event
Inbox fan-outserver events: every organization member; audit-mirroring events: owners and managers; instance events: every instance admin
Channel reachorganization channels, its members' own channels, and every instance channel
Address rulehttps, no credentials in the URL; any host, LAN included
Retry1 → 5 → 25 → 125 minutes, five attempts, then abandoned
SignatureX-TurboPanel-Signature: sha256=<hex HMAC-SHA256 of the raw body>
Name≤ 80 characters; address ≤ 2048; signing secret ≤ 256

Errors

CodeStatusMeaning
address_rejected422The URL failed the outbound gate; reason says which rule (scheme_not_https, credentials_in_url, malformed).
address_invalid, address_required400Not an email address / not a token-slash-chat-id pair / empty.
address_not_a_member422An email channel may only name your own address, or a member's account email for an organization channel.
label_required, label_invalid400The name is missing, too long, or has control characters.
signing_secret_not_applicable400Only a webhook channel signs its deliveries.
signing_secret_invalid4001–256 characters.
rule_event_unknown400A rule names an event that is not in the catalogue (reason carries it).
rule_severity_invalid, rules_invalid400The rule list is malformed.
kind_invalid, scope_invalid400Not one of the kinds above, or not user / organization.
Forbidden403Organization channels need organization:manage.
Not found404The channel or the inbox row is not yours.
Encryption unavailable — no encryption key configured503The instance has no root secret, so a sealed address cannot be stored.
Edit on GitHub

Last updated on

On this page