Skip to content

About

No description, website, or topics provided.

Resources

Stars

20 stars

Watchers

1 watching

Forks

Latest commit

 

History

30 Commits

Folders and files

Repository files navigation

M365 Speicher-Dashboard

🇩🇪 Deutsch (dieser Abschnitt) · 🇬🇧 English version below

OnePage-Web-App (PowerShell/Pode), die per Microsoft Graph die Postfachgrössen und OneDrive-Belegung aller Benutzer eines Microsoft-365-Tenants ausliest, in einer SQLite-Datenbank historisiert und als Dashboard darstellt:

  • Kacheln: Gesamtbelegung, Mailboxen, OneDrive, Zuwachs seit Beginn sowie Benutzerzahl mit AufschlĂĽsselung pro Lizenztyp (inkl. freigegebener Postfächer)
  • Diagramm: Belegung ĂĽber Zeit (Mailbox / OneDrive getrennt, Tooltip mit Gesamt)
  • Benutzerliste: sortierbar (Klick auf Spaltenkopf), Volltextsuche, Filter (Quota > 80 %, Top 10, freigegebene Postfächer), Lizenzspalte, Quota-Balken mit Warnschwellen (80 % / 95 %). Freigegebene Postfächer werden erkannt (Postfach vorhanden, Konto deaktiviert, keine Lizenz) und separat ausgewiesen
  • Einstellungen im UI: Tenant-ID, Client-ID, Client-Secret (verschlĂĽsselt gespeichert), Demo-Modus, Sprache (Deutsch/Englisch)
  • Darstellung: Design Dunkel (Standard) oder Hell sowie eigene Farben fĂĽr Akzent, Mailboxen, OneDrive, SharePoint, Seitenhintergrund und Karten, getrennt je Design. Live-Vorschau im Dialog, «Standardfarben» setzt das gewählte Design zurĂĽck. Praktisch, um das Dashboard optisch ins Intranet einzupassen
  • SharePoint-Reiter: alle Websites mit Speicherbelegung, Typ (Team/Kommunikation), Besitzer, Dateizahl, aktiven Dateien, Seitenaufrufen und letzter Aktivität; Inaktiv-Markierung (> 90 Tage) als Archivierungs-Kandidaten, eigener Zeitverlauf, Suche/Sortierung/Filter wie bei den Benutzern
  • Automatik: eingebauter Wochen-Schedule (Standard: Montag 06:00) erfasst die Daten selbstständig, solange der Server läuft

Screenshots (Demo-Modus)

Benutzer-Ansicht

SharePoint-Ansicht

Voraussetzungen

  • Windows Server oder PC (getestet auch unter macOS/Linux fĂĽr Entwicklung)
  • PowerShell 7 (winget install Microsoft.PowerShell)
  • Module: Install-Module Pode, PSSQLite -Scope CurrentUser (unter macOS/Linux wird statt PSSQLite automatisch das System-sqlite3 benutzt)

Einrichtung (einmalig)

Am einfachsten zuerst den Server starten und dann das Setup ausfĂĽhren, angemeldet als Global Administrator des Kunden-Tenants:

pwsh ./start.ps1
pwsh ./setup.ps1

setup.ps1 erledigt alles in einem Lauf:

  1. installiert fehlende Module (Microsoft Graph, Pode, PSSQLite)
  2. legt die App-Registrierung an (oder verwendet die vorhandene), setzt die vier Graph-Berechtigungen samt Administratorzustimmung und erstellt ein Client-Secret (24 Monate)
  3. schaltet die Pseudonymisierung der Berichte ab (-KeepConcealedNames lässt sie)
  4. trägt Tenant-ID, Client-ID und Secret direkt im Dashboard ein. Läuft der Server, gehen die Werte über seine API, damit er das Secret unter seinem eigenen Konto verschlüsselt (passt also auch, wenn er als Dienst unter SYSTEM läuft)
  5. testet die Verbindung und startet die erste Erfassung. Solange neue Berechtigungen noch nicht aktiv sind, versucht es das bis zu 10 Minuten erneut

