-
Notifications
You must be signed in to change notification settings - Fork 27
Multiple opencloud replicas not working with keycloak and opencloud.replicas description misleading #53
Description
Hello,
I discovered Opencloud a few days ago and have started exploring the application — it looks great so far, well done!
I'm planning to set up a high-availability (HA) Opencloud deployment on Kubernetes and found this Helm chart — which looks very solid overall, great work! However, I’m a bit confused by the description of the opencloud.replicas value. It states that persistence can be disabled when deploying more than one replica.
In my tests, if I disable persistence, I can indeed run multiple replicas — but when I delete a pod, the files are no longer visible in the Opencloud UI, even though they are still present in S3. So at the moment, the only reliable way would be to use RWS volumes for the data and config directory. I tested that and were able to have two replicas, but after that I can´t login to opencloud anymore and get the message Access denied.
It seems that opencloud can´t handle the sessions for already logged in users with keycloak. Do I something wrong or is this still a bug?
HA Opencloud Setup with Keycloak
global:
domain:
keycloak: keycloak.mydomain.de
opencloud: opencloud.mydomain.de
wopi: wopiserver.mydomain.de
collabora: collabora.mydomain.de
onlyoffice: onlyoffice.mydomain.de
companion: companion.mydomain.de
keycloak:
enabled: false
internal:
enabled: false
external:
# Enable external Keycloak
enabled: true
# External Keycloak URL
url: "https://keycloak.mydomain.de"
# External Keycloak realm
realm: "master"
# External Keycloak client ID
clientId: "web"
postgres:
enabled: false
opencloud:
enabled: true
replicas: 2
logLevel: "warn"
persistence:
enabled: true
# Size of the persistent volume for data
size: 5Gi
# Size of the persistent volume for config
configSize: 3Gi
# Access mode (ReadWriteOnce or ReadWriteMany for multiple replicas)
accessMode: ReadWriteMany
storage:
s3:
internal:
enabled: false
persistence:
enabled: false
external:
enabled: true
endpoint: "https://minio-api.mydomain.de"
region: "us-east-1"
accessKey: "opencloud"
secretKey: "my-super-secret-key"
bucket: "opencloud"
createBucket: false
env:
- name: OC_OIDC_ISSUER
value: https://keycloak.mydomain.de/realms/master
- name: "WEB_OIDC_METADATA_URL"
value: "https://keycloak.mydomain.de/realms/master/.well-known/openid-configuration"
- name: "WEB_OIDC_CLIENT_ID"
value: "web"
- name: "PROXY_OIDC_REWRITE_WELLKNOWN"
value: "true"
- name: "PROXY_USER_OIDC_CLAIM"
value: "preferred_username"
- name: "PROXY_USER_CS3_CLAIM"
value: "username"
- name: "GRAPH_ASSIGN_DEFAULT_USER_ROLE"
value: "false"
- name: "GRAPH_USERNAME_MATCH"
value: "none"
- name: "PROXY_AUTOPROVISION_ACCOUNTS"
value: "true"
- name: GRAPH_LDAP_SERVER_WRITE_ENABLED
value: "true"
- name: "PROXY_ROLE_ASSIGNMENT_DRIVER"
value: "oidc"
- name: "PROXY_ROLE_ASSIGNMENT_OIDC_CLAIM"
value: "roles"
- name: "PROXY_OIDC_ACCESS_TOKEN_VERIFY_METHOD"
value: "none"
- name: OC_ADMIN_USER_ID
value: ""
Here are some pod logs:
kubectl logs opencloud-opencloud-55c4cd5bd9-qm7t9 -f ─╯
Defaulted container "opencloud" out of: opencloud, init-config (init), init-drawio (init), init-externalsites (init), init-importer (init), init-jsonviewer (init), init-progressbars (init), init-unzip (init), init-web-extensions (init)
2025/05/28 18:58:31 Could not create config: config file already exists, use --force-overwrite to overwrite or --diff to show diff
{"level":"warn","service":"nats","time":"2025-05-28T18:58:31Z","message":"Filestore [KV_eventhistory] Stream state outdated, last block has additional entries, will rebuild"}
{"level":"warn","service":"nats","time":"2025-05-28T18:58:31Z","message":"Filestore [KV_eventhistory] Recovering stream state from index errored: prior state file"}
{"level":"warn","service":"nats","time":"2025-05-28T18:58:31Z","message":"Filestore [main-queue] Stream state outdated, last block has additional entries, will rebuild"}
{"level":"warn","service":"nats","time":"2025-05-28T18:58:31Z","message":"Filestore [main-queue] Recovering stream state from index errored: prior state file"}
{"level":"warn","service":"proxy","time":"2025-05-28T18:58:33Z","message":"basic auth enabled, use only for testing or development"}
{"level":"warn","service":"storage-system","pkg":"rhttp","time":"2025-05-28T18:58:33Z","message":"missing or incomplete nats configuration. Events will not be published."}
{"level":"warn","service":"ocm","pkg":"rhttp","time":"2025-05-28T18:58:33Z","message":"missing or incomplete nats configuration. Events will not be published."}
{"level":"warn","service":"ocm","pkg":"rhttp","traceid":"d444aed34a96e64732666d570f72aa61","time":"2025-05-28T18:58:33Z","message":"core access token not set"}
{"level":"warn","service":"ocm","pkg":"rhttp","traceid":"d444aed34a96e64732666d570f72aa61","host":"127.0.0.1","method":"GET","uri":"/","url":"/","proto":"HTTP/1.1","status":404,"size":19,"start":"28/May/2025:18:58:33 +0000","end":"28/May/2025:18:58:33 +0000","time_ns":113649,"time":"2025-05-28T18:58:33Z","message":"http"}
{"level":"warn","service":"ocm","pkg":"rhttp","traceid":"5cc2efee8d7d11f6f352755ec535fc54","time":"2025-05-28T18:58:33Z","message":"core access token not set"}
{"level":"warn","service":"ocm","pkg":"rhttp","traceid":"5cc2efee8d7d11f6f352755ec535fc54","host":"127.0.0.1","method":"GET","uri":"/","url":"/","proto":"HTTP/1.1","status":404,"size":19,"start":"28/May/2025:18:58:33 +0000","end":"28/May/2025:18:58:33 +0000","time_ns":198562,"time":"2025-05-28T18:58:33Z","message":"http"}
{"level":"warn","service":"frontend","pkg":"rhttp","traceid":"c5a63c2ab2d1e217a5521ef7ff64d9dd","time":"2025-05-28T18:58:34Z","message":"core access token not set"}
{"level":"warn","service":"frontend","pkg":"rhttp","traceid":"c5a63c2ab2d1e217a5521ef7ff64d9dd","host":"127.0.0.1","method":"GET","uri":"/","url":"/","proto":"HTTP/1.1","status":401,"size":0,"start":"28/May/2025:18:58:34 +0000","end":"28/May/2025:18:58:34 +0000","time_ns":609080,"time":"2025-05-28T18:58:34Z","message":"http"}
{"level":"warn","service":"frontend","pkg":"rhttp","traceid":"7f083b1d82e226405dd3706fb1c146ab","time":"2025-05-28T18:58:37Z","message":"core access token not set"}
{"level":"error","service":"graph","error":"LDAP Result Code 200 \"Network Error\": dial tcp [::1]:9235: connect: connection refused","time":"2025-05-28T18:58:49Z","message":"could not get ldap Connection"}
{"level":"error","service":"graph","request-id":"opencloud-opencloud-55c4cd5bd9-qm7t9/Uu2RydGzJC-000035","error":"LDAP Result Code 200 \"Network Error\": dial tcp [::1]:9235: connect: connection refused","time":"2025-05-28T18:58:49Z","message":"failed to add user"}
{"level":"error","service":"graph","request-id":"opencloud-opencloud-55c4cd5bd9-qm7t9/Uu2RydGzJC-000035","error":"generalException: failed to add user","time":"2025-05-28T18:58:49Z","message":"could not create user: backend error"}
{"level":"warn","service":"proxy","OData Error":"failed to add user","time":"2025-05-28T18:58:49Z","message":"Error Response"}
{"level":"error","service":"proxy","error":"500 Internal Server Error","time":"2025-05-28T18:58:49Z","message":"Error creating user"}
{"level":"error","service":"proxy","error":"500 Internal Server Error","time":"2025-05-28T18:58:49Z","message":"Autoprovisioning user failed"}
{"level":"error","service":"graph","error":"LDAP Result Code 200 \"Network Error\": dial tcp [::1]:9235: connect: connection refused","time":"2025-05-28T18:59:38Z","message":"could not get ldap Connection"}
{"level":"error","service":"graph","request-id":"opencloud-opencloud-55c4cd5bd9-qm7t9/Uu2RydGzJC-000066","error":"LDAP Result Code 200 \"Network Error\": dial tcp [::1]:9235: connect: connection refused","time":"2025-05-28T18:59:38Z","message":"failed to add user"}
{"level":"error","service":"graph","request-id":"opencloud-opencloud-55c4cd5bd9-qm7t9/Uu2RydGzJC-000066","error":"generalException: failed to add user","time":"2025-05-28T18:59:38Z","message":"could not create user: backend error"}
{"level":"warn","service":"proxy","OData Error":"failed to add user","time":"2025-05-28T18:59:38Z","message":"Error Response"}
{"level":"error","service":"proxy","error":"500 Internal Server Error","time":"2025-05-28T18:59:38Z","message":"Error creating user"}
{"level":"error","service":"proxy","error":"500 Internal Server Error","time":"2025-05-28T18:59:38Z","message":"Autoprovisioning user failed"}
And the error from the GUI:
Nicht angemeldet
Das könnte aufgrund einer routinemäßigen Abmeldung aus Sicherheitsgründen geschehen sein oder Ihr Benutzerkonto ist inaktiv oder noch nicht freigeschaltet. Bitte versuchen Sie es nach einiger Zeit erneut oder wenden Sie sich an Ihre Administration.
Doc
P.S. I would change the description for the value opencloud.replicas, because it´s misleading IMHO:
Current:
Number of replicas (Note: When using multiple replicas, persistence should be disabled or use a storage class that supports ReadWriteMany access mode)
New:
Number of replicas (Note: When using multiple replicas, use a storage class that supports ReadWriteMany access mode)