50 KiB
SessionGuard v0.3 – Installation und Konfiguration
Schritt-für-Schritt-Anleitung für den Betrieb von SessionGuard als RDS-Control-Plane zusammen mit Apache Guacamole 1.6, PocketID, Traefik, PostgreSQL und Windows Remote Desktop Session Hosts.
Diese Anleitung ist auf den aktuellen SessionGuard-v0.3-Arbeitsstand und die vorhandene Umgebung mit git.send.nrw, ts.hilden.info, guacauth.hilden.info und auth.hilden.info zugeschnitten. Alle Secrets sind Platzhalter und müssen durch eigene, zufällige Werte ersetzt werden.
1. Zielbild
Nach der Installation sieht die Umgebung logisch so aus:
Internet
|
v
Traefik
|
+----------------------+-----------------------+
| | |
v v v
Guacamole PocketID SessionGuard Master
+ SessionGuard | |
Extension | +---- PostgreSQL
| | |
+----------------------+ |
| |
| Broker API | Agent Heartbeats
v v
SessionGuard Master <---------------------- Windows RDS Agents
| |
| Brokerentscheidung +-- RDS01
| +-- RDS02
+----------------------------------------------+-- RDS03
Die Verantwortlichkeiten bleiben bewusst getrennt:
| Komponente | Aufgabe |
|---|---|
| PocketID | Benutzeridentität und OIDC-Gruppen |
| Traefik / traefik-forward-auth | TLS, Edge-Proxy und Guacamole-Header-Authentifizierung |
| Guacamole | HTML5/RDP-Gateway |
| SessionGuard Guacamole Extension | fragt beim Verbindungsaufbau den Broker nach dem Ziel-RDS-Host |
| SessionGuard Master | Broker, Director, Farms, Policies, RBAC, Alerts, Audit, Session-Historie |
| SessionGuard Agent | lokale RDS-/WTS-Steuerung, Profil-Pipeline, Templates und Telemetrie |
| PostgreSQL | persistenter SessionGuard-Control-Plane- und Director-State |
| Windows RDS | eigentliche Benutzer-Sitzungen |
Teil A – Voraussetzungen
2. Voraussetzungen prüfen
2.1 Docker-/Linux-Seite
Benötigt werden:
- Docker Engine
- Docker Compose v2
- bestehender Traefik v3
- Zugriff auf
git.send.nrw - DNS für Guacamole, PocketID und SessionGuard
- PostgreSQL 17 wird empfohlen
Vorhanden sind bereits:
Guacamole: https://ts.hilden.info
Forward Auth: https://guacauth.hilden.info
PocketID: https://auth.hilden.info
Für SessionGuard wird in dieser Anleitung beispielhaft verwendet:
SessionGuard: https://sessionguard.hilden.info
Dafür einen DNS-Eintrag auf denselben Traefik-Endpunkt erstellen.
2.2 Windows-Seite
Pro RDS-Host:
- Windows Server 2019/2022/2025 x64
- RDS Session Host installiert und funktionsfähig
- lokaler Administrator für die Installation
- Netzwerkzugriff zum SessionGuard Master
- bei Profil-Sicherung: Zugriff auf den gewünschten SMB-Store
- empfohlen: gMSA für den SessionGuard-Dienst, wenn auf SMB-Shares geschrieben werden soll
2.3 Build-Voraussetzungen
Falls der Windows-Agent lokal gebaut wird:
Go 1.23+
PowerShell 5.1+
Git
Für einen lokalen Build der Guacamole-Extension:
JDK 17
Maven 3.9+
Im normalen Gitea-CI/CD-Betrieb wird die Guacamole-Extension bereits im Docker-Build erstellt.
Teil B – Secrets und PocketID
3. SessionGuard-Secrets erzeugen
Für unterschiedliche Vertrauensbeziehungen unterschiedliche Secrets verwenden.
Beispiel unter Linux:
openssl rand -base64 48
openssl rand -base64 48
openssl rand -base64 48
openssl rand -base64 48
Benötigt werden mindestens:
SESSIONGUARD_DB_PASSWORD
SESSIONGUARD_ENROLLMENT_TOKEN
SESSIONGUARD_BROKER_API_KEY
SESSIONGUARD_OIDC_CLIENT_SECRET
Die Secrets dürfen nicht wiederverwendet werden.
Insbesondere sind diese Werte voneinander zu trennen:
PocketID OIDC Client Secret Browser -> SessionGuard
Broker API Key Guacamole Extension -> Master
Enrollment Token neuer Agent -> Master
Per-Agent Token Agent -> Master, wird automatisch erzeugt
PostgreSQL Password Master -> PostgreSQL
4. PocketID für den SessionGuard Master konfigurieren
In PocketID einen neuen vertraulichen OIDC-Client nur für SessionGuard anlegen.
Beispiel:
Name: SessionGuard Master
Client Type: Confidential
Redirect URI:
https://sessionguard.hilden.info/oidc/callback
Scopes:
openid profile email groups
Client-ID und Client-Secret notieren.
Das Client-Secret später ausschließlich über:
SESSIONGUARD_OIDC_CLIENT_SECRET
an den Master übergeben.
4.1 Empfohlene PocketID-Gruppen
Beispielsweise:
sessionguard-admins
sessionguard-helpdesk
sessionguard-operators
sessionguard-policy
sessionguard-profile
sessionguard-auditors
Empfohlene SessionGuard-Zuordnung:
| PocketID-Gruppe | SessionGuard-Rolle |
|---|---|
sessionguard-admins |
admin |
sessionguard-helpdesk |
helpdesk |
sessionguard-operators |
operator |
sessionguard-policy |
policy_admin |
sessionguard-profile |
profile_admin |
sessionguard-auditors |
auditor |
Für Produktion sollte rbac.groups nicht leer bleiben. Ein leeres Mapping vergibt aus Kompatibilitätsgründen weitreichendere Rechte als für einen finalen Produktionsbetrieb gewünscht.
5. PocketID für die lokalen Agent-WebUIs
Das lokale Agent-WebUI ist als Fallback vorgesehen, wenn der Master nicht erreichbar ist.
Pro Terminalserver kann ein eigener OIDC-Client verwendet werden, zum Beispiel:
https://rds01-mgmt.hilden.info/oidc/callback
https://rds02-mgmt.hilden.info/oidc/callback
Alternativ kann ein zentral verwalteter OIDC-Client mehrere explizit erlaubte Redirect-URIs enthalten, sofern dies in der eigenen PocketID-Konfiguration gewünscht ist.
Für das lokale Agent-UI nur Administratorgruppen freigeben, beispielsweise:
"admin_groups": [
"sessionguard-admins"
]
Das Agent-WebUI selbst lauscht standardmäßig auf Port 9091. Für einen produktiven OIDC-Login sollte davor HTTPS über einen Reverse Proxy verwendet werden.
Teil C – Docker-Netzwerke
6. Netzwerkstruktur härten
Die vorhandene Umgebung verwendet das externe Netzwerk:
aio_proxy
Das funktioniert technisch. Bei Guacamole Header Authentication ist aber wichtig, dass kein nicht vertrauenswürdiger Container Guacamole direkt erreichen und selbst einen X-Guacamole-User-Header senden kann.
Empfohlen sind daher getrennte Netze:
guacamole_proxy Traefik <-> Guacamole / ForwardAuth
guacamole_backend Guacamole <-> guacd / PostgreSQL
sessionguard_control Guacamole <-> SessionGuard Master
sessionguard_backend SessionGuard Master <-> SessionGuard PostgreSQL
6.1 Gemeinsames privates Control-Netz erstellen
Wenn Guacamole und SessionGuard in unterschiedlichen Compose-Projekten laufen:
docker network create --internal sessionguard_control
In beiden Compose-Dateien anschließend:
networks:
sessionguard_control:
external: true
name: sessionguard_control
Damit kann die Guacamole-Extension den Master intern erreichen, ohne dessen Broker-API über das Internet aufrufen zu müssen.
6.2 Optional: dediziertes Guacamole-Proxy-Netz
Besonders bei Header-Auth empfohlen:
docker network create guacamole_proxy
Traefik, traefik-forward-auth und guacamole werden an dieses Netzwerk angeschlossen. Andere Stacks sollten dort nicht Mitglied sein.
Wenn der bestehende aio_proxy von sehr vielen Containern gemeinsam verwendet wird, sollte die Umstellung auf ein dediziertes Netzwerk als Security-Hardening eingeplant werden.
Teil D – Gitea CI/CD
7. CI/CD-Dateien ins Repository übernehmen
Im SessionGuard-Repository sollten vorhanden sein:
.gitea/workflows/release.yml
deploy/guacamole/Dockerfile.guacamole
guacamole-extension/
Die Pipeline erzeugt bei Push auf main:
git.send.nrw/sendnrw/<repo>:<version>
git.send.nrw/sendnrw/<repo>:latest
git.send.nrw/sendnrw/<repo>-guacamole:<version>
git.send.nrw/sendnrw/<repo>-guacamole:latest
Zusätzlich wird veröffentlicht:
sessionguard-guacamole.jar
in der Gitea Generic Package Registry.
7.1 Gitea Secrets
Im Repository mindestens hinterlegen:
DOCKER_USERNAME
DOCKER_PASSWORD
Der verwendete Account benötigt Schreibrechte auf:
- Container Registry
- Generic Package Registry
Später empfiehlt sich eine Trennung in eigene Package-Credentials.
7.2 Release-Versionen
Die CI verwendet:
git describe --tags --always | sed 's/^v//'
Für einen sauberen Release:
git tag v0.5.0
git push origin v0.5.0
git push origin main
Ein Commit exakt auf Tag v0.5.0 erzeugt dann:
git.send.nrw/sendnrw/sessionguard:0.5.0
git.send.nrw/sendnrw/sessionguard-guacamole:0.5.0
latest wird ebenfalls aktualisiert.
7.3 Release prüfen
docker pull git.send.nrw/sendnrw/sessionguard:0.5.0
docker pull git.send.nrw/sendnrw/sessionguard-guacamole:0.5.0
Für Produktion möglichst einen festen Versions-Tag und nicht ausschließlich latest verwenden.
Teil E – SessionGuard Master
8. Verzeichnisstruktur anlegen
Auf dem Docker-Host beispielsweise:
mkdir -p /opt/sessionguard
cd /opt/sessionguard
Anlegen:
/opt/sessionguard/
├── docker-compose.yml
├── .env
└── master.json
9. .env für SessionGuard erstellen
Beispiel:
SESSIONGUARD_VERSION=0.5.0
POSTGRES_VERSION=17
TRAEFIK_NETWORK=aio_proxy
SESSIONGUARD_HOST=sessionguard.hilden.info
TRAEFIK_ENTRYPOINT=websecure
TRAEFIK_CERTRESOLVER=letsencrypt
SESSIONGUARD_DB_NAME=sessionguard
SESSIONGUARD_DB_USER=sessionguard
SESSIONGUARD_DB_PASSWORD=<SEHR_LANGES_DB_PASSWORT>
SESSIONGUARD_ENROLLMENT_TOKEN=<SEPARATES_ENROLLMENT_TOKEN>
SESSIONGUARD_BROKER_API_KEY=<SEPARATER_BROKER_API_KEY>
SESSIONGUARD_OIDC_CLIENT_SECRET=<POCKETID_SESSIONGUARD_CLIENT_SECRET>
# Optional
SESSIONGUARD_ALERT_WEBHOOK_URL=
Datei schützen:
chmod 600 .env
10. master.json erstellen
Beispiel für die vorhandene Domain:
{
"listen": ":8080",
"public_url": "https://sessionguard.hilden.info",
"data_file": "/var/lib/sessionguard/master.json",
"database_url": "",
"enrollment_token": "SET-BY-SESSIONGUARD_ENROLLMENT_TOKEN",
"offline_after_seconds": 30,
"history_limit": 50000,
"oidc": {
"issuer": "https://auth.hilden.info",
"client_id": "<POCKETID_SESSIONGUARD_CLIENT_ID>",
"client_secret": "SET-BY-SESSIONGUARD_OIDC_CLIENT_SECRET",
"redirect_url": "https://sessionguard.hilden.info/oidc/callback",
"admin_groups": [],
"secure_cookie": true
},
"rbac": {
"default_role": "viewer",
"groups": {
"sessionguard-admins": ["admin"],
"sessionguard-helpdesk": ["helpdesk"],
"sessionguard-operators": ["operator"],
"sessionguard-policy": ["policy_admin"],
"sessionguard-profile": ["profile_admin"],
"sessionguard-auditors": ["auditor"]
}
},
"broker": {
"enabled": true,
"api_key": "SET-BY-SESSIONGUARD_BROKER_API_KEY",
"lease_seconds": 900,
"min_health_score": 60,
"reconnect_existing": true,
"single_session_per_user": true,
"default_farm_id": ""
},
"alerts": {
"enabled": true,
"webhook_url": "",
"cpu_percent": 90,
"memory_percent": 90,
"disk_free_gb": 10,
"health_score": 50,
"offline_seconds": 120,
"profile_failures": 3,
"disconnected_sessions": 20,
"logon_duration_seconds": 30,
"notification_min_interval_seconds": 900
}
}
Die echten Secrets werden bewusst nicht in master.json geschrieben, sondern durch ENV-Variablen überschrieben.
11. SessionGuard Master Compose erstellen
Für die Registry-basierte Installation:
services:
sessionguard-postgres:
image: postgres:${POSTGRES_VERSION:-17}
restart: unless-stopped
environment:
POSTGRES_DB: ${SESSIONGUARD_DB_NAME:-sessionguard}
POSTGRES_USER: ${SESSIONGUARD_DB_USER:-sessionguard}
POSTGRES_PASSWORD: ${SESSIONGUARD_DB_PASSWORD:?required}
volumes:
- sessionguard-postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 20
networks:
- sessionguard_backend
sessionguard-master:
image: git.send.nrw/sendnrw/sessionguard:${SESSIONGUARD_VERSION:-latest}
restart: unless-stopped
depends_on:
sessionguard-postgres:
condition: service_healthy
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
environment:
SESSIONGUARD_DATABASE_URL: postgres://${SESSIONGUARD_DB_USER:-sessionguard}:${SESSIONGUARD_DB_PASSWORD}@sessionguard-postgres:5432/${SESSIONGUARD_DB_NAME:-sessionguard}?sslmode=disable
SESSIONGUARD_ENROLLMENT_TOKEN: ${SESSIONGUARD_ENROLLMENT_TOKEN}
SESSIONGUARD_BROKER_API_KEY: ${SESSIONGUARD_BROKER_API_KEY}
SESSIONGUARD_OIDC_CLIENT_SECRET: ${SESSIONGUARD_OIDC_CLIENT_SECRET}
SESSIONGUARD_ALERT_WEBHOOK_URL: ${SESSIONGUARD_ALERT_WEBHOOK_URL:-}
volumes:
- ./master.json:/etc/sessionguard/master.json:ro
tmpfs:
- /tmp:size=16m,mode=1777
networks:
- sessionguard_backend
- sessionguard_control
- proxy
labels:
- traefik.enable=true
- traefik.docker.network=${TRAEFIK_NETWORK}
- traefik.http.routers.sessionguard.rule=Host(`${SESSIONGUARD_HOST}`)
- traefik.http.routers.sessionguard.entrypoints=${TRAEFIK_ENTRYPOINT}
- traefik.http.routers.sessionguard.tls=true
- traefik.http.routers.sessionguard.tls.certresolver=${TRAEFIK_CERTRESOLVER}
- traefik.http.services.sessionguard.loadbalancer.server.port=8080
networks:
sessionguard_backend:
internal: true
sessionguard_control:
external: true
name: sessionguard_control
proxy:
external: true
name: ${TRAEFIK_NETWORK:-aio_proxy}
volumes:
sessionguard-postgres:
Wenn sessionguard_control noch nicht existiert:
docker network create --internal sessionguard_control
12. Master starten
cd /opt/sessionguard
docker compose pull
docker compose up -d
Status:
docker compose ps
Logs:
docker compose logs -f sessionguard-master
Health intern testen:
docker compose exec sessionguard-master \
wget -qO- http://127.0.0.1:8080/healthz
Extern testen:
https://sessionguard.hilden.info
Beim ersten Login sollte PocketID erscheinen.
13. RBAC prüfen
Mindestens zwei Tests durchführen:
- Benutzer in
sessionguard-adminsanmelden. - Benutzer ohne Admin-Gruppe bzw. mit Viewer-Gruppe anmelden.
Der zweite Benutzer darf keine administrativen Änderungen durchführen können.
Erst danach weitere Agents anbinden.
Teil F – Guacamole mit SessionGuard Extension
14. Wichtige Korrektur der vorhandenen PocketID-/ForwardAuth-Konfiguration
In der vorhandenen .env steht:
TFA_HOST=guacauth.hilden.info
Daher muss die PocketID Redirect URI für den traefik-forward-auth-Client dazu passen:
https://guacauth.hilden.info/portals/guacamole/oauth2/callback
Ein alter Kommentar mit guac-sso.hilden.info sollte entfernt werden, damit es später nicht zu Fehlkonfigurationen kommt.
Der SessionGuard Master benötigt einen eigenen OIDC-Client. ForwardAuth- und SessionGuard-Client-Secret dürfen nicht identisch sein.
15. Guacamole-Image austauschen
Im bestehenden Compose nur beim eigentlichen guacamole-Service das Image ändern.
Vorher:
image: guacamole/guacamole:${GUACAMOLE_VERSION:-1.6.0}
Nachher:
image: git.send.nrw/sendnrw/sessionguard-guacamole:${SESSIONGUARD_VERSION:-0.5.0}
guac-init kann weiterhin das offizielle Guacamole-Image verwenden.
16. SessionGuard-Variablen zu Guacamole ergänzen
Im guacamole.environment ergänzen:
SESSIONGUARD_MASTER_URL: http://sessionguard-master:8080
SESSIONGUARD_BROKER_API_KEY: ${SESSIONGUARD_BROKER_API_KEY}
SESSIONGUARD_BROKER_TIMEOUT_MS: "2500"
In die Guacamole .env zusätzlich:
SESSIONGUARD_VERSION=0.5.0
SESSIONGUARD_BROKER_API_KEY=<EXAKT_DERSELBE_BROKER_API_KEY_WIE_AM_MASTER>
Der Broker API Key ist kein Benutzer-Secret, sondern ein Service-to-Service-Key zwischen Guacamole-Extension und SessionGuard Master.
17. Guacamole an sessionguard_control anschließen
Beim guacamole-Service:
networks:
- aio_proxy
- sessionguard_control
Am Ende der Compose-Datei:
networks:
aio_proxy:
external: true
sessionguard_control:
external: true
name: sessionguard_control
Danach kann Guacamole den Master per Docker DNS erreichen:
http://sessionguard-master:8080
Wenn Master und Guacamole in unterschiedlichen Compose-Projekten laufen, funktioniert der DNS-Name nur dann zuverlässig, wenn beide Container im gleichen externen Docker-Netz hängen und dort der Name/Alias verfügbar ist. Falls der tatsächliche Containername anders lautet, einen expliziten Alias setzen oder den tatsächlichen DNS-Namen in SESSIONGUARD_MASTER_URL verwenden.
18. Guacamole neu starten
docker compose pull guacamole
docker compose up -d guacamole
Logs prüfen:
docker compose logs -f guacamole
Die SessionGuard-Extension muss beim Guacamole-Start ohne API-/Classloader-Fehler geladen werden.
19. Header-Auth absichern
Die vorhandene Konfiguration entfernt vor ForwardAuth bereits eingehende Identitätsheader:
- traefik.http.middlewares.guac-strip-auth.headers.customrequestheaders.X-Guacamole-User=
- traefik.http.middlewares.guac-strip-auth.headers.customrequestheaders.X-Forwarded-User=
- traefik.http.middlewares.guac-strip-auth.headers.customrequestheaders.X-Authenticated-User=
und verwendet anschließend:
- traefik.http.routers.guacamole.middlewares=guac-strip-auth,guac-pocketid
Das ist richtig gedacht.
Zusätzlich sicherstellen:
- Guacamole-Port
8080nicht direkt veröffentlichen. - Guacamole nicht aus beliebigen Container-Netzen erreichbar machen.
aio_proxymöglichst nicht als allgemeines Netz für unzusammenhängende Stacks verwenden.guacdund Guacamole-PostgreSQL nur in einem internen Backend-Netz betreiben.
Ein direkter Request eines fremden Containers an Guacamole darf nicht durch einen selbst gesetzten X-Guacamole-User authentifiziert werden können.
Teil G – Windows Agent
20. Windows-Agent bauen
Der aktuelle CI-Workflow baut die Container-Images und die Guacamole-JAR, veröffentlicht aber noch nicht automatisch den Windows-Agent als Release-Artefakt.
Bis dahin Agent auf einem Buildsystem erzeugen:
git clone <SESSIONGUARD_REPOSITORY>
cd sessionguard
go mod tidy
go test ./...
go vet ./...
.\scripts\build.ps1
Ergebnis:
.\bin\sessionguard-agent.exe
und zusätzlich:
.\bin\sessionguard-master-linux-amd64
Vor Produktion sollte genau der Commit gebaut werden, aus dem auch Master und Guacamole-Image erzeugt wurden.
21. Agent-Konfiguration erstellen
Pro Server eine agent.json erstellen.
Beispiel für RDS01:
{
"listen": ":9091",
"public_url": "https://rds01-mgmt.hilden.info",
"data_dir": "C:\\ProgramData\\SessionGuard",
"master_url": "https://sessionguard.hilden.info",
"enrollment_token": "SET-BY-SESSIONGUARD_ENROLLMENT_TOKEN",
"heartbeat_seconds": 10,
"oidc": {
"issuer": "https://auth.hilden.info",
"client_id": "<POCKETID_AGENT_CLIENT_ID>",
"client_secret": "SET-BY-SESSIONGUARD_OIDC_CLIENT_SECRET",
"redirect_url": "https://rds01-mgmt.hilden.info/oidc/callback",
"admin_groups": [
"sessionguard-admins"
],
"secure_cookie": true
},
"policy": {
"cleanup": {
"enabled": true,
"grace_seconds": 600,
"poll_seconds": 10,
"retry_seconds": 60,
"dry_run": true,
"exclude_users": [
"Administrator",
"DefaultAccount",
"WDAGUtilityAccount"
],
"exclude_sids": [
"S-1-5-18",
"S-1-5-19",
"S-1-5-20"
],
"allowed_profile_roots": [
"C:\\Users"
]
},
"profiles": {
"enabled": true,
"store_root": "\\\\fileserver\\SessionGuardProfiles",
"backup_on_logoff": true,
"restore_on_logon": false,
"backup_delay_seconds": 5,
"retry_seconds": 60,
"restore_window_seconds": 120,
"keep_versions": 2,
"exclude_users": [
"Administrator"
],
"exclude_sids": [
"S-1-5-18",
"S-1-5-19",
"S-1-5-20"
],
"folders": [
{
"path": "AppData\\Roaming\\Example",
"exclude_globs": [
"Cache/**",
"*.tmp"
]
},
{
"path": "Desktop"
},
{
"path": "Documents"
}
]
},
"sessions": {
"control_enabled": true,
"disconnected_logoff_enabled": false,
"disconnected_timeout_seconds": 3600,
"exclude_users": [
"Administrator"
],
"exclude_sids": [
"S-1-5-18",
"S-1-5-19",
"S-1-5-20"
]
},
"templates": []
}
}
Warum für die erste Installation restore_on_logon=false?
Der sichere Rollout ist:
- Backup testen.
- Restore manuell mit Testbenutzer validieren.
- Erst danach automatischen Restore aktivieren.
- Cleanup zunächst im Dry-Run lassen.
So existiert immer eine lokale Rückfallmöglichkeit.
22. Secrets des Agenten über Environment setzen
Empfohlen ist, sensible Werte nicht im JSON zu hinterlegen.
Der Agent unterstützt insbesondere:
SESSIONGUARD_MASTER_URL
SESSIONGUARD_ENROLLMENT_TOKEN
SESSIONGUARD_OIDC_CLIENT_SECRET
Bei einem Windows-Dienst müssen diese Werte so gesetzt werden, dass sie im Dienstkontext verfügbar sind. Alternativ kann die initiale Konfigurationsdatei mit strikten ACLs geschützt werden.
Der Installer schützt standardmäßig:
C:\ProgramData\SessionGuard
für SYSTEM und lokale Administratoren.
23. gMSA für Profil-Shares vorbereiten
Empfohlenes Dienstkonto beispielsweise:
DOMAIN\svc-sessionguard$
Das gMSA benötigt auf dem Profil-Share die erforderlichen Share- und NTFS-Rechte.
Mindestens erforderlich für Backup/Restore:
- Lesen
- Ordner anlegen
- Dateien schreiben
- Dateien ersetzen/umbenennen
- alte Versionen entsprechend Retention löschen
Keine SMB-Passwörter in agent.json speichern.
Wenn LocalSystem verwendet wird, greift der Server gegenüber SMB typischerweise über sein Computerkonto zu, beispielsweise:
DOMAIN\RDS01$
Dann müssten entsprechend die Computerkonten auf dem Share berechtigt werden.
24. Agent installieren
Elevated PowerShell:
.\scripts\install-agent.ps1 `
-Binary .\bin\sessionguard-agent.exe `
-Config .\configs\agent.json
Mit gMSA:
.\scripts\install-agent.ps1 `
-Binary .\bin\sessionguard-agent.exe `
-Config .\configs\agent.json `
-GmsaAccount "DOMAIN\svc-sessionguard$"
Der Installer:
- kopiert die Binary nach
C:\Program Files\SessionGuard - legt den State unter
C:\ProgramData\SessionGuardab - installiert den Windows-Dienst
SessionGuardAgent - aktiviert Delayed Auto Start
- konfiguriert automatische Service-Recovery
- startet den Dienst
25. Agent prüfen
Get-Service SessionGuardAgent
Erwartet:
Status: Running
Falls erforderlich Windows Event Log bzw. Dienst-Logs prüfen.
Anschließend Master öffnen:
https://sessionguard.hilden.info
Der Server sollte nach Enrollment/Heartbeat in der Serverliste erscheinen.
Ein Agent, der nach offline_after_seconds keinen Heartbeat gesendet hat, wird im Director als offline dargestellt.
26. Lokales Agent-WebUI veröffentlichen
Das Agent-WebUI lauscht standardmäßig:
http://RDS01:9091
Produktiv nicht direkt öffentlich ins Internet stellen.
Empfohlen:
Management-Netz / Reverse Proxy / TLS
|
v
http://RDS01:9091
Windows Firewall beispielsweise nur für die Reverse-Proxy-IP öffnen:
New-NetFirewallRule `
-DisplayName "SessionGuard Agent UI" `
-Direction Inbound `
-Action Allow `
-Protocol TCP `
-LocalPort 9091 `
-RemoteAddress <REVERSE_PROXY_IP>
Teil H – Farms, Tags und Broker
27. Erste Farm anlegen
Im Master-WebUI unter:
Farms & Broker
Beispiel:
Name: Office
ID: wird erzeugt bzw. im UI angezeigt
Optional Required Tags:
role=office
environment=production
Farm aktivieren.
28. Agents taggen und einer Farm zuordnen
Server im Master auswählen.
Unter Serversteuerung beispielsweise:
Maintenance Mode: Online
Tags:
role=office
environment=production
location=hilden
Optional Farm-ID explizit hinterlegen.
Die explizite Zuordnung hat gegenüber automatisch aus Tags ermittelten Farm-Zuordnungen eine höhere Policy-Relevanz.
29. Server-Modi verstehen
Online
Neue Sitzungen: erlaubt
Reconnect: erlaubt
Drain
Neue Sitzungen: nicht auf diesem Host
Reconnect bestehend: erlaubt
Verwenden vor Updates/Wartung.
Maintenance
Neue Sitzungen: blockiert
Reconnect: blockiert
Bestehende Windows-Sitzungen werden durch das Umschalten allein nicht automatisch beendet.
Restart when drained
Aktivieren:
Neu starten sobald leer
Dann:
- Host auf Drain.
- Keine neuen Sessions mehr.
- Bestehende Sessions laufen aus.
- Bei 0 Benutzersitzungen wird ein Restart-Kommando erzeugt.
- Nach Neustart Agent-Health prüfen.
- Host wieder auf
onlinesetzen.
30. Broker-Grundeinstellungen
In master.json:
"broker": {
"enabled": true,
"api_key": "SET-BY-SESSIONGUARD_BROKER_API_KEY",
"lease_seconds": 900,
"min_health_score": 60,
"reconnect_existing": true,
"single_session_per_user": true,
"default_farm_id": ""
}
Empfohlen für das vorhandene Profilmodell:
reconnect_existing = true
single_session_per_user = true
Damit versucht SessionGuard zuerst, einen Benutzer auf seine vorhandene aktive/getrennte Sitzung zurückzuführen.
Das reduziert gleichzeitige Profilzustände desselben Benutzers auf mehreren Hosts.
Teil I – Guacamole Published Resources
31. Brokered Desktop in Guacamole anlegen
In Guacamole eine normale RDP-Verbindung anlegen.
Beispielname:
Office Desktop
Beim RDP Hostname keinen festen RDS-Host eintragen, sondern:
${SESSIONGUARD_HOST}
RDP-Port bleibt normalerweise:
3389
Die bisherige RDP-Credential-Konfiguration bleibt unverändert. SessionGuard entscheidet über den Zielhost, ersetzt aber nicht automatisch die Windows-Anmeldeinformationen.
32. Passende Resource in SessionGuard anlegen
Im Master-WebUI unter:
Published Resources
Beispiel:
Name: Office Desktop
Typ: desktop
Farm: Office
Guacamole Connection Name: Office Desktop
Enabled: ja
Wenn möglich langfristig die Guacamole Connection-ID verwenden, da sie gegenüber Umbenennungen stabiler ist. Connection-Namen müssen eindeutig bleiben.
SessionGuard priorisiert beim Matching:
Resource-ID
-> Guacamole Connection-ID
-> Guacamole Connection-Name
Doppelte aktive Zuordnungen werden abgelehnt.
33. RemoteApp veröffentlichen
Guacamole-Verbindung:
hostname: ${SESSIONGUARD_HOST}
remote-app: ${SESSIONGUARD_REMOTE_APP}
remote-app-dir: ${SESSIONGUARD_REMOTE_APP_DIR}
remote-app-args: ${SESSIONGUARD_REMOTE_APP_ARGS}
SessionGuard Resource zum Beispiel:
Name: Sage
Typ: remoteapp
Farm: ERP
Remote App: ||Sage
Remote App Dir: C:\Program Files\Sage
Remote App Args: <optional>
Die RemoteApp muss auf allen Hosts der betreffenden Farm konsistent bereitgestellt sein.
34. Broker-Funktion testen
Test 1 – neue Sitzung
- Zwei RDS-Hosts auf
online. - Beide in derselben Farm.
- Beide Health Score >=
min_health_score. - Testbenutzer verbindet sich über die brokered Guacamole-Verbindung.
- Im Master prüfen, welcher Host ausgewählt wurde.
- Broker-Lease prüfen.
Test 2 – Reconnect
- Benutzer trennt die RDS-Sitzung.
- Benutzer öffnet dieselbe Guacamole Resource erneut.
- SessionGuard muss denselben RDS-Host zurückgeben.
Test 3 – Drain
- RDS01 auf
drainsetzen. - Neuer Benutzer darf nicht neu auf RDS01 platziert werden.
- Benutzer mit vorhandener Sitzung auf RDS01 darf dort reconnecten.
Test 4 – Maintenance
- RDS01 auf
maintenancesetzen. - Keine neuen Broker-Verbindungen nach RDS01.
- Auch vorhandener Reconnect darf nicht dorthin gebrokert werden.
Teil J – Profil-Pipeline
35. Profil-Store vorbereiten
Beispiel:
\\fileserver\SessionGuardProfiles
SessionGuard synchronisiert bewusst nur ausgewählte Profil-Unterordner.
Geeignete Beispiele:
Desktop
Documents
AppData\Roaming\Hersteller\Produkt
Nicht konfigurieren:
NTUSER.DAT
UsrClass.dat
komplettes C:\Users\<user>
Registry-Hives
EFS-Schlüsselmaterial
Windows-interne Profilstrukturen
36. Profilordner konfigurieren
Im Policy-Editor des Master-WebUIs:
Profil-Sicherung & Wiederherstellung
Beispiel:
Store Root: \\fileserver\SessionGuardProfiles
Backup nach Logoff: ja
Restore bei Logon: zunächst nein
Backup-Verzögerung: 5 Sekunden
Retry: 60 Sekunden
Restore-Fenster: 120 Sekunden
Historische Versionen: 2
Profilordner beispielsweise:
Desktop
Documents
AppData\Roaming\Example
Exclude-Globs für einen Ordner:
Cache/**
*.tmp
37. Backup zuerst ohne Cleanup-Risiko testen
Zunächst:
Backup: aktiviert
Restore: deaktiviert
Cleanup: aktiviert
Cleanup Dry-Run: aktiviert
Auto-Logoff: deaktiviert
Testablauf:
- Testbenutzer anmelden.
- Testdatei in einen synchronisierten Ordner schreiben.
- Benutzer sauber abmelden.
- Master öffnen.
- Aktivitäts-/Profiljob-Log prüfen.
- SMB-Store prüfen.
- Sicherstellen, dass ein
current-Snapshot vorhanden ist. - Dry-Run-Eintrag für geplanten Cleanup prüfen.
Wichtig:
Schlägt das Backup fehl, darf SessionGuard das lokale Profil nicht löschen.
38. Restore aktivieren
Erst nach erfolgreichem Backup-Test:
Restore bei Logon = aktiviert
Test:
- Testbenutzer abmelden.
- Gesicherte Datei lokal gezielt verändern/entfernen, ohne den Backup-Store zu verändern.
- Benutzer erneut anmelden.
- Prüfen, dass der letzte
current-Snapshot innerhalb des Restore-Fensters eingespielt wurde. - Master-Aktivitätslog prüfen.
Der Restore arbeitet als Merge und nicht als vollständiger Profil-Mirror.
39. Cleanup produktiv aktivieren
Erst wenn Backup und Restore mehrfach erfolgreich getestet wurden:
Cleanup Dry-Run = aus
Empfohlener Startwert:
Grace: 600 Sekunden
Pipeline:
Logoff
|
+-- Backup Delay
|
+-- Backup nach staging
|
+-- Benutzer erneut aktiv? -> Abbruch
|
+-- staging -> current
|
+-- Cleanup Grace
|
+-- finaler WTS-Recheck
|
+-- DeleteProfileW
Ein Reconnect blockiert gefährliche Operationen.
Teil K – Disconnect Auto-Logoff
40. Getrennte Sitzungen zunächst beobachten
Im Director prüfen:
- welche Anwendungen häufig getrennt bleiben
- typische Disconnect-Dauer
- ob bestimmte Service-/Admin-Benutzer ausgeschlossen werden müssen
Dann Timeout definieren, zum Beispiel:
3600 Sekunden = 1 Stunde
41. Auto-Logoff aktivieren
Policy:
Sitzungssteuerung erlauben: ja
Getrennte Sitzungen automatisch abmelden: ja
Disconnect Timeout: 3600
Wichtig:
Der automatische Logoff verwendet dieselbe Nachbearbeitung wie ein manueller Logoff:
Disconnected
|
Timeout erreicht
|
WTSLogoffSession
|
Profil-Backup
|
Cleanup Grace
|
Profil-Cleanup
Damit wird ein Benutzerprofil nicht einfach gelöscht, bevor die Sicherung abgeschlossen wurde.
Teil L – Templates
42. Templates konfigurieren
Im Policy-Editor können folgende Typen angelegt werden:
Datei
Ordner
URL-Verknüpfung
Windows .lnk
URL-Beispiel
ID: support-url
Typ: URL
Ziel: Desktop\Support.url
URL: https://support.example.org
Overwrite: ja
Datei von SMB
ID: settings-file
Typ: Datei
Ziel: AppData\Roaming\Example\defaults.json
Quelle: \\fileserver\sessionguard-templates\defaults.json
Overwrite: ja
Windows Shortcut
ID: company-shortcut
Typ: Shortcut
Ziel: Desktop\Fachanwendung.lnk
Target: C:\Program Files\Example\app.exe
Description: Fachanwendung
Overwrite: ja
Templates werden geprüft und nur bei Bedarf erzeugt/aktualisiert.
Teil M – Director und Session-Steuerung
43. Director prüfen
Der Master zeigt pro Server unter anderem:
Online/Offline
Maintenance Mode
Health Score
CPU
RAM
Systemdisk
RDP Listener
Profile Store
aktive Sitzungen
getrennte Sitzungen
Profiljobs
Cleanupjobs
Prozesse
Pro Session:
Session-ID
Benutzer
Status
Logon-Zeit
Idle-Zeit
Clientname
Clientadresse
44. Sitzung steuern
Je nach RBAC-Rolle sind verfügbar:
Nachricht senden
Trennen
Abmelden
Prozess beenden
Prozessbeendigung wird zusätzlich gegen PID-Wiederverwendung abgesichert, indem der Agent PID und Session-ID vor TerminateProcess erneut verifiziert.
Administrative Aktionen werden im Audit-Log protokolliert.
Teil N – Policies und Rollback
45. Policy-Ebenen
Die Policy-Priorität lautet:
Agent Override
> explizite Farm-Zuordnung
> zentral/tagbasiert ermittelte Farm
> globale Policy
Empfehlung:
- globale Baseline für alle RDS-Hosts
- Farm-Policy für Office/ERP/etc.
- Agent-Override nur für begründete Ausnahmen
46. Policy-Änderungen ausrollen
Für Änderungen zunächst einen Canary-Host verwenden.
Beispiel:
- Policy nur auf RDS03 anwenden.
- mindestens mehrere echte Logons/Logoffs beobachten.
- Director, Profiljobs und Alerts prüfen.
- danach auf Farm oder alle Server ausrollen.
Das WebUI bietet:
Für diesen Server speichern
Auf alle anwenden
Editor neu laden
47. Policy-Rollback
Unter:
Policy-Historie & Rollback
alte Revision auswählen und:
Rollback
verwenden.
Der Rollback löscht die Historie nicht, sondern erzeugt eine neue aktuelle Revision auf Basis der gewählten älteren Version.
Teil O – Alerts und Monitoring
48. Alert-Grenzwerte konfigurieren
Beispiel:
"alerts": {
"enabled": true,
"cpu_percent": 90,
"memory_percent": 90,
"disk_free_gb": 10,
"health_score": 50,
"offline_seconds": 120,
"profile_failures": 3,
"disconnected_sessions": 20,
"logon_duration_seconds": 30,
"notification_min_interval_seconds": 900
}
Damit werden unter anderem überwacht:
Agent offline
CPU hoch
RAM hoch
Disk knapp
Health Score zu niedrig
Profilfehler
zu viele getrennte Sessions
langsame beobachtete Logons
49. Webhook konfigurieren
Optional:
SESSIONGUARD_ALERT_WEBHOOK_URL=https://example.org/sessionguard-webhook
SessionGuard sendet JSON-Webhooks.
Die Webhook-Zustellung ist Best Effort und ersetzt kein unabhängiges Infrastrukturmonitoring.
50. Prometheus-Metriken
Der Master stellt bereit:
/metrics
und Health:
/healthz
Beide Endpunkte in das bestehende Monitoring integrieren.
Teil P – PostgreSQL und Backup
51. PostgreSQL sichern
SessionGuard speichert dort unter anderem:
Agents
Farms
Resources
Broker-Leases
Policy-State
Policy-Historie
Audit
Session-Historie
Alerts
Regelmäßiges Backup beispielsweise mit pg_dump:
docker compose exec -T sessionguard-postgres \
pg_dump -U sessionguard -d sessionguard -Fc \
> sessionguard-$(date +%F).dump
Das Profil-Share wird nicht in PostgreSQL gespeichert und muss separat gesichert werden.
52. Master-HA beachten
v0.3 ist als Single-Active-Master ausgelegt.
Der Master hält einen PostgreSQL Advisory Lock. Ein zweiter aktiver Master gegen dieselbe DB soll dadurch nicht gleichzeitig als Control Plane arbeiten.
Für manuellen Failover:
- alten Master stoppen bzw. dessen Ausfall sicher feststellen
- PostgreSQL-Verfügbarkeit prüfen
- Ersatz-Master gegen dieselbe DB starten
/healthzprüfen- Agent-Heartbeats prüfen
- Broker-Test durchführen
Kein Active/Active-Deployment konfigurieren.
Teil Q – Produktions-Rollout
53. Empfohlene Rollout-Reihenfolge
Phase 1 – Infrastruktur
- SessionGuard PostgreSQL bereitstellen
- SessionGuard Master bereitstellen
- HTTPS/Traefik konfigurieren
- PocketID OIDC testen
- RBAC testen
- PostgreSQL-Backup testen
Phase 2 – erster Agent
- einen Canary-RDS-Host wählen
- Agent installieren
- Heartbeat prüfen
- Director-Telemetrie prüfen
- Cleanup Dry-Run aktiv lassen
- Auto-Logoff deaktiviert lassen
Phase 3 – Guacamole Broker
- SessionGuard-Guacamole-Image deployen
- Extension-Startup prüfen
- Canary-Farm erstellen
- eine Published Resource erstellen
${SESSIONGUARD_HOST}in Guacamole verwenden- neue Sitzung testen
- Reconnect testen
Phase 4 – zweite RDS-Node
- zweiten Agent hinzufügen
- gleiche Farm
- Broker-Verteilung testen
- Drain testen
- Maintenance testen
- Restart when drained testen
Phase 5 – Profile
- Profil-Backup aktivieren
- Backup mehrfach testen
- SMB-Ausfall simulieren
- sicherstellen, dass Cleanup bei Backupfehler blockiert bleibt
- Restore aktivieren
- Restore mehrfach testen
- Reconnect während Backup testen
- erst danach Cleanup Dry-Run deaktivieren
Phase 6 – Session Lifecycle
- Disconnect-Dauer beobachten
- sinnvollen Timeout festlegen
- Ausschlussbenutzer festlegen
- Auto-Logoff aktivieren
- Backup-Pipeline nach Auto-Logoff prüfen
Phase 7 – breite Einführung
- weitere Farms anlegen
- weitere RDS-Hosts aufnehmen
- Policies zentralisieren
- Alerts anbinden
- Monitoring anbinden
- Betriebsdokumentation/Notfallzugang dokumentieren
Teil R – Funktionstests vor Produktivfreigabe
54. Mindest-Testmatrix
Broker
- neue Verbindung wird auf gesunden Online-Host gelegt
- Benutzer reconnectet auf seinen vorhandenen Host
- Drain blockiert neue Sessions
- Drain erlaubt Reconnect
- Maintenance blockiert Brokerzugriff
- Farm-Isolation funktioniert
- Lease-Race bei zwei fast gleichzeitigen Verbindungsversuchen funktioniert
Session Control
- Nachricht
- Disconnect
- Logoff
- getrennte Sessions gesammelt abmelden
- Prozess beenden
- Audit-Eintrag vorhanden
Profile
- normaler Backup-Job
- Restore
- Snapshot-History
- SMB-Ausfall
- Reconnect während Backup
- Reconnect unmittelbar vor Cleanup
- Cleanup Dry-Run
- echter Cleanup erst nach erfolgreichem Backup
Director
- Logon erscheint
- Disconnect erscheint
- Reconnect erscheint
- Logoff erscheint
- Prozesse sichtbar
- CPU/RAM/Disk sichtbar
- Agent Offline Alert funktioniert
Security
- Viewer kann nicht administrieren
- Helpdesk-Rechte sind begrenzt
- Operator kann Maintenance/Sessions steuern
- Policy Admin kann Policy ändern/rollbacken
- fremder Container kann Guacamole nicht per gefälschtem
X-Guacamole-Userumgehen
Teil S – Updates
55. Master aktualisieren
Vorher PostgreSQL sichern.
Dann neuen Tag setzen, beispielsweise:
SESSIONGUARD_VERSION=0.5.0
Update:
docker compose pull sessionguard-master
docker compose up -d sessionguard-master
Prüfen:
docker compose logs --tail=200 sessionguard-master
und:
/healthz
OIDC Login
Dashboard
Agent Heartbeats
Broker
56. Guacamole Extension aktualisieren
Gleichen SessionGuard-Release-Tag verwenden:
SESSIONGUARD_VERSION=0.5.0
Dann:
docker compose pull guacamole
docker compose up -d guacamole
Guacamole-Logs unmittelbar prüfen.
Master und Guacamole-Extension sollten möglichst aus demselben SessionGuard-Release stammen.
57. Windows Agents aktualisieren
Pro Farm in Wellen:
- Host auf
drainsetzen. - Sitzungen auslaufen lassen.
- optional
restart_when_drainedverwenden. - neuen Agent-Build kopieren/installieren.
- State unter
C:\ProgramData\SessionGuarderhalten. - Dienst prüfen.
- Heartbeat/Health im Master prüfen.
- Host wieder
onlinesetzen. - nächster Host.
Installer erneut ausführen:
.\scripts\install-agent.ps1 `
-Binary .\bin\sessionguard-agent.exe `
-Config .\configs\agent.json `
-GmsaAccount "DOMAIN\svc-sessionguard$"
Teil T – Troubleshooting
58. Agent erscheint nicht im Master
Prüfen:
Master URL korrekt?
DNS vom RDS-Host?
HTTPS-Zertifikat vertrauenswürdig?
Enrollment Token identisch?
Firewall/Proxy?
SessionGuardAgent läuft?
PowerShell:
Get-Service SessionGuardAgent
Test-NetConnection sessionguard.hilden.info -Port 443
Master-Logs:
docker compose logs -f sessionguard-master
59. Guacamole meldet Brokerfehler
Prüfen:
SessionGuard Master erreichbar?
SESSIONGUARD_BROKER_API_KEY identisch?
Guacamole und Master im sessionguard_control Netzwerk?
Farm aktiviert?
Resource aktiviert?
Resource korrekt mit Guacamole Connection gemappt?
mindestens ein gesunder Online-Host in Farm?
Netzwerk prüfen:
docker network inspect sessionguard_control
Guacamole-Logs:
docker compose logs -f guacamole
60. Broker findet keinen Server
Prüfen:
Farm enabled?
Agent online?
Agent in Farm?
Required Tags erfüllt?
Maintenance Mode = online?
Health Score >= min_health_score?
Resource zeigt auf richtige Farm?
Ein Host auf drain ist nur für Reconnects geeignet, nicht für neue Benutzer.
Ein Host auf maintenance wird auch für Reconnect nicht verwendet.
61. Profil-Backup schlägt fehl
Prüfen:
- Dienstkonto des Agenten
- Share-Rechte
- NTFS-Rechte
- DNS zum Fileserver
- SMB-Erreichbarkeit
- freier Speicher
- gesperrte Dateien
- Pfad in
store_root
Mit gMSA besonders wichtig: Tests müssen im Kontext des Dienstkontos betrachtet werden, nicht nur mit dem eigenen Admin-Account.
Bei Backupfehler darf der Cleanup nicht fortgesetzt werden.
62. Restore wird nicht ausgeführt
Prüfen:
restore_on_logon=true?
current Snapshot vorhanden?
SMB erreichbar?
Benutzer/SID ausgeschlossen?
Restore-Fenster überschritten?
Agent während Logon aktiv?
Ein Restore, der das konfigurierte Restore-Fenster überschritten hat, wird bewusst nicht verspätet in eine bereits laufende Sitzung injiziert.
63. OIDC Redirect-Fehler
Die Redirect URI muss Zeichen für Zeichen zum PocketID-Client passen.
Master:
https://sessionguard.hilden.info/oidc/callback
ForwardAuth entsprechend der vorhandenen ENV:
https://guacauth.hilden.info/portals/guacamole/oauth2/callback
Agent beispielsweise:
https://rds01-mgmt.hilden.info/oidc/callback
Außerdem public_url, redirect_url, DNS und TLS prüfen.
64. PostgreSQL startet nicht
docker compose logs sessionguard-postgres
Prüfen:
SESSIONGUARD_DB_PASSWORD gesetzt?
Volume beschreibbar?
Disk voll?
PostgreSQL-Volume aus inkompatibler Major-Version?
PostgreSQL Major Upgrades nicht durch simples Austauschen von 17 auf eine spätere Major-Version durchführen; dafür das normale PostgreSQL-Upgradeverfahren verwenden.
Teil U – Empfohlene Produktionswerte
65. Startwerte
Diese Werte sind ein sinnvoller Ausgangspunkt, müssen aber zur eigenen Umgebung passen:
| Einstellung | Startwert |
|---|---|
| Agent Heartbeat | 10 s |
| Agent offline nach | 30 s |
| Broker Lease | 900 s |
| Broker min. Health | 60 |
| Profil Backup Delay | 5 s |
| Profil Retry | 60 s |
| Restore Window | 120 s |
| Snapshot History | 2 |
| Cleanup Grace | 600 s |
| Cleanup Poll | 10 s |
| Cleanup Retry | 60 s |
| Disconnect Auto-Logoff | zunächst aus |
| Disconnect Timeout | später z. B. 3600 s |
| CPU Alert | 90 % |
| RAM Alert | 90 % |
| Disk Alert | < 10 GB |
| Alert Repeat Minimum | 900 s |
Teil V – Go-Live-Checkliste
66. Go-Live
Vor dem breiten Rollout müssen alle Punkte erfüllt sein:
- SessionGuard Master nur per HTTPS administrierbar
- getrennte Secrets für DB/OIDC/Broker/Enrollment
- RBAC-Gruppen eingerichtet
- PostgreSQL-Backup erfolgreich getestet
- SessionGuard Master Restore-Verfahren dokumentiert
- Guacamole Header-Auth kann nicht direkt aus fremden Netzen umgangen werden
- Guacamole Extension lädt fehlerfrei
- Brokered Desktop funktioniert
- Reconnect Affinity funktioniert
- Drain funktioniert
- Maintenance funktioniert
- mindestens zwei RDS-Hosts in einer Canary-Farm getestet
- Agent-Dienst Recovery getestet
- Profil-Backup mehrfach erfolgreich
- Profil-Restore mehrfach erfolgreich
- SMB-Ausfall getestet
- Reconnect während Profil-Backup getestet
- Cleanup Dry-Run überprüft
- echter Profil-Cleanup nur nach erfolgreichem Backup aktiviert
- Auto-Logoff separat getestet
- Audit-Log geprüft
- Alerts geprüft
/healthzüberwacht/metricsüberwacht- Break-Glass-RDP-Zugang dokumentiert
- Upgrade- und Rollback-Verfahren dokumentiert
67. Empfohlene Reihenfolge für diese konkrete Umgebung
Für die vorhandene Guacamole/PocketID-Installation würde ich genau so vorgehen:
1. sessionguard.hilden.info in DNS anlegen
2. separaten PocketID OIDC Client für SessionGuard erstellen
3. RBAC-Gruppen in PocketID erstellen/zuweisen
4. sessionguard_control Docker-Netz erstellen
5. SessionGuard PostgreSQL + Master deployen
6. OIDC/RBAC im Master prüfen
7. einen RDS-Canary auswählen
8. Agent dort installieren
9. Director/Health prüfen
10. Office-Canary-Farm erstellen
11. Guacamole auf sessionguard-guacamole:<version> umstellen
12. Guacamole mit sessionguard_control verbinden
13. eine neue Guacamole-Testconnection mit ${SESSIONGUARD_HOST} erstellen
14. passende Published Resource in SessionGuard erstellen
15. Broker-Verbindung testen
16. Disconnect/Reconnect testen
17. zweiten Canary-RDS-Host hinzufügen
18. Load Placement testen
19. Drain/Maintenance testen
20. Profil-Backup testen
21. Restore testen
22. Cleanup Dry-Run beobachten
23. Cleanup aktivieren
24. Disconnect Auto-Logoff aktivieren
25. danach schrittweise die restlichen RDS-Hosts aufnehmen
Damit wird nicht gleichzeitig Gateway, Broker, Profilmanagement und Session-Lifecycle produktiv umgestellt. Jede Schicht kann einzeln validiert und bei Problemen zurückgenommen werden.
68. Wichtige Betriebsgrenzen
SessionGuard ersetzt in diesem Stand nicht:
- ICA/HDX
- den Windows RDS Session Host
- einen vollständigen Windows Profile Provider wie FSLogix/UPM
- Active/Active-Master-HA
- die eigentliche RDP-Credential-Authentifizierung
SessionGuard übernimmt stattdessen gezielt:
Broker
Reconnect Affinity
Farms
Drain / Maintenance
Director
Session Control
Profile Folder Lifecycle
Templates
Policies
RBAC
Audit
Alerts
Guacamole bleibt das Gateway und Windows bleibt die Session Runtime.
69. Relevante Projektdateien
Im Repository:
README.md
configs/master.example.json
configs/agent.example.json
deploy/docker-compose.yml
deploy/.env.example
deploy/guacamole/Dockerfile.guacamole
deploy/guacamole/docker-compose.sessionguard.example.yml
deploy/guacamole/CI-CD.md
scripts/build.ps1
scripts/install-agent.ps1
docs/ARCHITECTURE.md
docs/BROKER.md
docs/DIRECTOR.md
docs/GUACAMOLE.md
docs/OPERATIONS.md
docs/PROFILE-LIFECYCLE.md
docs/RBAC.md
docs/SECURITY.md
docs/TESTING.md
Diese Anleitung sollte zusammen mit docs/TESTING.md als Go-Live-Grundlage verwendet werden.
SessionGuard-managed RemoteApps (v0.4)
This mode is intended for RD Session Hosts where you want SessionGuard Agents to maintain the local RemoteApp allow-list instead of manually publishing the same alias on every farm member. It uses the documented Terminal Services WMI provider in root\CIMv2\TerminalServices. Administrator rights are required for changes; the normal SessionGuard Windows service account must therefore retain its existing local system/administrative privileges.
Before enabling it for a production farm, verify the provider on a canary RDS host:
Get-WmiObject `
-Namespace 'root\cimv2\TerminalServices' `
-Class Win32_TSPublishedApplication `
-Authentication PacketPrivacy |
Select-Object Alias,Path,PathExists,CommandLineSetting
An empty result is valid when no RemoteApps are published. A class/provider error means this SessionGuard mode should not be enabled on that host until the Windows RDS installation is corrected.
In Master → Apps & Desktops, create/edit a Resource:
Type: RemoteApp
Farm: <target farm>
RemoteApp Alias: ||Sage
Agent-managed publication: enabled
Executable: C:\Program Files\Sage\Sage.exe
Command-line policy: deny / allow / require
The executable must exist at the configured path on each eligible farm member. The Agent reconciles on desired-state changes and periodically thereafter. The Master UI shows per-host readiness. A managed RemoteApp remains unavailable on any host that has not yet reported a healthy synchronized registration.
SessionGuard only removes aliases that the same Agent originally created and recorded as owned. Existing manually published RemoteApps are discovered and can be adopted for desired-state checks, but are not deleted when management is later disabled. Canary-test this behavior on the exact Windows Server version used in your environment.
Because v0.4 changes the heartbeat protocol to version 4, upgrade Master and Agents as one coordinated rollout. A v0.3 Agent will be rejected by a v0.4 Master with a protocol-version mismatch until upgraded.