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:
?lang=de/?lang=en— Explicit parameter (highest priority)Accept-Languageheader — Automatically sent by browsers- 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¶
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¶
- Sign up: User enters email address on the status page
- Confirmation: Double opt-in via confirmation email (in the language chosen at sign-up)
- Notification: Automatically on new incident updates (in the subscriber's stored language)
- 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 |