Das Script kann gefahrlos erneut laufen, etwa wenn das Secret abläuft: Es ergänzt fehlende Berechtigungen und erstellt ein neues Secret. Im Ordner setup/ liegen zusätzlich die Einzelschritte und die PDF-Anleitung (neu erzeugen mit python3 setup/build-anleitung.py, braucht reportlab); 02-get-ids.ps1 prüft eine bestehende Registrierung (Berechtigungen, Secret-Ablauf).

Alternative: von Hand im Portal

  1. Entra Admin Center → App-Registrierungen → Neue Registrierung (Name z. B. „Speicher-Dashboard", nur dieser Tenant).
  2. API-Berechtigungen → Hinzufügen → Microsoft Graph → Anwendungsberechtigungen → Reports.Read.All, User.Read.All, Organization.Read.All und Sites.Read.All → Administratorzustimmung erteilen. (Reports.Read.All ist Pflicht. User.Read.All/Organization.Read.All liefern Lizenztypen und die Erkennung freigegebener Postfächer; Sites.Read.All die Anzeigenamen der SharePoint-Websites, da der Usage-Report in vielen Tenants keine Site-URLs mehr enthält. Fehlen optionale Rechte, läuft die Erfassung trotzdem — das Dashboard zeigt dann einen Hinweis.)
  3. Zertifikate & Geheimnisse → Neuer geheimer Clientschlüssel (Laufzeit z. B. 24 Monate) → Wert sofort kopieren.
  4. Notieren: Verzeichnis-ID (Tenant), Anwendungs-ID (Client), Secret.
  5. Wichtig — Klarnamen in Berichten: Im Microsoft 365 Admin Center unter Einstellungen → Organisationseinstellungen → Berichte die Anzeige verborgener Benutzernamen aktivieren (Haken bei Pseudonymisierung entfernen), sonst liefern die Reports nur Hashes. Das Dashboard zeigt in dem Fall eine Warnung.

Start

pwsh ./server.ps1

Dashboard: http://localhost:8080 (Port in settings.json änderbar). Nach setup.ps1 ist alles eingetragen. Wer die App von Hand registriert hat, öffnet ⚙︎ Einstellungen, trägt die drei Werte ein, klickt Verbindung testen, speichert und dann Jetzt erfassen.

Der Demo-Modus (Checkbox in den Einstellungen) erzeugt Beispieldaten mit 13 Wochen Historie — praktisch für Vorführungen ohne Tenant-Zugriff.

Als Dauerdienst unter Windows

Am einfachsten als geplanter Task, der beim Systemstart läuft:

Register-ScheduledTask -TaskName 'M365UsageDashboard' `
  -Action (New-ScheduledTaskAction -Execute 'pwsh.exe' -Argument '-NoProfile -File C:\Apps\m365-usage-dashboard\server.ps1') `
  -Trigger (New-ScheduledTaskTrigger -AtStartup) `
  -Settings (New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1)) `
  -User 'SYSTEM' -RunLevel Highest

Hinweis: Wird der Task unter einem anderen Konto ausgefĂĽhrt als dem, mit dem das Secret gespeichert wurde, muss das Secret einmal unter diesem Konto neu gespeichert werden (DPAPI ist benutzergebunden).

Docker (z. B. Synology NAS)

Fertiges Image fĂĽr amd64 und arm64: ghcr.io/aussiech/m365-usage-dashboard. docker-compose.yml anpassen (Passwort und SchlĂĽssel) und starten, auf der Synology ĂĽber Container Manager > Projekt > Erstellen:

docker compose up -d

Im Container lauscht der Server im Netzwerk und verlangt deshalb immer ein Login (DASHBOARD_PASSWORD). Das Client-Secret wird mit DASHBOARD_SECRET_KEY per AES-GCM verschlĂĽsselt abgelegt. Tenant-ID, Client-ID und Secret lassen sich auch per M365_TENANT_ID, M365_CLIENT_ID, M365_CLIENT_SECRET vorgeben. Daten liegen im Volume /data. FĂĽr den Zugriff ĂĽber das Internet HTTPS davorschalten (Synology Reverse-Proxy). Details in Kapitel 6 der PDF-Anleitung.

Datenhaltung

  • data/usage.db — SQLite; Tabelle snapshots mit einem Datensatz pro Benutzer und Snapshot-Datum (PrimärschlĂĽssel snapshot_date, upn), Tabelle site_snapshots analog pro SharePoint-Site (snapshot_date, site_id), Tabelle meta.
  • Erfassung ĂĽberschreibt denselben Tag idempotent (INSERT OR REPLACE) — mehrfaches „Jetzt erfassen" erzeugt keine Duplikate.
  • settings.json — Konfiguration; das Client-Secret ist unter Windows per DPAPI verschlĂĽsselt und wird von der API nie zurĂĽckgegeben.
  • Die Graph-Reports werden von Microsoft mit ca. 24–48 h Verzögerung aktualisiert; das Snapshot-Datum entspricht dem „Report Refresh Date" des Reports.

Aufbau

Datei Zweck
server.ps1 Pode-Server: statisches UI, REST-API, Wochen-Schedule
src/Graph.psm1 Token (Client Credentials) + Reports-Abruf/-Merge, Demodaten
src/Storage.psm1 SQLite-Zugriff (PSSQLite bzw. sqlite3-CLI)
src/Settings.psm1 Einstellungen laden/speichern, Secret-VerschlĂĽsselung
src/App.psm1 Erfassungslauf + Dashboard-Datenaggregation
public/ OnePage-Frontend (Vanilla JS + Chart.js, lokal gebĂĽndelt)

API

Route Zweck
GET /api/data Status + Historie + aktuelle Benutzerliste
GET/POST /api/settings Konfiguration lesen/schreiben (Secret nur schreibend)
POST /api/test Verbindungstest (Token-Abruf)
POST /api/collect Erfassung sofort ausfĂĽhren

Lizenz

MIT — frei nutzbar, auch kommerziell. Entwickelt mit Unterstützung von Claude (Anthropic) unter menschlicher Anleitung und Review; Details in der Commit-Historie.

UnterstĂĽtzung

Das Dashboard ist kostenlos und Open Source — von Nutzern für Nutzer. Wer das Projekt unterstützen möchte:

Buy Me a Coffee


M365 Storage Dashboard (English)

Single-page web app (PowerShell/Pode) that reads mailbox sizes, OneDrive usage and SharePoint site storage for an entire Microsoft 365 tenant via Microsoft Graph, stores the history in a SQLite database and presents it as a dashboard:

  • Tiles: total tenant storage (mail + OneDrive + SharePoint) with the three shares broken out, growth since the first snapshot, and user count broken down by license type (incl. shared mailboxes)
  • Chart: storage over time — mailboxes, OneDrive and SharePoint as separate lines, tooltip shows the total
  • User list: sortable (click a column header), full-text search, filters (quota > 80 %, top 10, shared mailboxes), license column, quota bars with warning thresholds (80 % / 95 %). Shared mailboxes are detected automatically (mailbox present, account disabled, no license) and shown separately
  • SharePoint tab: all sites with real display names, storage, type (team/communication), owner, file count, active files, page views and last activity; sites inactive for more than 90 days are flagged as archiving candidates; separate growth chart; search/sort/filter like the user list (deep link: #sharepoint)
  • Settings in the UI: tenant ID, client ID, client secret (stored encrypted via DPAPI on Windows), demo mode with generated sample data, UI language (German/English)
  • Automation: built-in weekly schedule (default: Monday 06:00) collects a new snapshot as long as the server is running

Screenshots (demo mode) are shown above.

Requirements

  • Windows server or PC (development also tested on macOS/Linux)
  • PowerShell 7 (winget install Microsoft.PowerShell)
  • Modules: Install-Module Pode, PSSQLite -Scope CurrentUser (on macOS/Linux the system sqlite3 CLI is used instead of PSSQLite)

App registration in the customer tenant (one-time)

Easiest way: start the server, then run the setup as a Global Administrator of the customer tenant:

pwsh ./start.ps1
pwsh ./setup.ps1

setup.ps1 does everything in one go: installs missing modules, creates (or reuses) the app registration with all four Graph permissions incl. admin consent and a client secret (24 months), disables report pseudonymization (-KeepConcealedNames skips this), hands tenant ID, client ID and secret to the running dashboard via its API (so the server encrypts the secret under its own account, which also works for a service running as SYSTEM), tests the connection and runs the first collection, retrying for up to 10 minutes while new permissions propagate. It is safe to re-run, e.g. when the secret expires.

The setup/ folder additionally contains a step-by-step guide (PDF, German) and the individual steps as separate scripts:

  • 01-register-app.ps1 — creates the app registration, service principal, all Graph permissions incl. admin consent and a client secret, then prints the three values the dashboard needs
  • 02-get-ids.ps1 — reads tenant ID / client ID of an existing registration, lists secret expiry dates and verifies all permissions; -Fix assigns any missing app roles directly (more reliable than the portal's consent button, which can silently revoke existing grants)
  • 03-report-settings.ps1 — checks report pseudonymization and disables it on request (-Force for non-interactive use)

Manual portal setup works too: register an app (single tenant), add the Graph application permissions below, grant admin consent, create a client secret.

Permission Purpose Required?
Reports.Read.All usage reports: mailbox, OneDrive and SharePoint storage yes
User.Read.All per-user license assignments, shared-mailbox detection recommended
Organization.Read.All license master data (SKU names) recommended
Sites.Read.All SharePoint site display names and URLs (the usage report no longer includes site URLs in many tenants) recommended

If the optional permissions are missing, storage collection still works — the dashboard shows a hint and leaves the affected columns empty.

Important — real names in reports: Microsoft pseudonymizes usage reports in many tenants by default (hashes instead of names and site URLs). Disable this once in the Microsoft 365 Admin Center under Settings → Org settings → Reports, or run 03-report-settings.ps1. The dashboard detects concealed reports and shows a warning.

Getting started

pwsh ./start.ps1

Dashboard: http://localhost:8080 (port configurable in settings.json). On first start, open ⚙︎ Settings, enter the three values, click Test connection, save, then Collect now. stop.ps1 stops the server. The demo mode checkbox generates 13 weeks of sample data — handy for a first look without any tenant access.

To run permanently on Windows, register a scheduled task at system startup (see the German section above for a ready-made Register-ScheduledTask call).

Docker (e.g. Synology NAS)

Prebuilt image for amd64 and arm64: ghcr.io/aussiech/m365-usage-dashboard. Adjust docker-compose.yml (password and key) and run docker compose up -d (Synology: Container Manager > Project > Create). In the container the server listens on the network and therefore always requires a login (DASHBOARD_PASSWORD). The client secret is stored AES-GCM encrypted with DASHBOARD_SECRET_KEY. Tenant ID, client ID and secret can also be set via M365_TENANT_ID, M365_CLIENT_ID, M365_CLIENT_SECRET. Data lives in the /data volume. Put HTTPS in front (e.g. Synology reverse proxy) before exposing it to the internet.

Data storage

  • data/usage.db — SQLite; one row per user and snapshot date (snapshots), one row per SharePoint site and snapshot date (site_snapshots), plus a meta table
  • Collections are idempotent (INSERT OR REPLACE) and serialized — collecting twice on the same day never creates duplicates
  • settings.json — configuration; the client secret is DPAPI-encrypted on Windows and is never returned by the API
  • Graph usage reports lag by roughly 24–48 h; the snapshot date is the report's "Report Refresh Date"

Architecture

File Purpose
server.ps1 Pode server: static UI, REST API, weekly schedule
src/Graph.psm1 token (client credentials), report fetching/merging, site names, demo data
src/Storage.psm1 SQLite access (PSSQLite or sqlite3 CLI)
src/Settings.psm1 settings load/save, secret encryption
src/App.psm1 collection run + dashboard data aggregation
public/ single-page frontend (vanilla JS + bundled Chart.js)

API

Route Purpose
GET /api/data status + history + current user and site lists
GET/POST /api/settings read/write configuration (secret is write-only)
POST /api/test connection test (token acquisition)
POST /api/collect run a collection immediately

License

MIT — free to use, including commercially. Developed with the assistance of Claude (Anthropic) under human direction and review; see the commit history for details.

Support

The dashboard is free and open source — built by users, for users. If it saves you a few francs in backup costs:

Buy Me a Coffee

About

No description, website, or topics provided.

Resources

Stars

20 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages