helm icon indicating copy to clipboard operation
helm copied to clipboard

Non-Internal Database Prompts Admin creation window on deployment and subsequent updates

Open kyle-rf opened this issue 4 years ago • 9 comments

I have been experimenting deployment with various settings and one of the biggest pain points I am dealing with is using either an external database or mariadb.

I have a postgres database setup and on deployment, nextcloud has access. I can see all the tables it created and the admin user is in the oc_users table, generated from the existingSecret. However, accessing nextcloud for the first time still loads the admin creation window. Furthermore, if I make changes and run helm update I again get the admin creation window.

kyle-rf avatar Jul 09 '21 20:07 kyle-rf

With mariadb, the initial deployment is fine. But if some minor changes are made (not against the database itself) and a helm update command is run, the create admin page will come up rather than a standarad login page.

kyle-rf avatar Jul 12 '21 14:07 kyle-rf

I get the same behavior. I can't recreate the same admin user. Is there any way around it?

MagicTrevor avatar Aug 16 '21 02:08 MagicTrevor

Hi, first of all, thanks for the amazing work you are doing with this chart.

I'm facing the same issue @kyle-rf described. Using an external Postgres DB makes the nextcloud initial screen become an admin account creation page. I'm using microk8s. I have been trying to figure this out for days and I would love to use this chart rather than setting everything manually. Hope someone can help.

Thanks in advance for your support!

MicroK8s v1.27.2 revision 5372
Nextcloud chart version   3.5.15

Here is my values.yaml

values.yaml
## Official nextcloud image version
## ref: https://hub.docker.com/r/library/nextcloud/tags/
##
image:
  repository: nextcloud
  # tag: 24.0.3-apache
  pullPolicy: IfNotPresent
  # pullSecrets:
  #   - myRegistrKeySecretName

nameOverride: ""
fullnameOverride: ""
podAnnotations: {}
deploymentAnnotations: {}
deploymentLabels: {}

# Number of replicas to be deployed
replicaCount: 1

## Allowing use of ingress controllers
## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/
##
ingress:
  enabled: trues
  className: nginx
  annotations: 
    nginx.ingress.kubernetes.io/proxy-body-size: 4G
    kubernetes.io/tls-acme: "true"
    cert-manager.io/cluster-issuer: lets-encrypt
    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 = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
      }
      location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
        deny all;
      }
      location ~ ^/(?:autotest|occ|issue|indie|db_|console) {
        deny all;
      }
  tls:
    - secretName: example-ingress-tls
      hosts:
        - my.domain.com
  labels: {}
  path: /
  pathType: Prefix


# Allow configuration of lifecycle hooks
# ref: https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/
lifecycle: {}
  # postStartCommand: []
  # preStopCommand: []

phpClientHttpsFix:
  enabled: false
  protocol: https

nextcloud:
  host: my.domain.com
  username: admin
  password: changeme
  ## Use an existing secret
  existingSecret:
    enabled: false
    # secretName: nameofsecret
    # usernameKey: nextcloud-username
    # passwordKey: nextcloud-password
    # tokenKey: nextcloud-token
    # smtpUsernameKey: smtp-username
    # smtpPasswordKey: smtp-password
  update: 0
  # If web server is not binding default port, you can define it
  containerPort: 80
  datadir: /var/www/html/data
  persistence:
    subPath:
  mail:
    enabled: false
    fromAddress: user
    domain: domain.com
    smtp:
      host: domain.com
      secure: ssl
      port: 465
      authtype: LOGIN
      name: user
      password: pass
  # PHP Configuration files
  # Will be injected in /usr/local/etc/php/conf.d for apache image and in /usr/local/etc/php-fpm.d when nginx.enabled: true
  phpConfigs: {}
  # Default config files
  # IMPORTANT: Will be used only if you put extra configs, otherwise default will come from nextcloud itself
  # Default confgurations can be found here: https://github.com/nextcloud/docker/tree/master/16.0/apache/config
  defaultConfigs:
    # To protect /var/www/html/config
    .htaccess: true
    # Redis default configuration
    redis.config.php: true
    # Apache configuration for rewrite urls
    apache-pretty-urls.config.php: true
    # Define APCu as local cache
    apcu.config.php: true
    # Apps directory configs
    apps.config.php: true
    # Used for auto configure database
    autoconfig.php: true
    # SMTP default configuration
    smtp.config.php: true
  # Extra config files created in /var/www/html/config/
  # ref: https://docs.nextcloud.com/server/15/admin_manual/configuration_server/config_sample_php_parameters.html#multiple-config-php-file
  configs: {}

  # For example, to use S3 as primary storage
  # ref: https://docs.nextcloud.com/server/13/admin_manual/configuration_files/primary_storage.html#simple-storage-service-s3
  #
  #  configs:
  #    s3.config.php: |-
  #      <?php
  #      $CONFIG = array (
  #        'objectstore' => array(
  #          'class' => '\\OC\\Files\\ObjectStore\\S3',
  #          'arguments' => array(
  #            'bucket'     => 'my-bucket',
  #            'autocreate' => true,
  #            'key'        => 'xxx',
  #            'secret'     => 'xxx',
  #            'region'     => 'us-east-1',
  #            'use_ssl'    => true
  #          )
  #        )
  #      );

  ## Strategy used to replace old pods
  ## IMPORTANT: use with care, it is suggested to leave as that for upgrade purposes
  ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy
  strategy:
    type: Recreate
    # type: RollingUpdate
    # rollingUpdate:
    #   maxSurge: 1
    #   maxUnavailable: 0

  ##
  ## Extra environment variables
  extraEnv:
   - name: OVERWRITEHOST
     value: my.domain.com
  #  - name: SOME_SECRET_ENV
  #    valueFrom:
  #      secretKeyRef:
  #        name: nextcloud
  #        key: secret_key

  # Extra init containers that runs before pods start.
  extraInitContainers: []
  #  - name: do-something
  #    image: busybox
  #    command: ['do', 'something']

  # Extra sidecar containers.
  extraSidecarContainers: []
  #  - name: nextcloud-logger
  #    image: busybox
  #    command: [/bin/sh, -c, 'while ! test -f "/run/nextcloud/data/nextcloud.log"; do sleep 1; done; tail -n+1 -f /run/nextcloud/data/nextcloud.log']
  #    volumeMounts:
  #    - name: nextcloud-data
  #      mountPath: /run/nextcloud/data

  # Extra mounts for the pods. Example shown is for connecting a legacy NFS volume
  # to NextCloud pods in Kubernetes. This can then be configured in External Storage
  extraVolumes:
  #  - name: nfs
  #    nfs:
  #      server: "10.0.0.1"
  #      path: "/nextcloud_data"
  #      readOnly: false
  extraVolumeMounts:
  #  - name: nfs
  #    mountPath: "/legacy_data"

  # 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

nginx:
  ## You need to set an fpm version of the image for nextcloud if you want to use nginx!
  enabled: false
  image:
    repository: nginx
    tag: alpine
    pullPolicy: IfNotPresent

  config:
    # This generates the default nginx config as per the nextcloud documentation
    default: true
    # custom: |-
    #     worker_processes  1;..

  resources: {}

  # Set nginx container securityContext parameters. For example, you may need to define runAsNonRoot directive
  securityContext: {}
  # the nginx alpine container default user is 82
  #   runAsUser: 82
  #   runAsGroup: 33
  #   runAsNonRoot: true
  #   readOnlyRootFilesystem: true

internalDatabase:
  enabled: false
  name: nextcloud

##
## External database configuration
##
externalDatabase:
  enabled: true

  ## Supported database engines: mysql or postgresql
  type: postgresql

  ## Database host
  host: some.postgres.instances.svc.local:5432

  ## Database user
  user: nextcloud

  ## Database password
  password: nextcloud

  ## Database name
  database: nextcloud

  ## Use a existing secret
  existingSecret:
    enabled: false
    # secretName: nameofsecret
    # usernameKey: db-username
    # passwordKey: db-password

##
## MariaDB chart configuration
## ref: https://github.com/bitnami/charts/tree/main/bitnami/mariadb
##
mariadb:
  ## Whether to deploy a mariadb server from the bitnami mariab db helm chart
  # to satisfy the applications database requirements. if you want to deploy this bitnami mariadb, set this and externalDatabase to true
  # To use an ALREADY DEPLOYED mariadb database, set this to false and configure the externalDatabase parameters
  enabled: false

  auth:
    database: nextcloud
    username: nextcloud
    password: changeme
    # Use existing secret (auth.rootPassword, auth.password, and auth.replicationPassword will be ignored).
    # secret must contain the keys mariadb-root-password, mariadb-replication-password and mariadb-password
    existingSecret: ""

  architecture: standalone

  ## Enable persistence using Persistent Volume Claims
  ## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
  ##
  primary:
    persistence:
      enabled: false
      # Use an existing Persistent Volume Claim (must be created ahead of time)
      # existingClaim: ""
      # storageClass: ""
      accessMode: ReadWriteOnce
      size: 8Gi

##
## PostgreSQL chart configuration
## for more options see https://github.com/bitnami/charts/tree/main/bitnami/postgresql
##
postgresql:
  enabled: false
  global:
    postgresql:
      # global.postgresql.auth overrides postgresql.auth
      auth:
        username: nextcloud
        password: changeme
        database: nextcloud
        # Name of existing secret to use for PostgreSQL credentials.
        # auth.postgresPassword, auth.password, and auth.replicationPassword will be ignored and picked up from this secret.
        # secret might also contains the key ldap-password if LDAP is enabled.
        # ldap.bind_password will be ignored and picked from this secret in this case.
        existingSecret: ""
        # Names of keys in existing secret to use for PostgreSQL credentials
        secretKeys:
          adminPasswordKey: ""
          userPasswordKey: ""
          replicationPasswordKey: ""
  primary:
    persistence:
      enabled: false
      # Use an existing Persistent Volume Claim (must be created ahead of time)
      # existingClaim: ""
      # storageClass: ""

##
## Redis chart configuration
## for more options see https://github.com/bitnami/charts/tree/main/bitnami/redis
##

redis:
  enabled: false
  auth:
    enabled: true
    password: 'changeme'
    # name of an existing secret with Redis® credentials (instead of auth.password), must be created ahead of time
    existingSecret: ""
    # Password key to be retrieved from existing secret
    existingSecretPasswordKey: ""


## Cronjob to execute Nextcloud background tasks
## ref: https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/background_jobs_configuration.html#cron
##
cronjob:
  enabled: false

  ## Cronjob sidecar resource requests and limits
  ## ref: http://kubernetes.io/docs/user-guide/compute-resources/
  ##
  resources: {}

  # Allow configuration of lifecycle hooks
  # ref: https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/
  lifecycle: {}
    # postStartCommand: []
    # preStopCommand: []
  # Set securityContext parameters. For example, you may need to define runAsNonRoot directive
  securityContext: {}
  #   runAsUser: 33
  #   runAsGroup: 33
  #   runAsNonRoot: true
  #   readOnlyRootFilesystem: true

service:
  type: ClusterIP
  port: 8080
  loadBalancerIP: nil
  nodePort: nil

## Enable persistence using Persistent Volume Claims
## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
##
persistence:
  # Nextcloud Data (/var/www/html)
  enabled: true
  annotations: {}
  ## nextcloud data Persistent Volume Storage Class
  ## If defined, storageClassName: <storageClass>
  ## If set to "-", storageClassName: "", which disables dynamic provisioning
  ## If undefined (the default) or set to null, no storageClassName spec is
  ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
  ##   GKE, AWS & OpenStack)
  ##
  storageClass: ""

  ## A manually managed Persistent Volume and Claim
  ## Requires persistence.enabled: true
  ## If defined, PVC must be created manually before volume will be bound
  # existingClaim:

  accessMode: ReadWriteOnce
  size: 100Gi

  ## Use an additional pvc for the data directory rather than a subpath of the default PVC
  ## Useful to store data on a different storageClass (e.g. on slower disks)
  nextcloudData:
    enabled: false
    subPath:
    annotations: {}
    # storageClass: "-"
    # existingClaim:
    accessMode: ReadWriteOnce
    size: 8Gi

