⚙ Portfolio-Projekt 06. May 2026 ~15 min. Lesezeit

Developer Dashboard — Sicheres Server-Monitoring & Content-Analytics

🧪 67 Tests 📑 10 Tabs 🔒 5 OWASP-Layer ⚡ Live in Prod 🗄️ PostgreSQL 📊 Chart.js
Django 5.2 Python 3.10 PostgreSQL 14 Chart.js 4.4 Bootstrap 5.3 psutil Gunicorn Nginx python-decouple GitHub Actions

Ausgangssituation

Ich betreibe seit 2024 ein eigenes Django-Blog auf einem VPS (Ubuntu + Nginx + Gunicorn + PostgreSQL). Mit wachsendem Content-Volumen und steigender Serveraktivität wurde der Bedarf nach einem zentralen, sicheren Monitoring-Dashboard offensichtlich. Keine Drittanbieter, keine SaaS-Kosten – das System sollte vollständig im eigenen Stack leben.

Ziele

Das Dashboard verfolgte von Beginn an drei gleichwertige Ziele:

  • Operational Visibility – Echtzeit-Blick auf Server, Prozesse und Content-Kennzahlen direkt im Browser
  • Security-First – Authentifizierung, Rate Limiting, CSP und weitere OWASP-konforme Maßnahmen als nicht verhandelbare Basis
  • Produktionsreife – kein Prototyp, sondern ein stabiles, getestetes, deploybares System

Design-Entscheidungen

Ich habe mich bewusst gegen fertige Admin-Frameworks (z. B. Jet, Grappelli) entschieden. Django Admin wäre zu unflexibel für Custom-Tabs und Live-Metriken gewesen. Das Dashboard wurde als eigenständige Django-App (docs) konzipiert, die im selben Projekt lebt – mit eigenem URL-Namespace, eigenem View-Layer und eigenem Template-System.

Die Tab-Struktur wurde so gewählt, dass jeder Tab genau einen Verantwortungsbereich abbildet: Daten, Server, Artikelverwaltung, Medien, Sicherheit, Terminal, Tests, Deployment, Roadmap und API-Explorer.

Aktueller Projektstand

Das Dashboard ist produktiv deployed und wird aktiv genutzt. 67 automatisierte Tests validieren kontinuierlich Authentifizierung, Rate Limiting, View-Logik und Security-Headers. Die gesamte Architektur ist in internen Markdown-Dokumenten beschrieben und versioniert.

Starting Point

Since 2024 I've been running my own Django blog on a VPS (Ubuntu + Nginx + Gunicorn + PostgreSQL). As content volume grew and server activity increased, the need for a central, secure monitoring dashboard became obvious. No third-party services, no SaaS costs — the system had to live entirely within my own stack.

Goals

The dashboard pursued three equally important goals from the start:

  • Operational Visibility – A real-time view of server, processes and content metrics directly in the browser
  • Security-First – Authentication, rate limiting, CSP and other OWASP-compliant measures as a non-negotiable foundation
  • Production Readiness – Not a prototype, but a stable, tested, deployable system

Design Decisions

I deliberately chose not to use ready-made admin frameworks (e.g. Jet, Grappelli). Django Admin would have been too inflexible for custom tabs and live metrics. The dashboard was conceived as a standalone Django app (docs) living within the same project — with its own URL namespace, view layer and template system.

The tab structure was designed so that each tab represents exactly one area of responsibility: Data, Server, Article Management, Media, Security, Terminal, Tests, Deployment, Roadmap and API Explorer.

Current Project Status

The dashboard is deployed to production and actively used. 67 automated tests continuously validate authentication, rate limiting, view logic and security headers. The full architecture is documented and versioned in internal Markdown files.

Architektur: Django MVT mit eigenem App-Layer

Das Dashboard lebt als docs-App im Django-Projekt. Der zentrale View ist eine einzige Funktion (docs_view) mit @login_required-Decorator. Er sammelt alle Kontext-Daten – Server-Stats, Artikel-Statistiken, Medien-Metadaten – und übergibt sie an ein einziges Template. Alle 10 Tabs werden client-seitig via JavaScript umgeschaltet; kein AJAX, keine zusätzlichen API-Endpunkte für den Dashboard-Kern.

Die Middleware-Schicht (config/middleware.py) ist verantwortlich für: Rate Limiting (IP-basiert, In-Memory-Sliding-Window), Security-Header-Injektion und Request-Logging. Sie ist vollständig unit-getestet und von den Views entkoppelt.

Analytics-Tab: Chart.js 4.4 mit Server-Side Aggregation

Der Analytics-Tab kombiniert drei Visualisierungstypen: ein Liniendiagramm für Artikel-Publikationsfrequenz (nach Monat), ein Balkendiagramm für Kategorienverteilung und eine KPI-Zeile mit Gesamtzahlen. Die Daten werden serverseitig aggregiert (Django ORM + annotate() + TruncMonth) und als JSON ins Template injiziert. Chart.js läuft rein client-seitig; keine Backend-Requests nach dem initialen Seitenload.

Technisches Detail: Responsive Charts

Chart.js skaliert die Canvas-Elemente standardmäßig nicht korrekt in Tab-Containern, die initial display:none haben. Das Problem wurde durch lazy initialization der Charts beim ersten Tab-Aktivierungsereignis gelöst – eine subtile, aber wichtige Implementierungsdetail.

