Skip to content

Status Page

URL: status.xynap.tech Container: status-page Port: 8090 (internal) Version: 2.7.0

The public status page displays the current state of all xynap services, a 90-day uptime history, and active incident reports. It is accessible without login.

Features

Feature Description
Live Status Real-time status of all components via Docker API
Uptime History 90-day bar chart per component
Incidents Current and past incidents with updates
Email Subscription Notifications on outages (double opt-in, i18n)
Incident Notify Automatic email to subscribers on new updates
Multilingual German / English (UI + API)
Dark Mode Automatic or manually toggleable
REST API Full API with Swagger documentation

Architecture

Browser ──▶ Traefik ──▶ status-page:8090 (FastAPI + Uvicorn)
                              ├── Docker Socket (Container Health)
                              ├── /data/services.json (Configuration)
                              ├── /data/incidents.json (Incidents)
                              ├── /data/uptime.json (90-Day History)
                              ├── /data/subscribers.db (SQLite)
                              └── /data/notified.json (Deduplication)

The service checks the state of configured containers every 5 minutes via the Docker API and stores the results in uptime.json.

Configuration

Environment Variables

Variable Default Description
SERVICES_FILE /data/services.json Component configuration
INCIDENTS_FILE /data/incidents.json Incident reports
UPTIME_FILE /data/uptime.json Uptime data
SUBSCRIBERS_DB /data/subscribers.db Subscriber database
CHECK_INTERVAL 300 Check interval in seconds
SMTP_HOST hosting-postfix SMTP server for emails
SMTP_PORT 25 SMTP port
MAIL_FROM status@xynap.tech Sender address
BASE_URL https://status.xynap.tech Base URL for email links
NOTIFIED_FILE /data/notified.json Deduplication of sent notifications

services.json

This file defines the monitored components:

{
  "components": [
    {
      "id": "platform-api",
      "name": "Platform API",
      "name_en": "Platform API",
      "container": "platform-api",
      "group": "core"
    },
    {
      "id": "mail-service",
      "name": "E-Mail Dienst",
      "name_en": "Email Service",
      "container": "hosting-postfix",
      "group": "hosting"
    }
  ]
}
Field Description
id Unique identifier (URL-safe)
name German display name
name_en English display name
container Docker container name for health checks
group Optional grouping

incidents.json

Incidents are managed manually in this file:

[
  {
    "id": "inc-2026-03-10-mail",
    "title": "E-Mail Zustellung verzoegert",
    "title_en": "Email delivery delayed",
    "status": "resolved",
    "severity": "minor",
    "components": ["mail-service"],
    "created_at": "2026-03-10T08:30:00Z",
    "resolved_at": "2026-03-10T10:15:00Z",
    "updates": [
      {
        "status": "investigating",
        "message": "Wir untersuchen Verzoegerungen bei der E-Mail-Zustellung.",
        "message_en": "We are investigating delays in email delivery.",
        "timestamp": "2026-03-10T08:30:00Z"
      },
      {
        "status": "resolved",
        "message": "Problem behoben. Alle E-Mails werden normal zugestellt.",
        "message_en": "Issue resolved. All emails are being delivered normally.",
        "timestamp": "2026-03-10T10:15:00Z"
      }
    ]
  }
]

REST API

The API is available at https://status.xynap.tech/api/v1/. Swagger documentation: status.xynap.tech/api/docs

Language Control

The API supports German and English:

  1. ?lang=de / ?lang=en — Explicit parameter (highest priority)
  2. Accept-Language header — Automatically sent by browsers
  3. Default: English — For API clients without header (curl, Postman)

Endpoints

Status

# Overall status of all services
GET /api/v1/status?lang=en

# Response
{
  "status": "operational",
  "components": [...],
  "incidents": [...],
  "timestamp": "2026-03-12T14:30:00Z"
}

Components

# All components
GET /api/v1/components

# Single component
GET /api/v1/components/{component_id}

Uptime

# 90-day uptime of all components
GET /api/v1/uptime

# Single component (days configurable: 1-90)
GET /api/v1/uptime/{component_id}?days=30

Incidents

# All incidents (max 100)
GET /api/v1/incidents?limit=20

# Filter by status
GET /api/v1/incidents?status=investigating

# Single incident
GET /api/v1/incidents/{incident_id}

Subscription

# Subscribe email
POST /api/v1/subscribe
Content-Type: application/json
{"email": "user@example.com", "lang": "en"}

Confirmation and unsubscribe links are sent automatically via email (double opt-in).

Email Notifications

Subscription Flow

  1. Sign up: User enters email address on the status page
  2. Confirmation: Double opt-in via confirmation email (in the language chosen at sign-up)
  3. Notification: Automatically on new incident updates (in the subscriber's stored language)
  4. Unsubscribe: Every email contains an unsubscribe link

Incident Notifications

The background task checks incidents.json every 5 minutes for new updates:

  • Each incident update is identified by hash (incident_id:timestamp)
  • New updates are sent to all confirmed subscribers
  • Each subscriber receives the email in their language chosen at sign-up (DE/EN)
  • Already sent updates are tracked in notified.json (no duplicates)
  • On first start, existing updates are marked as "already sent"

SMTP

Emails are sent via the internal Postfix (hosting-postfix). Sender: status@xynap.tech

Deployment

The container is managed via the Docker stack:

# Build and start container
sudo docker compose -f /etc/xynap/stack/docker-compose.yml up -d --build status-page

# View logs
sudo docker compose -f /etc/xynap/stack/docker-compose.yml logs -f status-page

# On code changes: bypass cache
sudo docker compose -f /etc/xynap/stack/docker-compose.yml build --no-cache status-page
sudo docker compose -f /etc/xynap/stack/docker-compose.yml up -d status-page

Docker Build Cache

When modifying app.py or index.html, the build cache must be bypassed with --no-cache, as Docker otherwise reuses cached COPY layers.

Files

Path Description
/usr/local/xynap/status-page/app.py FastAPI backend
/usr/local/xynap/status-page/static/index.html Frontend (single-page)
/usr/local/xynap/status-page/Dockerfile Container definition
/var/lib/xynap/status-page/ Persistent data (volume)
/var/lib/xynap/status-page/notified.json Sent notification hashes