1. Das Problem: Speicher, der nicht mitwächst
Wenn dein Unternehmen Microsoft 365 nutzt und regelmäßig neue Teams erstellt, kennst du das: Die SharePoint-Speicherkapazität passt sich nicht automatisch an und muss manuell verwaltet werden.
Bei kleinen Organisationen geht das noch. Aber was, wenn hunderte neuer Teams pro Woche entstehen? Dann wird das Anpassen der Speichergrößen über das SharePoint-Admincenter schnell zur zeitraubenden - und fehleranfälligen - Aufgabe.
Wir bauen einen automatisierten Prozess: Setup mit PowerShell 7 und PnP.PowerShell, ein Automatisierungs-Script mit Zertifikatsauthentifizierung, ein Node.js-Worker für die kontinuierliche Überwachung - und ein Cronjob, der das Ganze in Bewegung hält.
Für wen ist das?
IT-Administratoren, SharePoint-Verantwortliche und alle, die ihre Microsoft-365-Umgebung effizienter verwalten wollen. Besonders relevant bei vielen Teams oder hoher Nutzerfluktuation.
Was du mitnimmst
- Warum manuelle SharePoint-Speicherverwaltung bei Skalierung kippt
- Setup von PowerShell 7 und PnP.PowerShell für moderne Authentifizierung
- Ein Automatisierungs-Script mit Zertifikat statt Passwort
- Integration in einen Node.js-Worker für kontinuierliche Überwachung
2. Warum sich das lohnt
Bevor wir eine Zeile Code schreiben, der wirtschaftliche Hebel, denn der macht aus einem Nice-to-have eine klare Entscheidung.
Zeitersparnis
Stunden manueller Arbeit werden zu Minuten automatisierter Prozesse.
Skalierbarkeit
Hunderte neue Teams pro Woche, ohne manuellen Eingriff.
Fehlerreduktion
Automatisierte Prozesse minimieren menschliche Fehler.
Transparenz
Protokollierung aller Änderungen für Audit-Zwecke.
Was die Speicherkosten treibt
SharePoint Online bringt 1 TB Basisspeicher pro Organisation plus 10 GB pro lizenziertem Benutzer (bis 25 TB pro Site). Reicht das nicht: ca. 0,20 €/GB pro Monat für zusätzlichen Speicher. Microsoft 365 Archive (für selten genutzte Daten) kostet ca. 0,05 €/GB pro Monat.
5 TB Mehrbedarf ≈ 1.000 € pro Monat.
Bei tausenden Teams summiert sich das schnell. Automatisierte Verwaltung heißt: aktiv genutzte Teams bekommen angemessenen Speicher, überdimensionierte Zuteilungen fallen weg. Der Hebel ist real, nicht kosmetisch.
3. Die Architektur in einem Satz
Ein Node.js-Worker erkennt über die Microsoft Graph API neue Teams, gleicht sie gegen die Datenbank ab und triggert pro Team ein PowerShell-Script, das das Speicherkontingent setzt. Klingt nach Umweg über PowerShell - ist aber Absicht:
4. Voraussetzungen
1. PowerShell 7
PowerShell 7 ist erforderlich, um die benötigten Module zu nutzen.
# Installation unter Ubuntu
wget -q https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install -y powershellWeitere Installationsanleitungen in der offiziellen PowerShell-Dokumentation.
2. PnP.PowerShell
PnP.PowerShell bietet moderne Authentifizierungsoptionen und ermöglicht Automatisierung ohne manuelle Eingabe von Zugangsdaten.
# Installation von PnP.PowerShell
pwsh
Install-Module -Name PnP.PowerShell -Force3. Azure AD App und Zertifikat
Damit das Script laufen kann, brauchst du eine Azure AD App mit:
- Sites.FullControl.All (Anwendungsberechtigungen in SharePoint)
- einem X.509-Zertifikat (selbstsigniert oder von einer Zertifizierungsstelle)
# Selbstsigniertes Zertifikat erstellen (Windows)
$cert = New-SelfSignedCertificate -Subject "CN=MeineAzureADApp" \
-KeySpec Signature -KeyLength 2048 \
-KeyExportPolicy Exportable \
-HashAlgorithm SHA256 \
-CertStoreLocation "Cert:\CurrentUser\My"
# Export des Zertifikats
Export-PfxCertificate -Cert $cert \
-FilePath "C:\Pfad\Zu\meinerAzureADApp.pfx" \
-Password (ConvertTo-SecureString -String "MeinPasswort" -Force -AsPlainText)
Export-Certificate -Cert $cert -FilePath "C:\Pfad\Zu\meinerAzureADApp.cer"5. Schritt 1: Das Speicher-Script
Das folgende Script setzt Speicherkontingent und Warnungslimit für eine spezifische SharePoint-Seite. Die Authentifizierung läuft über das eben erstellte Zertifikat - kein Passwort im Klartext, kein interaktiver Login.
Param(
[Parameter(Mandatory=$true)]
[string]$SiteName,
[Parameter(Mandatory=$true)]
[int]$NewStorageGB,
[Parameter(Mandatory=$true)]
[int]$NewStorageWarningGB
)
Import-Module PnP.PowerShell
$Tenant = "DEIN_TENANT"
$AdminCenterURL = "https://$Tenant-admin.sharepoint.com"
$SiteURL = "https://$Tenant.sharepoint.com/sites/$SiteName"
$ClientId = "DEINE_CLIENT_ID"
$TenantId = "DEINE_TENANT_ID"
$CertificatePath = "./DeinZertifikat.pfx"
$CertificatePassword = ConvertTo-SecureString -String "DEIN_PASSWORT" -Force -AsPlainText
Connect-PnPOnline -Url $AdminCenterURL `
-ClientId $ClientId -Tenant $TenantId `
-CertificatePath $CertificatePath `
-CertificatePassword $CertificatePassword
$NewStorageMB = $NewStorageGB * 1024
$NewStorageWarningMB = $NewStorageWarningGB * 1024
Set-PnPSite -Identity $SiteURL `
-StorageMaximumLevel $NewStorageMB `
-StorageWarningLevel $NewStorageWarningMB
Disconnect-PnPOnline
Write-Host "Speicherkontingent fuer '$SiteName' angepasst." -ForegroundColor Green6. Schritt 2: Der Node.js-Worker
Der Worker ruft Teams über die Microsoft Graph API ab, prüft den Status in der Datenbank und führt das PowerShell-Script bei Bedarf aus. Node.js ist hier nur ein Beispiel - dieselbe Logik funktioniert in Python, Go oder .NET genauso.
const { exec } = require("child_process");
const fetch = require("node-fetch");
// Beispiel: Teams ohne Speicheranpassung aus der Datenbank holen
const database = {
getTeamsWithoutStorageQuota: async () => [
{ teamName: "TeamA", teamId: "12345" },
],
};
const getSiteNameByTeamId = async (teamId) => {
const token = "YOUR_ACCESS_TOKEN";
const response = await fetch(
`https://graph.microsoft.com/v1.0/groups/${teamId}/sites/root`,
{ headers: { Authorization: `Bearer ${token}` } }
);
if (!response.ok) throw new Error(`Fehler: ${response.statusText}`);
const data = await response.json();
return data.name;
};
const setStorageQuota = (siteName, storageGB, warningGB) => {
const command = `pwsh ./setStorageQuota.ps1 -SiteName "${siteName}" ` +
`-NewStorageGB ${storageGB} -NewStorageWarningGB ${warningGB}`;
exec(command, (error, stdout, stderr) => {
if (error) return console.error(`Fehler: ${error.message}`);
if (stderr) return console.error(`stderr: ${stderr}`);
console.log(`stdout: ${stdout}`);
});
};
(async () => {
try {
const teams = await database.getTeamsWithoutStorageQuota();
for (const team of teams) {
const siteName = await getSiteNameByTeamId(team.teamId);
setStorageQuota(siteName, 100, 90);
}
} catch (error) {
console.error(`Fehler im Worker: ${error.message}`);
}
})();7. Schritt 3: Dauerbetrieb per Cron
Für die kontinuierliche Überwachung lässt du den Worker per Cron regelmäßig laufen. So läuft der Prozess vollständig automatisiert, ohne dass jemand daran denken muss.
0 0 * * * cd /pfad/zum/projekt && npm run start-worker >> /pfad/zum/logfile.log 2>&1Der Eintrag führt den Worker täglich um Mitternacht aus und protokolliert die Ausgabe in eine Logdatei.
8. Vom Problem zur Lösung
Ein Kunde mit tausenden aktiven Teams: standardmäßige Speicherlimits führten immer wieder zu vollen Sites und Arbeitsunterbrechungen. 30-50 neue Teams pro Woche, die manuelle Verwaltung war eine enorme Belastung für die IT. Der direkte Vergleich:
Vorher
Nachher
Solche Routine-Tasks gehören aus der IT-Abteilung raus. Niemand sollte hunderte Mal pro Monat dasselbe Häkchen setzen.
9. Ehrliche Einordnung: Wo die Grenzen sind
Der gezeigte Ansatz ist bewusst schlank, ein Fundament, das du an einem Tag stehen hast. Bevor er unternehmensweit läuft, fehlen aber die Dinge, die im Betrieb den Unterschied machen:
Solides Fundament
Für einen abgegrenzten Tenant und ein Team, das die Scripts kennt, ist dieses Setup eine belastbare Basis. Es läuft, es ist nachvollziehbar, es spart sofort Zeit.
Für den Produktivbetrieb fehlt
- Monitoring & Alerting bei Fehlern
- Secret-Management (Key Vault statt Klartext)
- Error-Recovery & Retry-Logik
- Wartung bei API- & Modul-Updates
Diese Lücke schließen wir. Wir bauen solche Automatisierungen für den Mittelstand produktionsreif: mit Monitoring, sauberem Secret-Management, durchdachter Fehlerbehandlung und laufender Wartung - damit die Routine aus deiner IT-Abteilung verschwindet und nicht zum nächsten Wartungsfall wird.