Wie Sie mit PowerShell und Node.js hunderte Microsoft Teams effizient und fehlerfrei managen - auch bei hohem Wachstum.
Wenn Ihr Unternehmen Microsoft 365 nutzt und regelmäßig neue Teams erstellt, kennen Sie das Problem: Die SharePoint-Speicherkapazität passt sich nicht automatisch an und muss manuell verwaltet werden.
Bei kleinen Organisationen geht das noch. Aber was, wenn Sie hunderte neuer Teams pro Woche erstellen? Das manuelle Anpassen der Speichergrößen über das SharePoint-Admincenter wird schnell zur zeitraubenden Aufgabe - und zur fehleranfälligen.
In diesem Beitrag zeigen wir, wie sich dieser Prozess sauber automatisieren lässt: Setup mit PowerShell 7 und PnP.PowerShell, ein Automatisierungs-Script mit Zertifikatsauthentifizierung, ein Node.js-Worker für kontinuierliche Überwachung - und ein Cronjob, der das Ganze in Bewegung hält.
Für wen ist dieser Artikel?
IT-Administratoren, SharePoint-Verantwortliche und alle, die ihre Microsoft 365-Umgebung effizienter verwalten möchten. Besonders relevant für Unternehmen mit vielen Teams oder hoher Nutzerfluktuation.
Was Sie lernen werden:
Stunden manueller Arbeit werden zu Minuten automatisierter Prozesse.
Reibungslose Handhabung von hunderten neuen Teams pro Woche.
Automatisierte Prozesse minimieren menschliche Fehler.
Protokollierung aller Änderungen für Audit-Zwecke.
Microsoft 365 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.
Bei tausenden Teams summieren sich diese Kosten schnell. Beispiel: 5 TB Mehrbedarf → ca. 1.000 € monatlich. Automatisierte Verwaltung ist deshalb eine klar wirtschaftliche Entscheidung: Aktiv genutzte Teams bekommen angemessenen Speicher, unnötige Kosten durch überdimensionierte Zuteilungen fallen weg.
Warum nicht die Microsoft Graph API?
Die Graph API bietet aktuell keine direkte Unterstützung für die Anpassung von SharePoint-Speicherkontingenten. Daher setzen wir auf ein PowerShell-Script mit PnP.PowerShell, das vollständig automatisiert läuft - getriggert durch einen Node.js-Worker, der die Graph API nur für die Team-Erkennung nutzt.
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.
PnP.PowerShell bietet moderne Authentifizierungsoptionen und ermöglicht Automatisierung ohne manuelle Eingabe von Zugangsdaten.
# Installation von PnP.PowerShell
pwsh
Install-Module -Name PnP.PowerShell -ForceUm das Script ausführen zu können, brauchen Sie eine Azure AD App mit folgenden Berechtigungen:
# 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"Das folgende Script setzt das Speicherkontingent und das Warnungslimit für eine spezifische SharePoint-Seite. 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 = "IHRE_TENANT"
$AdminCenterURL = "https://$Tenant-admin.sharepoint.com"
$SiteURL = "https://$Tenant.sharepoint.com/sites/$SiteName"
$ClientId = "IHRE_CLIENT_ID"
$TenantId = "IHRE_TENANT_ID"
$CertificatePath = "./IhrZertifikat.pfx"
$CertificatePassword = ConvertTo-SecureString -String "IHR_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 GreenSicherheitshinweis
In produktiven Umgebungen sollten Passwörter nicht im Klartext im Script stehen. Verwenden Sie Azure Key Vault, Environment-Variablen oder Managed Identities. Das Zertifikat selbst sollte mit eingeschränkten Dateirechten geschützt werden.
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 dient hier nur als Beispiel — ähnliche Worker-Implementierungen sind in Python, Go oder .NET genauso möglich.
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}`);
}
})();Tipps für die Implementierung
Für eine kontinuierliche Überwachung lässt sich der Worker über einen Cron-Job regelmäßig ausführen. So läuft der Prozess vollständig automatisiert.
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.
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.
Die Automatisierung der SharePoint-Speicherverwaltung ist ein perfektes Beispiel dafür, wie kleine technische Optimierungen große betriebliche Vorteile bringen. Der gezeigte Ansatz kombiniert PowerShell mit Node.js und ist damit:
Vor allem aber: Solche Routine-Tasks gehören aus der IT-Abteilung raus. Niemand sollte hunderte Mal pro Monat dasselbe Häkchen setzen.
Ob SharePoint, Azure, M365 oder Ihr ERP - wir automatisieren die wiederkehrenden Verwaltungsaufgaben, die Ihre IT-Abteilung blockieren.