> ## Documentation Index
> Fetch the complete documentation index at: https://www.towbar.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Gatus

> Gatus checks service endpoints and displays their health on a status page.

export const UseCaseNavigation = () => {
  useLayoutEffect(() => {
    const storageKey = "towbar-use-case-open-groups";
    const groupSelector = "#sidebar li[data-title] > button[aria-expanded]";
    let restoring = false;
    let frame = 0;
    function storedGroups() {
      try {
        return new Set(JSON.parse(sessionStorage.getItem(storageKey) || "[]"));
      } catch {
        return new Set();
      }
    }
    function save(groups) {
      try {
        sessionStorage.setItem(storageKey, JSON.stringify([...groups]));
      } catch {}
    }
    function groupName(button) {
      return button.parentElement?.dataset.title;
    }
    function rememberOpenGroups() {
      const groups = new Set();
      for (const button of document.querySelectorAll(groupSelector)) {
        if (button.getAttribute("aria-expanded") === "true") {
          const name = groupName(button);
          if (name) groups.add(name);
        }
      }
      save(groups);
    }
    function restoreOpenGroups() {
      frame = 0;
      const groups = storedGroups();
      if (!groups.size) return;
      restoring = true;
      for (const button of document.querySelectorAll(groupSelector)) {
        if (groups.has(groupName(button)) && button.getAttribute("aria-expanded") === "false") {
          button.click();
        }
      }
      restoring = false;
    }
    function scheduleRestore() {
      if (!frame) frame = requestAnimationFrame(restoreOpenGroups);
    }
    function onClick(event) {
      if (restoring || !(event.target instanceof Element)) return;
      const button = event.target.closest(groupSelector);
      if (button) {
        const name = groupName(button);
        if (!name) return;
        const groups = storedGroups();
        if (button.getAttribute("aria-expanded") === "true") groups.delete(name); else groups.add(name);
        save(groups);
        return;
      }
      if (event.target.closest('a[href^="/docs/use-cases/"]')) {
        rememberOpenGroups();
      }
    }
    const observer = new MutationObserver(scheduleRestore);
    document.addEventListener("click", onClick, true);
    observer.observe(document.getElementById("sidebar") || document.body, {
      childList: true,
      subtree: true
    });
    scheduleRestore();
    return () => {
      document.removeEventListener("click", onClick, true);
      observer.disconnect();
      cancelAnimationFrame(frame);
    };
  }, []);
  return null;
};

<UseCaseNavigation />

**Upstream source:** [Current installation guide](https://github.com/TwiN/gatus).

Gatus needs a versioned list of endpoints to check. The sample checks one public URL; it does not require a separate database for this first setup.

## Towbar manifest

```yaml title=".towbar/services/gatus.compose.yml" theme={"system"}
id: gatus
name: Gatus
file: deploy/gatus/compose.yml
strategy: maintenance
services:
  gatus:
    port: 8080
    domains:
      - gatus.example.com
    ingress:
      type: proxy
environments:
  production:
    server: 192.0.2.10
```

## Compose project

<CodeGroup>
  ```yaml title="deploy/gatus/compose.yml" theme={"system"}
  services:
    gatus:
      image: twinproduction/gatus@sha256:094eb186e55235db367e90e9d56140e5897b7044c41de23cde4cc18e6da1242e
      configs:
        - source: checks
          target: /config/config.yaml
  configs:
    checks:
      file: ./config.yaml
  ```

  ```yaml title="deploy/gatus/config.yaml" theme={"system"}
  endpoints:
    - name: Example site
      url: https://example.com
      interval: 1m
      conditions:
        - "[STATUS] == 200"
  ```
</CodeGroup>

## Configure

1. Prepare the example server, connect the repository, and map `production` to the branch containing these files. Replace the example server IP and domain.
2. Commit every file shown below under `deploy/gatus/`. The Towbar manifest points to the Compose file; it does not create it for you.
3. Sync the repository and inspect the resolved Compose project. Save the runtime values below if this example declares any.
4. Replace the example endpoint with a URL you control. Add alerting only after the basic check works; destination credentials belong in Towbar runtime secrets, not this file.
5. Deploy it manually and run the verification below before enabling auto-deploy.

## Verify

Open the status page, verify that the endpoint has a recent successful check, then temporarily use a failing URL to confirm the failure appears.

For field constraints, see [Compose guide](/docs/services/modes/compose).
