Kubernetes-Bereitstellung
Diese Seite beschreibt die Bereitstellung von FoxPlan auf einem Kubernetes-Cluster mit seinem Helm-Chart. Die gesamte Konfiguration erfolgt über eine Values-Datei: Die Templates des Charts müssen nie geändert werden.
Für einen einzelnen Server ohne Cluster siehe Docker-Compose-Bereitstellung.
Herunterzuladende Dateien
- foxplan-1.0.0.tgz — das Helm-Chart
- values.yaml — alle Values, kommentiert
curl -O https://app.fox-plan.com/docs/onpremise/kubernetes/foxplan-1.0.0.tgz
curl -o foxplan-values.yaml https://app.fox-plan.com/docs/onpremise/kubernetes/values.yaml
Die FoxPlan-Images werden in einer frei zugänglichen Registry veröffentlicht: Es sind keine Zugangsdaten anzufordern und keine imagePullSecrets anzulegen. Ihre Adresse teilt Ihnen FoxPlan zusammen mit Ihrer Lizenz mit; sie wird im Value image.registry eingetragen.
Architektur
| Komponente | Kubernetes-Objekt | Rolle |
|---|---|---|
| Anwendung | Deployment foxplan-app | FoxPlan-Server (Port 5000), ein oder mehrere Replikas |
| Dokumentation | Deployment foxplan-docs | Diese Dokumentation, bereitgestellt unter /docs |
| Export der Planungen | Deployment foxplan-export | PDF, PNG, Excel, MS Project und Primavera, bereitgestellt unter /gantt-export |
| MongoDB | StatefulSet foxplan-mongodb | Datenbank, ein Knoten, persistentes Volume |
| Redis | StatefulSet foxplan-redis | Sitzungen und Cache, persistentes Volume. Immer bereitgestellt: FoxPlan startet nicht ohne Redis |
| Garage (optional) | StatefulSet foxplan-garage | S3-Dateispeicher, falls Sie keinen haben |
| Routing | Ingress foxplan | / → Anwendung, /docs → Dokumentation, /gantt-export → Export |
Die Namen erhalten den Namen des Helm-Releases als Präfix (foxplan in den Beispielen). Der Export-Pod enthält einen kleinen nginx-Proxy, der das Präfix /gantt-export entfernt: Das Routing funktioniert so mit jedem Ingress-Controller, ohne controllerspezifische Rewrite-Annotation.
Voraussetzungen
- Ein Cluster mit Kubernetes 1.27 oder neuer sowie Helm 3.
- Ein Ingress-Controller: Traefik, ingress-nginx, HAProxy, der Ihres Managed-Angebots…
- Eine Standard-Storage-Class (oder eine in den Values angegebene Klasse) für die Volumes von MongoDB, Redis und gegebenenfalls Garage.
- Mindestens ein amd64-Knoten: Die Export-Images werden nur f ür amd64 veröffentlicht. Die übrigen Images gibt es auch für arm64.
- Ein Domainname, der auf Ihren Ingress-Controller zeigt, und ein TLS-Zertifikat: ausgestellt von cert-manager oder von Ihnen in einem Secret bereitgestellt.
- Ein SMTP-Server: Registrierungscodes, Einladungen und Passwortzurücksetzungen hängen davon ab. Ohne ihn kann sich niemand anmelden.
- Nur für die automatische Skalierung: metrics-server.
Abruf der Images
Die Netzwerkflüsse sind die der Docker-Compose-Installation, beschrieben unter Schritt 1: Images herunterladen — Netzwerkflüsse: die FoxPlan-Registry und Docker Hub für die Images von Drittanbietern. Sie gehen von den Knoten des Clusters aus, wenn diese die Images herunterladen. Vom Chart verwendete Drittanbieter-Images:
| Image | Verwendet |
|---|---|
mongo:8.2.7 | Immer, außer bei externer MongoDB (mongodb.enabled: false) |
redis:7.4 | Immer |
nginxinc/nginx-unprivileged:1.28-alpine | Proxy des Export-Pods |
dxflrs/garage:v2.1.0, curlimages/curl:8.14.1 | Nur mit garage.enabled: true |
Rufen Sie die Images aus einer von Ihrem Informationssystem unabhängigen Umgebung ab, wie für Docker Compose beschrieben, und pushen Sie sie dann in Ihre interne Registry. Geben Sie diese anschließend in den Values an: image.registry für die FoxPlan-Images, mongodb.image, redis.image, export.proxy.image, garage.image und garage.initImage für die übrigen. Wenn diese Registry eine Authentifizierung verlangt, fügen Sie ihr Secret in imagePullSecrets hinzu. Die Knoten haben dann keinerlei Flüsse mehr ins Internet.
Ports und SSO
Enterprise-SSO erfordert keinen zusätzlichen Port, ob es sich um die Standard-Anmeldung mit Microsoft oder Google oder um ein benutzerdefiniertes SSO handelt. Die Rückkehr einer Anmeldung wird vom Browser des Benutzers an https://<host>/login/oauth2/code/… übermittelt, über den Ingress wie der Rest der Anwendung: Der Identitätsanbieter baut nie eine Verbindung zum Cluster auf.
| Richtung | Port | Zwischen | Zweck |
|---|---|---|---|
| Eingehend | 443 (TCP) | Arbeitsplätze der Benutzer → Ingress-Controller | Die Anwendung und die SSO-Rückkehr |
| Eingehend | 80 (TCP) | Arbeitsplätze der Benutzer → Ingress-Controller | Weiterleitung auf 443; HTTP-01-Challenge von cert-manager |
| Ausgehend | 443 (TCP) | Pods foxplan-app → Identitätsanbieter | Token-Austausch, Signaturschlüssel, Profil — Domains in der Netzwerkfluss-Matrix |
Stellen Sie den Port 5000 der Pods nicht bereit (NodePort, LoadBalancer): Der Ingress genügt. Filtern Ihre NetworkPolicy-Objekte ausgehenden Verkehr, erlauben Sie den Pods foxplan-app den Zugriff auf den Identitätsanbieter, auf 443 oder auf dessen eigenem Port — Keycloak auf 8443 zum Beispiel.
- Standard-SSO (Microsoft, Google): Variablen über
app.extraEnvundapp.extraSecretEnv. Die Weiterleitungs-URL wird aushostgebildet:https://<host>/login/oauth2/code/azureoder…/google, unverändert bei Microsoft Entra oder Google einzutragen. - Benutzerdefiniertes SSO (Okta, Keycloak, jeder OIDC-Anbieter, eingerichtet unter Unternehmens-SSO): Die Weiterleitungs-URL wird aus den vom Ingress-Controller gesetzten Headern
X-Forwarded-Proto,X-Forwarded-HostundX-Forwarded-Portrekonstruiert. Die Schaltfläche Konfiguration prüfen zeigt die genaue einzutragende URL.
Terminiert ein Load Balancer vor dem Ingress-Controller TLS, empfängt der Controller HTTP und gibt X-Forwarded-Proto: http weiter: FoxPlan berechnet dann eine http://-URL, die der Anbieter ablehnt (redirect_uri mismatch). Lassen Sie die Header des Load Balancers durchreichen — use-forwarded-headers: "true" in der ConfigMap von ingress-nginx, forwardedHeaders.trustedIPs am Einstiegspunkt von Traefik — oder betreiben Sie den Load Balancer im TCP-Modus, ohne Entschlüsselung. Der öffentliche Port muss 443 bleiben.
Dimensionierung
Standardmäßige Anforderungen (requests) und Obergrenzen (limits) des Charts:
| Komponente | Angeforderte CPU | Angeforderter Speicher | Speicherobergrenze | Volume |
|---|---|---|---|---|
| Anwendung (pro Replika) | 1 | 4 Gi | 6 Gi | — |
| MongoDB | 0,5 | 2 Gi | 4 Gi | 50 Gi |
| Redis | 0,1 | 256 Mi | 1 Gi | 5 Gi |
| Export (3 Container) | 0,36 | 656 Mi | 2,6 Gi | — |
| Dokumentation | 0,01 | 32 Mi | 256 Mi | — |
| Garage (optional) | 0,1 | 256 Mi | 1 Gi | 1 Gi + 100 Gi |
Richtwerte für die auf den Knoten verfügbare Kapazität:
| Benutzer | CPU | Arbeitsspeicher | Festplatte |
|---|---|---|---|
| Bis 100 | 4 vCPU | 16 GB | 100 GB |
| 100 bis 500 | 8 vCPU | 32 GB, mit 2 Replikas der Anwendung | 200 GB |
| Darüber | Automatische Skalierung der Anwendung, MongoDB als Replica Set |
Die JVM der Anwendung nutzt 75 % ihrer Speicherobergrenze (app.javaOptions): Um ihr mehr Speicher zu geben, erhöhen Sie app.resources.limits.memory, ohne weitere Einstellung.
Installation
1. Namespace und Zertifikat
kubectl create namespace foxplan
Mit cert-manager ist nichts anzulegen: Die Annotation des Issuers in den Values genügt (siehe nächster Schritt). Andernfalls legen Sie das TLS-Secret der Domain an, einschließlich der vollständigen Kette:
kubectl -n foxplan create secret tls foxplan-tls --cert=fullchain.pem --key=privkey.pem
2. Values
Gehen Sie von der heruntergeladenen values.yaml aus oder von einer Datei, die nur die Änderungen enthält. Das Minimum:
# foxplan-values.yaml
image:
registry: <von FoxPlan mitgeteilte Adresse>
tag: latest # in der Produktion die bereitgestellte Version festlegen
host: foxplan.mon-entreprise.fr
ingress:
className: traefik # oder nginx, haproxy… leer = Standardklasse des Clusters
annotations:
cert-manager.io/cluster-issuer: letsencrypt # wenn Sie cert-manager verwenden
app:
replicas: 1 # Anzahl der Anwendungsinstanzen — siehe „Anzahl der Instanzen“
mail:
from: foxplan@mon-entreprise.fr
host: smtp.mon-entreprise.fr
port: 587
username: foxplan@mon-entreprise.fr
password: <SMTP-Passwort>
Ohne image.registry, host, mail.from oder mail.host verweigert Helm die Installation mit einer Meldung, die den fehlenden Value nennt.
ingress-nginx begrenzt Uploads standardmäßig auf 1 MB, was Anhänge blockiert. Fügen Sie diese Annotationen hinzu:
ingress:
className: nginx
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
# Große Header in SSO-Antworten (SAML, OIDC)
nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
nginx.ingress.kubernetes.io/proxy-read-timeout: "120"
Traefik setzt keine Grenze: Es ist keine Annotation erforderlich.
3. Bereitstellung
helm upgrade --install foxplan foxplan-1.0.0.tgz -n foxplan -f foxplan-values.yaml
kubectl -n foxplan get pods -w
Beim ersten Start werden die Images heruntergeladen und die Datenbank initialisiert: Rechnen Sie mit einigen Minuten, bis der Pod foxplan-app bereit ist.
4. Erstes Konto anlegen
Öffnen Sie https://IHRE_DOMAIN: Solange keine Instanz existiert, öffnet sich eine Diagnoseseite (Bildschirm Ersteinrichtung) und zeigt Ihnen, ob alles korrekt funktioniert — siehe was geprüft wird. Wenn alles antwortet, klicken Sie auf Erste Instanz mit meinem Konto anlegen. Der Registrierungscode wird über Ihren SMTP-Server versendet; geben Sie ihn ein, folgen Sie dem Assistenten und wählen Sie dann Ihr Passwort.
Danach öffnet das Diagnosesymbol rechts neben der Sprachauswahl auf der Anmeldeseite diese Diagnose jederzeit erneut.
Wichtigste Values
| Value | Standard | Rolle |
|---|---|---|
image.registry | — | Adresse der FoxPlan-Registry. Pflicht |
image.tag | latest | Version der FoxPlan-Images |
image.pullPolicy | Always | Mit latest wird das Image bei jedem Pod-Start neu heruntergeladen |
host | — | Domainname. Pflicht |
ingress.className, ingress.annotations | — | Ingress-Controller und seine Einstellungen |
ingress.tls.secretName | foxplan-tls | TLS-Secret der Domain |
mail.* | — | SMTP-Server. Pflicht |
s3.* | leer | Ihr S3-Speicher — siehe Dateispeicher |
app.replicas | 1 | Replikas der Anwendung |
autoscaling.enabled | false | Automatische Skalierung nach CPU-Last |
app.extraEnv, app.extraSecretEnv | — | Zusätzliche Variablen: SSO Microsoft oder Google… |
mongodb.enabled, mongodb.externalUri | true | Integrierte MongoDB oder Ihre eigene |
export.amd64Only | true | Platziert den Export-Pod auf einem amd64-Knoten |
garage.enabled | false | Integrierter S3-Speicher |
secrets.* | generiert | JWT-Schlüssel und Passwörter — siehe Secrets |
Die heruntergeladene Datei values.yaml dokumentiert jeden Value.
Dateispeicher
Projektdokumente, Vertragsanhänge und Profilfotos werden in einem S3-kompatiblen Objektspeicher abgelegt. Dort bleiben sie privat: Die Anwendung liefert sie selbst aus, nach Prüfung der Berechtigungen.
Ihr vorhandener Speicher — Ceph, NetApp StorageGRID, Scality, MinIO, AWS… Legen Sie einen Bucket und für FoxPlan dedizierte Zugangsdaten an, dann:
s3:
url: https://s3.mon-entreprise.local # ohne den Bucket-Namen
bucket: foxplan
accessKey: <Zugriffskennung>
secretKey: <geheimer Schlüssel>
region: <vom Speicher erwartete Region>
Die Region geht in die Signatur jeder Anfrage ein: Weicht sie von der des Speichers ab, werden alle Anfragen abgelehnt und die Diagnose zeigt den Speicher als fehlerhaft an. Der Bucket wird im Pfad der URL adressiert: Es ist kein DNS pro Bucket erforderlich.
Garage, falls Sie keinen haben — garage.enabled: true stellt Garage bereit, einen in Frankreich entwickelten Open-Source-S3-Speicher. Ein Job legt bei der Installation den Bucket und den Zugriffsschlüssel von FoxPlan an; die Zugangsdaten werden generiert und im Secret abgelegt. Der Abschnitt s3 wird dann ignoriert. Garage läuft auf einem einzigen Knoten: Sichern Sie ihn (siehe Sicherung).
Ohne Speicher funktioniert die Anwendung; nur die Dateien sind nicht verfügbar. On Premise wird kein Kontingent angewendet.
Anzahl der Instanzen
Die Anzahl der Anwendungsinstanzen wird in Ihrer Wertedatei festgelegt, auf eine von zwei Arten.
Feste Anzahl — app.replicas:
app:
replicas: 3
Automatisch — je nach CPU-Last, zwischen einem Minimum und einem Maximum (erfordert metrics-server). app.replicas wird dann ignoriert:
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 6
targetCPUUtilizationPercentage: 70
Wenden Sie die Änderung mit helm upgrade an (vollständiger Befehl unter Versionsupdate) und prüfen Sie dann:
kubectl -n foxplan get pods -l app.kubernetes.io/component=app
kubectl -n foxplan get hpa # mit automatischer Skalierung
Legen Sie diese Anzahl immer in den Werten fest: Ein kubectl scale wird beim nächsten Update überschrieben. Jede Instanz fordert 1 vCPU und 4 Gi Arbeitsspeicher an (app.resources): Ihre Knoten müssen alle aufnehmen können, einschließlich des Skalierungsmaximums. Ab 2 Instanzen fügt das Chart ein PodDisruptionBudget hinzu, das während Arbeiten an den Knoten mindestens eine laufen lässt. Richtwert: 2 Instanzen für 100 bis 500 Benutzer, darüber automatische Skalierung.
Die Sitzungen liegen in Redis, und geplante Aufgaben setzen eine Sperre in Redis: Die Instanzen teilen sich die Benutzer ohne Sitzungsaffinität, und eine Aufgabe läuft nur einmal.
Hochverfügbarkeit
- Anwendung: 2 Instanzen oder mehr — siehe Anzahl der Instanzen.
- MongoDB: Die MongoDB des Charts ist ein einzelner Knoten. Für Hochverfügbarkeit verwenden Sie ein Replica Set (MongoDB-Operator, verwalteter Dienst) mit
mongodb.enabled: falseundmongodb.externalUri: mongodb://utilisateur:mot-de-passe@hote1,hote2,hote3/foxplanweb?replicaSet=rs0&authSource=admin. - Redis: immer vom Chart bereitgestellt, mit Persistenz auf Festplatte. Ein Ausfall von Redis meldet die Benutzer ab, ohne Datenverlust: Redis enthält nur die Sitzungen und den Cache.
Eingehende und ausgehende Zertifikate
FoxPlan verwendet zwei verschiedene Zertifikate, eines pro Verkehrsrichtung:
| Eingehende Flüsse | Ausgehende Flüsse | |
|---|---|---|
| Zweck | Den Browsern nachweisen, dass der Server wirklich host ist | Der Anwendung erlauben, Ihre internen Dienste zu erkennen: AD FS, SMTP mit TLS, S3… |
| Verwendet von | Dem Ingress-Controller | Den Pods foxplan-app (Java) |
| Inhalt | Das Zertifikat der FoxPlan-Domain und sein privater Schlüssel | Das öffentliche Zertifikat der Zertifizierungsstelle, die diese Dienste signiert hat — Stamm- und Zwischenzertifikate. Niemals ein privater Schlüssel |
| Ablageort | TLS-Secret foxplan-tls (ingress.tls.secretName) oder cert-manager | Wert app.outboundCaCerts oder eine bestehende ConfigMap, angegeben über app.outboundCaConfigMap |
| Format | PEM: --cert = Serverzertifikat, gefolgt von den Zwischenzertifikaten, --key = unverschlüsselter Schlüssel | PEM, Schlüsselnamen auf .crt. Eine Datei darf mehrere Zertifikate enthalten |
| Pflicht | Ja | Nur wenn ein aufgerufener Dienst von einer nicht öffentlichen Stelle signiert ist |
| Übernahme | Der Controller liest das Secret bei dessen Aktualisierung neu | Beim Start der Pods. helm upgrade startet sie neu; eine geänderte externe ConfigMap erfordert kubectl -n foxplan rollout restart deployment foxplan-app |
Es sind nicht dieselben Zertifikate, sie stammen aber oft aus derselben PKI: Das Zertifikat der Stammzertifizierungsstelle, die das von FoxPlan signiert hat, ist dann auch das für die ausgehenden Flüsse bereitzustellende.
Für die ausgehenden Flüsse:
# foxplan-values.yaml
app:
outboundCaCerts:
ca-interne.crt: |
-----BEGIN CERTIFICATE-----
MIIDFzCCAf+gAwIBAgIU...
-----END CERTIFICATE-----
oder, ohne die Datei in die Werte zu kopieren:
helm upgrade --install foxplan foxplan-1.0.0.tgz -n foxplan -f foxplan-values.yaml \
--set-file 'app.outboundCaCerts.ca-interne\.crt=ca-interne.crt'
Das Chart lehnt einen Namen ohne Endung .crt und einen Inhalt mit privatem Schlüssel ab; es behält nur die Blöcke BEGIN/END CERTIFICATE. Wie Sie feststellen, ob eine Stelle nötig ist, und wie Sie eine .cer-, .p7b- oder .pfx-Datei in PEM umwandeln, steht unter Docker Compose: Die Befehle sind dieselben.
Secrets
Bleiben sie in den Values leer, werden der JWT-Schlüssel und die Passwörter von MongoDB und Redis (sowie die Schlüssel von Garage) bei der ersten Installation generiert, im Secret foxplan-secrets abgelegt und bei jedem Update beibehalten. Dieses Secret übersteht auch helm uninstall.
SECRET_KEY_JWT verschlüsselt auch die in der Datenbank gespeicherten SSO-Konfigurationen. Wird eine Datenbank ohne diesen Schlüssel wiederhergestellt, sind diese Konfigurationen nicht mehr lesbar.
kubectl -n foxplan get secret foxplan-secrets -o yaml > foxplan-secrets.yaml
Um die Secrets selbst zu verwalten (Vault, External Secrets…), legen Sie ein Secret mit SECRET_KEY_JWT, MONGO_PASSWORD, REDIS_PASSWORD, MAIL_SMTP_PASSWORD, FILE_S3_ACCESS_KEY und FILE_S3_SECRET_KEY an (bei externer MongoDB zusätzlich URL_MONGO) und geben Sie es in secrets.existingSecret an. Die MongoDB-Passwörter müssen alphanumerisch bleiben: Sie gehen unverändert in die Verbindungs-URL ein.
Sicherung
Gemeinsam und zum selben Zeitpunkt zu sichern: die Datenbank, die Dateien und das Secret.
Datenbank — im laufenden Betrieb, aus dem MongoDB-Pod, der die Werkzeuge enthält:
kubectl -n foxplan exec foxplan-mongodb-0 -- sh -c \
'mongodump --username "$MONGO_INITDB_ROOT_USERNAME" \
--password "$MONGO_INITDB_ROOT_PASSWORD" \
--authenticationDatabase admin --archive --gzip' \
> foxplan-$(date +%F-%H%M).archive.gz
Zur Wiederherstellung derselbe Befehl mit mongorestore --drop und kubectl exec -i … < archive. Leeren Sie anschließend den Redis-Cache, sonst liefert die Anwendung veraltete Daten aus:
kubectl -n foxplan exec foxplan-redis-0 -- sh -c 'redis-cli -a "$REDIS_PASSWORD" --no-auth-warning FLUSHALL'
Dateien in Garage — im laufenden Betrieb, mit rclone von einem Administrationsrechner aus:
kubectl -n foxplan port-forward svc/foxplan-garage 3900:3900 &
KEY=$(kubectl -n foxplan get secret foxplan-secrets -o jsonpath='{.data.FILE_S3_ACCESS_KEY}' | base64 -d)
SECRET=$(kubectl -n foxplan get secret foxplan-secrets -o jsonpath='{.data.FILE_S3_SECRET_KEY}' | base64 -d)
rclone sync :s3:foxplan ./foxplan-files \
--s3-provider Other --s3-endpoint http://127.0.0.1:3900 --s3-region garage \
--s3-access-key-id "$KEY" --s3-secret-access-key "$SECRET"
Zur Wiederherstellung vertauschen Sie Quelle und Ziel. Bei Ihrem eigenen S3-Speicher wenden Sie dessen übliche Sicherungsrichtlinie an. Die Volume-Snapshots Ihrer Plattform (VolumeSnapshot) eignen sich ebenfalls, sofern MongoDB und Garage zum selben Zeitpunkt erfasst werden.
Versionsupdate
helm upgrade foxplan foxplan-1.0.0.tgz -n foxplan -f foxplan-values.yaml
- Festgelegte Version (
image.tag): Ändern Sie den Value und führen Sie den Befehl erneut aus. - Mit
latest: Der Befehl allein ändert nichts, wenn die Values identisch sind. Starten Sie die Pods neu, damit sie das Image erneut herunterladen:
kubectl -n foxplan rollout restart deployment
Die Bereitstellung der Anwendung erfolgt schrittweise: Ein neues Replika startet und wird bereit, bevor das alte stoppt.
Deinstallation
helm uninstall foxplan -n foxplan
Die Volumes (MongoDB, Redis, Garage) und das Secret werden beibehalten: Eine Neuinstallation findet die Daten wieder. Um alles zu löschen, entfernen Sie anschließend die PersistentVolumeClaim-Objekte und das Secret aus dem Namespace.
Fehlerbehebung
| Symptom | Wahrscheinliche Ursache |
|---|---|
helm verweigert: „image.registry est obligatoire“ | Pflicht-Value fehlt: image.registry, host, mail.from oder mail.host |
Pod foxplan-export im Status Pending | Kein amd64-Knoten: Fügen Sie einen hinzu, oder export.amd64Only: false, wenn Ihre ARM-Knoten amd64 emulieren |
Pod foxplan-app startet in einer Schleife neu | Logs: kubectl -n foxplan logs deploy/foxplan-app. Meist ist MongoDB oder Redis nicht erreichbar |
Anhang abgelehnt, Fehler 413 | Upload-Grenze des Ingress-Controllers: siehe Hinweis zu ingress-nginx |
| Speicher in der Diagnose fehlerhaft | Region s3.region weicht von der des Speichers ab, oder Speicher von den Pods aus nicht erreichbar |
| Kein Registrierungscode erhalten | SMTP: Die Diagnose der Anmeldeseite zeigt, ob er erreichbar ist |
latest wird nicht aktualisiert | kubectl -n foxplan rollout restart deployment: siehe Versionsupdate |
| SSO-Konfiguration nach Wiederherstellung nicht lesbar | Secret foxplan-secrets weicht von dem zum Zeitpunkt der Sicherung gültigen ab |
PKIX path building failed in den Protokollen von foxplan-app | Interne Zertifizierungsstelle von AD FS, SMTP oder S3 fehlt in app.outboundCaCerts: siehe Eingehende und ausgehende Zertifikate |