resources: {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #  cpu: 100m
  #  memory: 128Mi
  # requests:
  #  cpu: 100m
  #  memory: 128Mi

## Liveness and readiness probe values
## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes
##
livenessProbe:
  enabled: true
  initialDelaySeconds: 10
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3
  successThreshold: 1
readinessProbe:
  enabled: true
  initialDelaySeconds: 10
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3
  successThreshold: 1
startupProbe:
  enabled: false
  initialDelaySeconds: 30
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 30
  successThreshold: 1


## Enable pod autoscaling using HorizontalPodAutoscaler
## ref: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
##
hpa:
  enabled: false
  cputhreshold: 60
  minPods: 1
  maxPods: 10

nodeSelector: {}

tolerations: []

affinity: {}


## Prometheus Exporter / Metrics
##
metrics:
  enabled: false

  replicaCount: 1
  # The metrics exporter needs to know how you serve Nextcloud either http or https
  https: false
  # Use API token if set, otherwise fall back to password authentication
  # https://github.com/xperimental/nextcloud-exporter#token-authentication
  # Currently you still need to set the token manually in your nextcloud install
  token: ""
  timeout: 5s
  # if set to true, exporter skips certificate verification of Nextcloud server.
  tlsSkipVerify: false

  image:
    repository: xperimental/nextcloud-exporter
    tag: 0.6.0
    pullPolicy: IfNotPresent
    # pullSecrets:
    #   - myRegistrKeySecretName

  ## Metrics exporter resource requests and limits
  ## ref: http://kubernetes.io/docs/user-guide/compute-resources/
  ##
  # resources: {}

  ## Metrics exporter pod Annotation and Labels
  # podAnnotations: {}

  # podLabels: {}

  service:
    type: ClusterIP
    ## Use serviceLoadBalancerIP to request a specific static IP,
    ## otherwise leave blank
    # loadBalancerIP:
    annotations:
      prometheus.io/scrape: "true"
      prometheus.io/port: "9205"
    labels: {}

  ## Prometheus Operator ServiceMonitor configuration
  ##
  serviceMonitor:
    ## @param metrics.serviceMonitor.enabled Create ServiceMonitor Resource for scraping metrics using PrometheusOperator
    ##
    enabled: false

    ## @param metrics.serviceMonitor.namespace Namespace in which Prometheus is running
    ##
    namespace: ""

    ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus.
    ##
    jobLabel: ""

    ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped
    ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint
    ##
    interval: 30s

    ## @param metrics.serviceMonitor.scrapeTimeout Specify the timeout after which the scrape is ended
    ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint
    ##
    scrapeTimeout: ""

    ## @param metrics.serviceMonitor.labels Extra labels for the ServiceMonitor
    ##
    labels: {}


rbac:
  enabled: false
  serviceaccount:
    create: true
    name: nextcloud-serviceaccount
    annotations: {}


## @param securityContext for nextcloud pod @deprecated Use `nextcloud.podSecurityContext` instead
securityContext: {}

frankcs avatar Jul 10 '23 18:07 frankcs

Sorry for the delay everyone! 🙏

Thanks, @frankcs for giving us your values.yaml. I have this working on my end, but I use a persistent volume for both my external postgres chart and the nextcloud chart itself. Can you confirm the issue persists if you have persistence working on both postgres and nextcloud? I see you have it enabled in your values.yaml, but want to make sure your volumes are binding and ok.

The only other thing I can think is that something is going wrong with how we calculate your actual credentials maybe 🤔 :

https://github.com/nextcloud/helm/blob/14423bf14839f94aa92b90c7019898f27cc386d6/charts/nextcloud/templates/_helpers.tpl#L111-L125

On my personal home lab, I use external secrets. Out of curiosity, can you try creating a secret with your database credentials using:

externalDatabase:
  enabled: true
  type: postgresql
  host: some.postgres.instances.svc.local:5432
  database: nextcloud
  existingSecret:
    enabled: true
    secretName: beautiful-nextcloud-db-secret
    usernameKey: username
    passwordKey: password

The above example assumes you have a secret called beautiful-nextcloud-db-secret in the same namespace as nextcloud and the secret has the keys username and password with credentials to your database.

Minor note, but in the future, could you please also use syntax highlighting by appending yaml after the three backticks in markdown so like this: ```yaml, that way it's a little easier to read. You can also put it in a collapsible like this:

screenshot showing the use of the <details> and <summary> tags to make a syntax highlighted yaml code block collapsible

which will produce this:

values.yaml
example: yaml
  - beepboop

Then it's easier for others to scroll through the issue to catch up and evaluate different replies even if you post a very long values.yaml.

jessebot avatar Jul 12 '23 11:07 jessebot

Hi @jessebot and thanks for your quick response. I have checked that my persistent volumes are bound and also checked that the files are being written to them. All good there.

I tried your approach with the existing secret, although it seemed a bit counterintuitive to try with:

externalDatabase:
  ...
  existingSecret:
    enabled: false
  ...

I tried with the enabled set both to true and false. Surprisingly I got the same results in both cases:

  • The tables are created in the db
  • When accesing the domain root I still get the admin account creation page instead of a login screen
Captura de Pantalla 2023-07-12 a las 20 04 06

The issue still persists for me. The previously shared values.yaml is still valid for troubleshooting.

Thanks for your time!

frankcs avatar Jul 12 '23 18:07 frankcs

Thanks so much for editing your values.yaml 🙏

I didn't realize I left externalDatabase.existingSecret.enabled: false 🤦 Sorry for the misinformation; you were correct to try with it set to true though!

I'm not sure why this is happening, so I'll mark this as help wanted, but here's a few more questions:

  • Are you using helm directly or via something like Argo CD? What version of helm or ArgoCD are you using?
  • Are there any errors in your logs for the nextcloud container in the nextcloud pod? You can enable debug logging with the following in values.yaml:
nextcloud:
  configs:
    # Loglevel to start logging at. Valid values are: 0 = Debug, 1 = Info, 2 = Warning, 3 = Error, and 4 = Fatal. The default value is Warning.
    logging.config.php: |-
      <?php
      $CONFIG = array (
        'log_type' => 'file',
        'logfile' => 'nextcloud.log',
        'loglevel' => 0,
        'logdateformat' => 'F d, Y H:i:s'
        );
  • You've probably already checked this, but does the nextcloud database user have full privileges to the nextcloud database? example:
ALTER DATABASE nextcloud OWNER TO nextcloud;
GRANT ALL PRIVILEGES ON DATABASE nextcloud TO nextcloud;

jessebot avatar Jul 13 '23 07:07 jessebot

Thanks @jessebot for your time... I finally got the issue!!

It turns out that the nextcloud pod was being restarted before finishing the installation. When restarted it was "seeing" some tables created so it was kind of working but not really. That explained the "funny" admin account creation page.

I'm using some old hardware for my home lab, so the external database was probably introducing too much of a delay at startup.

I only had to do the following to get it to work:

startupProbe:
  enabled: true # This is false by default, you need to turn it on
  initialDelaySeconds: 120 # Adjust to meet your clunky hardware requirements

frankcs avatar Jul 13 '23 16:07 frankcs

Congrats, @frankcs ! I'm glad to hear it's working. You're also welcome to submit a PR to update our README to have a section on adjusting probes :)

@kyle-rf and @MagicTrevor are you also ok with this solution? Is it safe to close this issue? If I don't hear anything for a few weeks, I'll close this, but you are also free to ask for a reopen even I close it :)

jessebot avatar Jul 21 '23 08:07 jessebot