# Status page

Set up a public status page and optional email updates.

The public status page shows service status, incidents, and history at `/status` and,
optionally, on its own domain.

## Set up the page

1. **Add branding.**

   Add a `[brand]` section to `kogut.toml`:

   ```toml title="kogut.toml"
   [brand]
   name = "Acme"
   logo = "acme.svg"
   accent = "#d9480f"
   status_domain = "status.acme.com"
   ```

   Put a local logo in the data directory, or use a URL. A local logo appears only on the
   status domain, so use a URL for a page shared at `/status`. Keys and formats are in the
   [branding reference](https://docs.kogut.dev/reference/configuration/#brand).

2. **Route the domain.**

   Point the domain at your server and route it through your reverse proxy:

   ```caddy title="Caddyfile"
   status.acme.com {
       reverse_proxy localhost:8484
   }
   ```

   kogut picks the status page by the `Host` header and serves plain HTTP, so the proxy
   handles TLS. See [Behind Caddy](https://docs.kogut.dev/installation/caddy/).

   The status domain does not expose the panel or API. Other paths return the status page
   for `GET` and `HEAD`, except `/status-logo` and the subscription paths
   `/status/subscribe`, `/status/confirm`, and `/status/unsubscribe`.

3. **Check the public components.**

   Open the domain, or `/status` on the panel's domain. Every service with a server-run
   HTTP check of a public address, without `from`, appears as a component under its own
   name.

   File-managed services appear in file order, followed by panel-created services by name.
   Agent-only checks, private addresses, TCP, DNS, and heartbeats do not qualify. Dotless
   hostnames and names ending in `.local`, `.localhost`, `.internal`, `.lan`,
   `.home.arpa`, or `.corp` count as private.

   Check that only the intended services appear. Check URLs, host names, error details,
   likely causes, and logs are never public.

Branding is set only in the file. The panel's **Status page** screen has a preview and
links.

## Enable email updates

The subscription form appears only with `subscriptions = true`, an email channel in
`kogut.toml`, and a status domain or public URL.

1. Configure an [email channel](https://docs.kogut.dev/alerts/channels/#email) in `kogut.toml`. Subscriber mail
   uses the first email channel in the file and its `from` address, never a panel channel.
2. Add `subscriptions = true` to `[brand]`, and set a status domain or the panel's public
   URL so emails have valid links.
3. Open the page and subscribe with a test address. Open the confirmation link and press
   the button. Confirmation links expire after 48 hours. Requests for a pending address
   resend at most once every 15 minutes. Already-subscribed addresses receive nothing.
4. Check the unsubscribe link. Following it shows a button, which deletes the subscription
   and its queued messages. Emails also support one-click unsubscribe in mail apps.

Subscribers receive an email after a public incident stays open for two minutes, when its
public title changes, and when it resolves. Shorter incidents send nothing. Messages show
only public details, UTC times, and a status-page link.

Subscriber mail uses the notification queue and its retries, apart from team alerts. It is
sent one message at a time and counts against the provider's sending limits, so use a
transactional email provider for large lists.

The form accepts five requests per client per hour and 200 in total. A client is an
IPv4 address or an IPv6 /64 network. Limits are 1,000 unconfirmed and 10,000 total
subscriptions.

kogut stores subscriber addresses, subscription and confirmation times, and link
tokens. Rate limits use an in-memory keyed address hash for up to an hour, not a stored
IP address.

To stop updates, set `subscriptions = false`. This hides the form and discards unsent
subscriber mail, including confirmations, but keeps subscribers and allows unsubscribe.
Enabling updates again sends notices about incidents from then on.

## Read the history

Each day shows its worst state over the last 90 days. Hover over a day for its status and
uptime. Days and times use UTC. Major outages count fully against uptime, partial outages
count half, and degraded performance does not reduce uptime. Time without check data
does not count. Domain-registration checks do not count either.

Public incidents appear automatically with neutral titles such as "api: major outage".
All service checks down means a major outage, some down means partial, and none down
means degraded performance. Titles and updates cannot be edited. Maintenance windows
hold notifications but do not appear on the page.

Reload to see changes. The page has no JavaScript or automatic refresh. kogut caches its
HTML for 10 seconds, and browsers or CDNs may cache responses for a minute.

To keep the page up when your app server is down, run kogut on another machine. See
[Setups](https://docs.kogut.dev/high-availability/setups/).