Sicherheitsarchitektur: 5 OWASP-konforme Layer

Die Sicherheitsmaßnahmen sind in fünf unabhängige, testbare Layer aufgeteilt:

  • Authentication: @login_required + Django Session mit SESSION_COOKIE_HTTPONLY=True, SECURE_BROWSER_XSS_FILTER=True
  • Rate Limiting: Custom Middleware, 5 Versuche / IP / 15 min, HTTP 429-Response mit Retry-After-Header
  • CSP (Content Security Policy): Enforced via docs_view Response-Header, whitelist-basiert, keine unsafe-inline-Ausnahmen im Script-Bereich
  • CSRF: Django-Standard aktiv, alle POST-Formulare protektiert
  • Secret Management: python-decouple + .env-Datei – kein Secret im Repository

Terminal-Tab: Live Server-Metriken

Der Server-Tab liest via psutil CPU-Load, RAM-Nutzung, Disk-I/O und Prozessliste. Der Terminal-Tab zeigt einen simulierten Log-Stream mit farbigen Badges: ⚠ für Warnungen, ✓ für erfolgreiche Operationen. Die Darstellung ist rein HTML/CSS, kein WebSocket – bewusste Entscheidung für Einfachheit und Stabilität in der aktuellen Phase.

Test-Strategie: 67 Tests in 4 Kategorien

Die Testsuite ist in vier Klassen aufgeteilt:

  • AuthTests: Login-Redirect, Logout, Session-Expiry
  • RateLimitTests: Window-Reset, Burst-Schutz, IP-Isolation
  • DashboardViewTests: Tab-Rendering, Kontext-Variablen, HTTP-Status-Codes
  • SecurityHeaderTests: CSP, X-Frame-Options, X-Content-Type, HSTS

Alle Tests laufen in einer In-Memory-SQLite-Datenbank und werden in der CI/CD-Pipeline (GitHub Actions + self-hosted VPS-Runner) bei jedem Push ausgeführt.

Bewusste Weglassungen (jetzt)

WebSockets für Echtzeit-Updates, persistentes Logging in die Datenbank und ein eigenständiges API-Gateway für Dashboard-Daten wurden bewusst zurückgestellt. Der aktuelle Stand ist produktionsreif – Komplexität wird erst hinzugefügt, wenn der konkrete Bedarf besteht.

Architecture: Django MVT with Dedicated App Layer

The dashboard lives as a docs app within the Django project. The central view is a single function (docs_view) with a @login_required decorator. It gathers all context data — server stats, article statistics, media metadata — and passes it to a single template. All 10 tabs are toggled client-side via JavaScript; no AJAX, no additional API endpoints needed for the dashboard core.

The middleware layer (config/middleware.py) handles: rate limiting (IP-based, in-memory sliding window), security header injection and request logging. It is fully unit-tested and decoupled from the views.

Analytics Tab: Chart.js 4.4 with Server-Side Aggregation

The Analytics tab combines three visualisation types: a line chart for article publication frequency (by month), a bar chart for category distribution and a KPI row with overall totals. Data is aggregated server-side (Django ORM + annotate() + TruncMonth) and injected into the template as JSON. Chart.js runs purely client-side; no backend requests after the initial page load.

Technical Detail: Responsive Charts

Chart.js does not scale canvas elements correctly by default inside tab containers that start as display:none. The issue was resolved by lazily initialising charts on the first tab-activation event — a subtle but important implementation detail.

Security Architecture: 5 OWASP-Compliant Layers

The security measures are split into five independent, testable layers:

  • Authentication: @login_required + Django session with SESSION_COOKIE_HTTPONLY=True, SECURE_BROWSER_XSS_FILTER=True
  • Rate Limiting: Custom middleware, 5 attempts / IP / 15 min, HTTP 429 response with Retry-After header
  • CSP (Content Security Policy): Enforced via docs_view response header, whitelist-based, no unsafe-inline exceptions in the script scope
  • CSRF: Django standard active, all POST forms protected
  • Secret Management: python-decouple + .env file — no secrets in the repository

Terminal Tab: Live Server Metrics

The Server tab reads CPU load, RAM usage, disk I/O and process list via psutil. The Terminal tab shows a simulated log stream with coloured badges: ⚠ for warnings, ✓ for successful operations. The rendering is pure HTML/CSS, no WebSocket — a deliberate choice for simplicity and stability in the current phase.

Test Strategy: 67 Tests in 4 Categories

The test suite is split into four classes:

  • AuthTests: Login redirect, logout, session expiry
  • RateLimitTests: Window reset, burst protection, IP isolation
  • DashboardViewTests: Tab rendering, context variables, HTTP status codes
  • SecurityHeaderTests: CSP, X-Frame-Options, X-Content-Type, HSTS

All tests run against an in-memory SQLite database and are executed on every push via the CI/CD pipeline (GitHub Actions + self-hosted VPS runner).

Conscious Omissions (for now)

WebSockets for real-time updates, persistent logging to the database and a standalone API gateway for dashboard data were deliberately deferred. The current state is production-ready — complexity is only added when there is a concrete need for it.

No track selected

Click play to start