Skip to content

/entrypoint.sh: line 192: php/conf.d/redis-session.ini: Permission denied for non-root container #187

Closed

Description

@devent

Need to run a non-root container. I set the securityContext as following:

securityContext:
  runAsUser: 33
  runAsGroup: 33

Get the error:

Configuring Redis as session handler
/entrypoint.sh: 56: cannot create /usr/local/etc/php/conf.d/redis-session.ini: Permission denied

Of course a non-root can not write to /usr/local/etc/php/conf.d

Source https://github.com/nextcloud/docker/blob/master/22/apache/entrypoint.sh#L77

Activity

  1. jessebot commented on Sep 5, 2023

    @jessebot
    Collaborator

    Does this still happen today using the latest version of this helm chart? I know that config may always be owned by root, as per this issue, #335, however, I'm not sure that's related. You could try setting this:

    nextcloud:
      podSecurityContext:
        runAsUser: 33
        runAsGroup: 33
        runAsNonRoot: true
        fsGroup: 33

    However, that may already get set here:

    securityContext:
    {{- if .Values.nextcloud.podSecurityContext }}
    {{- with .Values.nextcloud.podSecurityContext }}
    {{- toYaml . | nindent 8 }}
    {{- end }}
    {{- else }}
    {{- if .Values.nginx.enabled }}
    # Will mount configuration files as www-data (id: 82) for nextcloud
    fsGroup: 82
    {{- else }}
    # Will mount configuration files as www-data (id: 33) for nextcloud
    fsGroup: 33
    {{- end }}
    {{- if .Values.securityContext }}
    {{- with .Values.securityContext }}
    {{- toYaml . | nindent 8 }}
    {{- end }}
    {{- end }}
    {{- end }}

    Note: Since this issue was introduced, we've modified the available securityContext parameters. We have nextcloud.securityContext, nginx.securityContext (for the containers) and nextcloud.podSecurityContext (for the pod).

  2. applejag commented on Sep 7, 2023

    @applejag

    @jessebot Still having the issue when trying your YAML snippet. Also can't use the example from the chart's values.yaml as they are invalid values:

    # Set securityContext parameters for the nextcloud CONTAINER only (will not affect nginx container).
    # For example, you may need to define runAsNonRoot directive
    securityContext: {}
    # runAsUser: 33
    # runAsGroup: 33
    # runAsNonRoot: true
    # readOnlyRootFilesystem: false
    # Set securityContext parameters for the entire pod. For example, you may need to define runAsNonRoot directive
    podSecurityContext: {}
    # runAsUser: 33
    # runAsGroup: 33
    # runAsNonRoot: true
    # readOnlyRootFilesystem: false

    Have to revert to last known working version, which for me is 3.5.19 of the chart.

  3. jessebot commented on Sep 7, 2023

    @jessebot
    Collaborator

    @jilleJr or @devent could you please provide your whole values.yaml after anonymizing any sensitive data?

    Also can't use the example from the chart's values.yaml as they are invalid values

    Could you explain what you mean by invalid and where you're seeing the error? Those are the default values that are applied if you're using the non-alpine containers.

  4. applejag commented on Sep 7, 2023

    @applejag

    @jilleJr or @devent could you please provide your whole values.yaml after anonymizing any sensitive data?

    Also can't use the example from the chart's values.yaml as they are invalid values

    Sure:

    values.yaml
    image:
      flavor: fpm
    
    nginx:
      enabled: true
      resources:
        requests:
          memory: 10M
          cpu: 5m
        limits:
          memory: 100M
          cpu: 100m
    
    redis:
      enabled: true
      architecture: standalone
      auth:
        enabled: true
        password: ref+sops://secrets.yaml#redisPassword
      master:
        persistence:
          enabled: false
        requests:
          memory: 10M
          cpu: 10m
        limits:
          memory: 100M
          cpu: 100m
    
    ingress:
      enabled: true
      annotations:
        cert-manager.io/cluster-issuer: letsencrypt
        traefik.ingress.kubernetes.io/router.middlewares: nextcloud-nextcloud-replace-dav@kubernetescrd,nextcloud-nextcloud-replace-well-known@kubernetescrd,nextcloud-nextcloud-headers@kubernetescrd
      tls:
        - secretName: nextcloud-tls
          hosts:
            - XXXXXXXXXXXXXXXX
    
    nextcloud:
      host: XXXXXXXXXXXXXXXX
      username: ref+sops://secrets.yaml#nextcloudUsername
      password: ref+sops://secrets.yaml#nextcloudPassword
      mail:
        enabled: true
        domain: ref+sops://secrets.yaml#emailDomain
        smtp:
          host: ref+sops://secrets.yaml#emailSmtpHostname
          port: ref+sops://secrets.yaml#emailSmtpPort
          secure: ssl
          name: ref+sops://secrets.yaml#emailSmtpUsername
          password: ref+sops://secrets.yaml#emailSmtpPassword
      configs:
        misc.config.php: |
          <?php
          $CONFIG = array(
            'default_phone_region' => 'DE',
            'music.lastfm_api_key' => getenv('LASTFM_API_KEY'),
            'trusted_proxies' => array(
              0 => '127.0.0.1',
              1 => '10.0.0.0/8',
            ),
            'trusted_domains' => array (
              2 => 'XXXXXXXXXXXXXXXX',
            ),
          );
      extraEnv:
        - name: LASTFM_API_KEY
          valueFrom:
            secretKeyRef:
              key: LASTFM_API_KEY
              name: nextcloud-extras
        - name: PHP_MEMORY_LIMIT
          value: 1024M
      # Security context is broken in the Nexus chart:
      # https://github.com/nextcloud/helm/issues/187
      #securityContext:
      #  runAsUser: 33
      #  runAsGroup: 33
      #  runAsNonRoot: true
      #podSecurityContext:
      #  fsGroup: 82
      #  fsGroupChangePolicy: OnRootMismatch
    
    cronjob:
      enabled: true
    
      resources:
        requests:
          memory: 10M
          cpu: 5m
        limits:
          memory: 100M
          cpu: 100m
    
    resources:
      requests:
        memory: 1500M
        cpu: 100m
      limits:
        memory: 2000M
        cpu: 1000m
    
    persistence:
      enabled: true
      size: 30Gi
      annotations:
        helm.sh/resource-policy: keep
    
    internalDatabase:
      enabled: false
    
    externalDatabase:
      enabled: true
      type: mysql
    
    mariadb:
      enabled: true
      auth:
        username: ref+sops://secrets.yaml#mariadbUsername
        password: ref+sops://secrets.yaml#mariadbPassword
        rootPassword: ref+sops://secrets.yaml#mariadbRootPassword
      primary:
        persistence:
          enabled: true
          annotations:
            helm.sh/resource-policy: keep
        resources:
          requests:
            memory: 300M
            cpu: 30m
          limits:
            memory: 500M
            cpu: 200m
    
      volumePermissions:
        enabled: true
    
    metrics:
      enabled: true
      token: ref+sops://secrets.yaml#metricsToken
    

    Could you explain what you mean by invalid and where you're seeing the error? Those are the default values that are applied if you're using the non-alpine containers.

    The readOnlyRootFilesystem is not a valid pod-level securityContext field.

    Given that they're just copy-pasted from each other, I don't know how credible they are.

  5. eloo commented on Oct 6, 2023

    @eloo

    will this ever be fixed?
    or are we doomed to run nextcloud as root in kubernetes for ever?

  6. spikeygg commented on Nov 25, 2023

    @spikeygg

    I updated my nextcloud docker installation to 27.1.3 today and it failed with this similar error. I am running non-root user as well. I found this thread: https://forums.unraid.net/topic/88504-support-knex666-nextcloud/page/20/ where robbenmu suggests that removing the redis config from the docker container makes it work. I tried that and it also worked for me (without disabling/removing the redis configuration in config.php) but I doubt my nextcloud is using redis now.

    EDIT
    I found quickly that the mobile uploads wouldn't work: Malformed Server Configuration with Redis configured in the config.php but no Redis server defined. So, I added a bind volume to my docker container with a pointer to a local and editable redis-session.ini so that nextcloud could edit it inside /usr/local/etc/php/conf.d/redis-session.ini. This is a super dumb problem that should be fixed...

  7. jessebot commented on Nov 26, 2023

    @jessebot
    Collaborator

    @provokateurin or @tvories Are you running redis and a non-root container?

    https://github.com/nextcloud/docker/blob/d1dbc77e0b5e851105cf8606942e74b7d21fe682/27/apache/entrypoint.sh#L108-L133

    I see that this does indeed try to write to /usr/local/etc/php/conf.d/redis-session.ini, which would actually be a root owned directory I think. Would the correct thing to do be raising this with nextcloud/docker or nextcloud/server? Why is this being written here and could we maybe make it configurable?

  8. 98jan commented on Dec 10, 2023

    @98jan

    Any plans to make it work rootless? I am also failing for running nextcloud with redis enabled with a non-root user.

    Would really appreciate it, when there would be an option to run it rootless.

  9. jessebot commented on Dec 13, 2023

    @jessebot
    Collaborator

    @98jan can you please try asking in the upstream repo about this? This seems to be a nextcloud/docker issue.

  10. eloo commented on Dec 13, 2023

    @eloo

    there is already an issue upstream.. and its more than 4 years old :D but the maintainers seems not to care about that

    nextcloud/docker#763

  11. jessebot commented on Dec 14, 2023

    @jessebot
    Collaborator

    and its more than 4 years old :D but the maintainers seems not to care about that

    Please be nice. I know you're all frustrated, but it's not that the maintainers dislike you or your particular GitHub Issue. We're unpaid volunteers that do this in our free time.

    I left a comment on that issue: nextcloud/docker#763 (comment)

    One of the contributors there suggested:

    Don't set redis host. Configure it with occ

    If we can figure out the occ command, I'm open to a PR to remove the ConfigMap and instead have a job that has post-install helm hook annotations to set the redis host that way. As long as it doesn't break anything, that seems like a win-win situation, yes?

    Update

    @stavros-k responded and helped us out by providing the scripts we need here:

    here is the redis script, you will also find other utils in this dir
    https://github.com/stavros-k/containers/blob/master/apps/nextcloud-fpm/configure-scripts/occ-redis.sh

    Please feel free to test out the suggested solution and submit a PR.

    also, I played with the docker hooks feature a bit, but couldn't seem to get it to work? 🤔 you can see more details in nextcloud/docker#763 (comment) but until that's resolved (nextcloud/docker#2115), we still need to do this via a job with a helm hook rather than using the docker hooks feature.

  12. R-Nabil commented on Feb 23, 2024

    @R-Nabil

    May I ask what's the altest on this ? Trying to use redis with my k3s deployment and it fails with the same error (i'm not even running it as nonRoot for now...)

  13. jessebot commented on Jul 22, 2024

    @jessebot
    Collaborator

    @R-Nabil, sorry for the extreme delay here, but this shouldn't occur for non-root usage. If it's still happening, could you please open a separate issue?

  14. 4 remaining items

  15. added a commit that references this issue on Apr 3, 2025
    73a5127
  16. added a commit that references this issue on Jul 17, 2025
    5de9afb
  17. added 3 commits that reference this issue on Feb 25, 2026
    5d14ab8
    4bcbe1e
    f95853a
  18. jessebot commented on Jul 19, 2026

    @jessebot
    Collaborator

    Quick update on this, when I try the fix that I saw in kreativmonkey/homelab-gitops#161 at least the pod is running again, which is already a massive change from 2023, when I couldn't get it to run at all using a non-root container. I still had to use a root initContainer, but the resulting nextcloud container running is indeed running as the user I'd expect (which in my case is 82).

    Here is my current full values.yaml

    full values.yaml
    image:
      # this is a custom nextcloud image with ffmpeg on it
      # it's otherwise exact the same as nextcloud:fpm-alpine
      repository: jessebot/nextcloud
      tag: {{ .Values.nextcloud.tag }}
      pullPolicy: IfNotPresent
    
    podLabels:
      deploymentName: nextcloud
    
    {{- with .Values.tolerations }}
    tolerations:
      {{- toYaml . | nindent 10 }}
    {{- end }}
    
    {{- with .Values.affinity }}
    affinity:
      {{- toYaml . | nindent 10 }}
    {{- end }}
    
    ingress:
      enabled: true
      className: nginx
      annotations:
        cert-manager.io/cluster-issuer: '{{ .Values.global.clusterIssuer }}'
        nginx.ingress.kubernetes.io/proxy-body-size: 10G
        nginx.ingress.kubernetes.io/enable-cors: "false"
        nginx.ingress.kubernetes.io/server-snippet: |-
          server_tokens off;
          proxy_hide_header X-Powered-By;
    
          rewrite ^/.well-known/webfinger /index.php/.well-known/webfinger last;
          rewrite ^/.well-known/nodeinfo /index.php/.well-known/nodeinfo last;
          rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
          rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json;
          location = /.well-known/carddav {
            return 301 $scheme://$host/remote.php/dav;
          }
          location = /.well-known/caldav {
            return 301 $scheme://$host/remote.php/dav;
          }
          location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
            deny all;
          }
          location ~ ^/(?:autotest|occ|issue|indie|db_|console) {
            deny all;
          }
      tls:
        - secretName: nextcloud-tls
          hosts:
            - '{{ .Values.hostnames.nextcloud }}'
    
    nextcloud:
      host: '{{ .Values.hostnames.nextcloud }}'
      existingSecret:
        enabled: true
        secretName: nextcloud-admin-credentials
        usernameKey: username
        passwordKey: password
        tokenKey: serverInfoToken
        smtpUsernameKey: smtpUsername
        smtpPasswordKey: smtpPassword
        smtpHostKey: smtpHost
    
      # update to the latest version of nextcloud
      update: 1
    
      securityContext:
        runAsUser: 82
        runAsGroup: 82
        # runAsNonRoot: true
    
      podSecurityContext:
        fsGroup: 82
    
      # for sending notifications
      mail:
        enabled: true
        fromAddress: '{{ .Values.smtp.fromAddress }}'
        domain: '{{ .Values.smtp.domain }}'
    
      extraInitContainers:
        - name: change-data-dir-permissions
          image: alpine:latest
          # we're currently battling:
          # /entrypoint.sh: line 121: can't create /usr/local/etc/php/conf.d/redis-session.ini: Permission denied
          command:
            - /bin/sh
            - -c
            - "chmod 770 -R /var/www/html/data && chown 82:www-data -R /var/www/html && touch /mnt/redis-session.ini && chown 82:www-data /mnt/redis-session.ini"
          volumeMounts:
            - mountPath: /var/www/
              name: nextcloud-main
              subPath: root
            - mountPath: /var/www/html
              name: nextcloud-main
              subPath: html
            - mountPath: /var/www/html/data
              name: nextcloud-main
              subPath: data
            - mountPath: /var/www/html/config
              name: nextcloud-main
              subPath: config
            - name: php-confd
              mountPath: /mnt
          securityContext:
            runAsUser: 0
            runAsGroup: 0
            runAsNonRoot: false
            seccompProfile:
              type: RuntimeDefault
    
      extraEnv:
        - name: "OVERWRITECLIURL"
          value: 'https://{{ .Values.hostnames.nextcloud }}'
    
        # fix time in nextcloud container
        - name: "TZ"
          value: '{{ .Values.global.timeZone }}'
    
        # OIDC parameters
        - name: "NC_oidc_login_provider_url"
          valueFrom:
            secretKeyRef:
              name: nextcloud-oidc-credentials
              key: issuer
    
        - name: "NC_oidc_login_client_id"
          valueFrom:
            secretKeyRef:
              name: nextcloud-oidc-credentials
              key: client_id
    
        - name: "NC_oidc_login_client_secret"
          valueFrom:
            secretKeyRef:
              name: nextcloud-oidc-credentials
              key: client_secret
    
        - name: "PGSSLCERT"
          value: /etc/secrets/nextcloud/tls.crt
    
        - name: "PGSSLKEY"
          value: /etc/secrets/nextcloud/tls.key
    
        - name: "PGSSLROOTCERT"
          value: /etc/secrets/ca/ca.crt
    
      extraVolumes:
        - name: postgres-ca
          secret:
            secretName: nextcloud-postgres-server-cert
            defaultMode: 0640
    
        - name: postgres-client-certs
          secret:
            secretName: nextcloud-postgres-nextcloud-cert
            defaultMode: 0640
    
        - name: php-confd
          emptyDir: {}
    
      extraVolumeMounts:
        - name: postgres-ca
          mountPath: /etc/secrets/ca
    
        - name: postgres-client-certs
          mountPath: /etc/secrets/nextcloud
    
        - name: php-confd
          mountPath: /usr/local/etc/php/conf.d/redis-session.ini
          subPath: redis-session.ini
    
      defaultConfigs:
        redis.config.php: true
    
      phpConfigs:
        #  www.conf: |-
        #    [www]
        #    user = www-data
        #    group = www-data
        www.conf: |-
          [www]
          security.limit_extensions = .php .css .js .html
          listen = 127.0.0.1:9000
          pm = dynamic
          pm.max_children = 350
          pm.start_servers = 100
          pm.min_spare_servers = 100
          pm.max_spare_servers = 280
    
        opcache.conf: |
          php_admin_value[memory_limit] = -1
          php_admin_value[opcache.jit_buffer_size] = 8M
          php_admin_value[opcache.interned_strings_buffer] = 64
          php_admin_value[opcache.memory_consumption] = 128M
          php_admin_value[opcache.max_accelerated_files] = 30000
          php_admin_value[opcache.validate_timestamps] = 0
          php_admin_value[opcache.revalidate_freq] = 60
          php_admin_value[upload_max_filesize] = 10G
          php_admin_value[post_max_size] = 10G
    
      configs:
        logging.config.php: |-
          <?php
          $CONFIG = array (
            'log_type' => 'errorlog',
            'logfile' => '',
            'loglevel' => 0,
            'logtimezone' => '{{ .Values.global.timeZone }}',
            'logdateformat' => 'F d, Y H:i:s',
            'maintenance_window_start' => 23,
            );
    
        previews.config.php: |-
          <?php
          $CONFIG = array (
            'enable_previews' => true,
            'enabledPreviewProviders' => array (
              'OC\Preview\Movie',
              'OC\Preview\PNG',
              'OC\Preview\SVG',
              'OC\Preview\JPEG',
              'OC\Preview\GIF',
              'OC\Preview\BMP',
              'OC\Preview\XBitmap',
              'OC\Preview\MP3',
              'OC\Preview\MP4',
              'OC\Preview\TXT',
              'OC\Preview\MarkDown',
              'OC\Preview\PDF',
            ),
          );
    
        proxy.config.php: |-
          <?php
          $CONFIG = array (
            'trusted_proxies' => array(
              0 => '127.0.0.1',
              1 => '10.0.0.0/8',
              2 => '192.168.0.0/16',
            ),
            'forwarded_for_headers' => array('HTTP_X_FORWARDED_FOR'),
          );
    
        extra.config.php: |-
          <?php
          $CONFIG = array (
            'allow_local_remote_servers' => true,
            'default_phone_region' => '{{ .Values.global.phoneRegion }}',
            'default_timezone' => '{{ .Values.global.timeZone }}',
          );
    
        oidc.config.php: |-
          <?php
          $CONFIG = array (
            // this disables the default login
            'hide_login_form' => true,
    
            // Some Nextcloud options that might make sense here
            'allow_user_to_change_display_name' => true,
            'lost_password_link' => 'disabled',
    
            // Automatically redirect the login page to the provider
            'oidc_login_auto_redirect' => false,
    
            // Redirect to this page after logging out the user
            'oidc_login_logout_url' => 'https://{{ .Values.hostnames.nextcloud }}/apps/oidc_login/oidc',
    
            // If set to true the user will be redirected to the
            // logout endpoint of the OIDC provider after logout
            'oidc_login_end_session_redirect' => false,
    
            // Login button text
            'oidc_login_button_text' => 'Log in with ZITADEL',
    
            // Hide the NextCloud password change form.
            'oidc_login_hide_password_form' => true,
    
            // Use ID Token instead of UserInfo
            'oidc_login_use_id_token' => false,
    
            // Attribute map for OIDC response.
            'oidc_login_attributes' => array (
                'id' => 'preferred_username',
                'name' => 'name',
                'mail' => 'email',
                'login_filter' => 'groups',
                'photoURL' => 'picture',
                'is_admin' => 'groups_nextcloud_admins',
            ),
    
            // Allow only users in configured value(s) to access Nextcloud. In case the user
            // is not assigned to this value (read from oidc_login_attributes) the login
            // will not be allowed for this user.
            'oidc_login_filter_allowed_values' => array('nextcloud_admins', 'nextcloud_users'),
    
            // Set OpenID Connect scope
            'oidc_login_scope' => 'openid profile email',
    
            // Run in LDAP proxy mode
            'oidc_login_proxy_ldap' => false,
    
            // Disable creation of users new to Nextcloud from OIDC login.
            // A user may be known to the IdP but not (yet) known to Nextcloud.
            'oidc_login_disable_registration' => false,
    
            // Fallback to direct login if login from OIDC fails
            // Note that no error message will be displayed if enabled
            'oidc_login_redir_fallback' => false,
    
            // If you get your groups from the oidc_login_attributes, you might want
            // to create them if they are not already existing, Default is `false`.
            'oidc_create_groups' => false,
    
            // Enable use of WebDAV via OIDC bearer token.
            'oidc_login_webdav_enabled' => true,
    
            // Enable authentication with user/password for DAV clients that do not
            // support token authentication (e.g. DAVx⁵)
            'oidc_login_password_authentication' => true,
    
            // The time in seconds used to cache public keys from provider.
            // The default value is 1 day.
            'oidc_login_public_key_caching_time' => 86400,
    
            // The time in seconds used to cache the OIDC well-known configuration from the provider.
            // The default value is 1 day.
            'oidc_login_well_known_caching_time' => 86400,
    
            // If true, nextcloud will download user avatars on login.
            // This may lead to security issues as the server does not control
            // which URLs will be requested. Use with care.
            'oidc_login_update_avatar' => true,
    
            // Code challenge method for PKCE flow.
            'oidc_login_code_challenge_method' => 'S256',
            );
    
    nginx:
      enabled: true
      config:
        # This generates the default nginx config as per the nextcloud documentation
        default: false
        custom: |-
          upstream php-handler {
              server 127.0.0.1:9000;
          }
    
          server {
              listen 80;
    
              # HSTS settings
              # WARNING: Only add the preload option once you read about
              # the consequences in https://hstspreload.org/. This option
              # will add the domain to a hardcoded list that is shipped
              # in all major browsers and getting removed from this list
              # could take several months.
              #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
    
              # set max upload size
              client_max_body_size 10G;
              fastcgi_buffers 64 4K;
    
              # Enable gzip but do not remove ETag headers
              gzip on;
              gzip_vary on;
              gzip_comp_level 4;
              gzip_min_length 256;
              gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
              gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
    
              # Pagespeed is not supported by Nextcloud, so if your server is built
              # with the `ngx_pagespeed` module, uncomment this line to disable it.
              #pagespeed off;
    
              # HTTP response headers borrowed from Nextcloud `.htaccess`
              add_header Referrer-Policy                      "no-referrer"       always;
              add_header X-Content-Type-Options               "nosniff"           always;
              add_header X-Download-Options                   "noopen"            always;
              add_header X-Frame-Options                      "SAMEORIGIN"        always;
              add_header X-Permitted-Cross-Domain-Policies    "none"              always;
              add_header X-Robots-Tag                         "noindex, nofollow" always;
              add_header X-XSS-Protection                     "1; mode=block"     always;
    
              # Remove X-Powered-By, which is an information leak
              fastcgi_hide_header X-Powered-By;
    
              # If the user agent is missing, empty, or contains a single hyphen
              # return forbidden http code
              if ($http_user_agent ~ "^-?$") {
                return 403;
              }
    
              # set the real ip in the logs
              set_real_ip_from 192.168.0.0/16;
              set_real_ip_from 10.0.0.0/8;
              real_ip_recursive on;
    
              # Add .mjs as a file extension for javascript
              # Either include it in the default mime.types list
              # or include you can include that list explicitly and add the file extension
              # only for Nextcloud like below:
              include mime.types;
              types {
                  text/javascript js mjs;
              }
    
              # Path to the root of your installation
              root /var/www/html;
    
              # Specify how to handle directories -- specifying `/index.php$request_uri`
              # here as the fallback means that Nginx always exhibits the desired behaviour
              # when a client requests a path that corresponds to a directory that exists
              # on the server. In particular, if that directory contains an index.php file,
              # that file is correctly served; if it doesn't, then the request is passed to
              # the front-end controller. This consistent behaviour means that we don't need
              # to specify custom rules for certain paths (e.g. images and other assets,
              # `/updater`, `/ocm-provider`, `/ocs-provider`), and thus
              # `try_files $uri $uri/ /index.php$request_uri`
              # always provides the desired behaviour.
              index index.php index.html /index.php$request_uri;
    
              # Rule borrowed from `.htaccess` to handle Microsoft DAV clients
              location = / {
                  if ( $http_user_agent ~ ^DavClnt ) {
                      return 302 /remote.php/webdav/$is_args$args;
                  }
              }
    
              location = /robots.txt {
                  allow all;
                  log_not_found off;
                  access_log off;
              }
    
              # Make a regex exception for `/.well-known` so that clients can still
              # access it despite the existence of the regex rule
              # `location ~ /(\.|autotest|...)` which would otherwise handle requests
              # for `/.well-known`.
              location ^~ /.well-known {
                  # The following 6 rules are borrowed from `.htaccess`
    
                  location = /.well-known/carddav     { return 301 /remote.php/dav/; }
                  location = /.well-known/caldav      { return 301 /remote.php/dav/; }
                  # Anything else is dynamically handled by Nextcloud
                  location ^~ /.well-known            { return 301 /index.php$uri; }
    
                  try_files $uri $uri/ =404;
              }
    
              # Rules borrowed from `.htaccess` to hide certain paths from clients
              location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)  { return 404; }
              location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console)              { return 404; }
    
              # Ensure this block, which passes PHP files to the PHP process, is above the blocks
              # which handle static assets (as seen below). If this block is not declared first,
              # then Nginx will encounter an infinite rewriting loop when it prepends `/index.php`
              # to the URI, resulting in a HTTP 500 error response.
              location ~ \.php(?:$|/) {
                  # Required for legacy support
                  rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /index.php$request_uri;
    
                  fastcgi_split_path_info ^(.+?\.php)(/.*)$;
                  set $path_info $fastcgi_path_info;
    
                  try_files $fastcgi_script_name =404;
    
                  include fastcgi_params;
                  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                  fastcgi_param PATH_INFO $path_info;
                  #fastcgi_param HTTPS on;
    
                  fastcgi_param modHeadersAvailable true;         # Avoid sending the security headers twice
                  fastcgi_param front_controller_active true;     # Enable pretty urls
                  fastcgi_pass php-handler;
    
                  fastcgi_intercept_errors on;
                  fastcgi_request_buffering off;
              }
    
              location ~ \.(?:css|js|svg|gif)$ {
                  try_files $uri /index.php$request_uri;
                  expires 6M;         # Cache-Control policy borrowed from `.htaccess`
                  access_log off;     # Optional: Don't log access to assets
              }
    
              location ~ \.woff2?$ {
                  try_files $uri /index.php$request_uri;
                  expires 7d;         # Cache-Control policy borrowed from `.htaccess`
                  access_log off;     # Optional: Don't log access to assets
              }
    
              location / {
                  try_files $uri $uri/ /index.php$request_uri;
              }
          }
    
      extraEnv:
        # fix time in nginx container
        - name: "TZ"
          value: '{{ .Values.global.timeZone }}'
    
    internalDatabase:
      enabled: false
    
    externalDatabase:
      enabled: true
      type: postgresql
      host: "nextcloud-postgres-rw.nextcloud.svc:5432;sslmode=verify-full;sslrootcert=/etc/secrets/ca/ca.crt;sslcert=/etc/secrets/nextcloud/tls.crt;sslkey=/etc/secrets/nextcloud/tls.key"
      database: nextcloud
      existingSecret:
        enabled: true
        secretName: nextcloud-pgsql-credentials
        usernameKey: username
        passwordKey: password
    
    postgresql:
      enabled: false
    
    externalRedis:
      enabled: true
      ## Redis host
      host: "nextcloud-valkey.nextcloud.svc.cluster.local"
      ## Redis port
      port: "6379"
      ## Redis password
      password: ""
      ## Use a existing secret
      existingSecret:
        enabled: true
        secretName: nextcloud-valkey-credentials
        passwordKey: valkeyPassword
    
    redis:
      enabled: false
    
    cronjob:
      enabled: true
    
    persistence:
      enabled: true
      existingClaim: nextcloud-files
      nextcloudData:
        enabled: false
    
    livenessProbe:
      enabled: false
      initialDelaySeconds: 20
      periodSeconds: 10
      timeoutSeconds: 10
      failureThreshold: 100
      successThreshold: 1
    
    readinessProbe:
      enabled: false
      initialDelaySeconds: 20
      periodSeconds: 10
      timeoutSeconds: 10
      failureThreshold: 100
      successThreshold: 1
    
    startupProbe:
      enabled: false
      initialDelaySeconds: 20
      periodSeconds: 10
      timeoutSeconds: 10
      failureThreshold: 100
      successThreshold: 1
    
    hpa:
      enabled: false
      cputhreshold: 60
      minPods: 1
      maxPods: 10
    
    metrics:
      enabled: true
      https: false
      token: "enabled"
      timeout: 10s
      podLabels:
        jobLabel: nextcloud-metrics
    
      service:
        annotations:
          prometheus.io/scrape: "true"
          prometheus.io/port: "9205"
        labels:
          jobLabel: nextcloud-metrics
    
      serviceMonitor:
        enabled: true
        namespace: "nextcloud"
    
    rbac:
      enabled: true
    
    ## Collabora chart configuration
    ## for more options see https://github.com/CollaboraOnline/online/tree/master/kubernetes/helm/collabora-online
    collabora:
      enabled: true
    
      # please check collabora README.md first
      autoscaling:
        enabled: false
    
      image:
        repository: collabora/code
        pullPolicy: IfNotPresent
        tag: 25.04.5.1.1
    
      collabora:
        fullnameOverrride: "collabora"
    
        ## HTTPS nextcloud domain, if needed
        aliasgroups:
          - host: "https://{{ .Values.hostnames.nextcloud }}:443"
    
        extra_params: >
          --o:ssl.enable=false
          --o:ssl.termination=true
          --o:fetch_update_check=0
          --o:num_prespawn_children=3
          --o:remote_font_config.url=https://{{ .Values.hostnames.nextcloud }}/apps/richdocuments/settings/fonts.json
    
        ## Specify server_name when the hostname is not reachable directly for example behind reverse-proxy
        server_name: '{{ .Values.hostnames.collabora }}'
    
        # setup admin login credentials
        existingSecret:
          enabled: true
          secretName: "collabora-admin-credentials"
          usernameKey: "username"
          passwordKey: "password"
    
      # setup ingress
      ingress:
        enabled: true
        className: "nginx"
        # please check collabora values.yaml for nginx/haproxy annotations examples
        annotations:
          cert-manager.io/cluster-issuer: '{{ .Values.global.clusterIssuer }}'
          nginx.ingress.kubernetes.io/upstream-hash-by: "$arg_WOPISrc"
          nginx.ingress.kubernetes.io/proxy-body-size: "0"
          nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
          nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
          nginx.ingress.kubernetes.io/server-snippet: |
            # block admin and metrics endpoint from outside by default
            location /cool/getMetrics { deny all; return 403; }
            location /cool/adminws/ { deny all; return 403; }
            location /browser/dist/admin/admin.html { deny all; return 403; }
    
        hosts:
          - host: '{{ .Values.hostnames.collabora }}'
            paths:
            - path: /
              pathType: ImplementationSpecific
        tls:
         - secretName: collabora-ingress-tls
           hosts:
             - '{{ .Values.hostnames.collabora }}'
    
      # see collabora helm README.md for recommended values
      # https://github.com/CollaboraOnline/online/tree/master/kubernetes/helm/collabora-online#deploying-collabora-online-in-kubernetes
      resources:
        limits:
          cpu: "8"
          memory: "8Gi"
        requests:
          cpu: "2"
          memory: "3Gi"

    The bits that probably matter the most are (keep in mind I run the alpine container):

    The important bits of the values.yaml probably
    externalRedis:
      enabled: true
      ## valkey host which is running locally in the cluster
      host: "nextcloud-valkey.nextcloud.svc.cluster.local"
      ## Redis port
      port: "6379"
      ## Use a existing secret
      existingSecret:
        enabled: true
        secretName: nextcloud-valkey-credentials
        passwordKey: valkeyPassword
    
    redis:
      enabled: false
    
    nextcloud:
      extraVolumes:
        - name: php-confd
          emptyDir: {}
    
      extraVolumeMounts:
        - name: php-confd
          mountPath: /usr/local/etc/php/conf.d/redis-session.ini
          subPath: redis-session.ini
    
      defaultConfigs:
        redis.config.php: true
    
      extraInitContainers:
        - name: change-data-dir-permissions
          image: alpine:latest
          # we're currently battling:
          # /entrypoint.sh: line 121: can't create /usr/local/etc/php/conf.d/redis-session.ini: Permission denied
          command:
            - /bin/sh
            - -c
            - "chmod 770 -R /var/www/html/data && chown 82:www-data -R /var/www/html && touch /mnt/redis-session.ini && chown 82:www-data /mnt/redis-session.ini"
          volumeMounts:
            - mountPath: /var/www/
              name: nextcloud-main
              subPath: root
            - mountPath: /var/www/html
              name: nextcloud-main
              subPath: html
            - mountPath: /var/www/html/data
              name: nextcloud-main
              subPath: data
            - mountPath: /var/www/html/config
              name: nextcloud-main
              subPath: config
            - name: php-confd
              mountPath: /mnt
          securityContext:
            runAsUser: 0
            runAsGroup: 0
            runAsNonRoot: false
            seccompProfile:
              type: RuntimeDefault

    Going through the valkey metrics now to make sure this is actually working, but I think this is the work around, at least at the helm chart level. Sorry I haven't been really active, but today my nextcloud slowed down enough that I finally looked into this again. Thanks to @kreativmonkey for their sluething.

  19. added a commit that references this issue on Jul 22, 2026
    668ad2e
  20. yodatak commented on Aug 22, 2026

    @yodatak

    For external redis the issue is still present :/ #752 dont fix for external and the artifacthub say the key is
    nextcloud.postgreSqlInitContainer.redisInitContainer and its seem not the good place

  21. added a commit that references this issue on Sep 17, 2026
  22. added 2 commits that reference this issue on Oct 1, 2026
  23. added a commit that references this issue on Oct 12, 2026
  24. added a commit that references this issue on Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    cachinganything to do with redis or opcachesecurityContextissues related security contexts

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions