nextcloud / helm

A community maintained helm chart for deploying Nextcloud on Kubernetes.
GNU Affero General Public License v3.0
315 stars 260 forks source link

A false WARNING is displayed about running with the integrated sqlite database when using PostgreSQL #315

Closed FredericLespez closed 1 year ago

FredericLespez commented 1 year ago

I deployed a Nextcloud instance with a PostgreSQL database. The deployment went fine and Nextcloud is working correctly. The PostgreSQL database is working fine and Nextcloud use it. But the helm command displayed this warning:

#######################################################################################################
## WARNING: You did not provide an external database host in your 'helm install' call                ##
## Running Nextcloud with the integrated sqlite database is not recommended for production instances ##
#######################################################################################################

This warning is misleading since the instance is not running with the integrated sqlite database.

How to reproduce:

For better performance etc. you have to configure nextcloud with a resolvable database host. To configure nextcloud to use and external database host:

  1. Complete your nextcloud deployment by running:

    export APP_HOST=127.0.0.1 export APP_PASSWORD=$(kubectl get secret --namespace test nextcloud -o jsonpath="{.data.nextcloud-password}" | base64 --decode)

    PLEASE UPDATE THE EXTERNAL DATABASE CONNECTION PARAMETERS IN THE FOLLOWING COMMAND AS NEEDED

    helm upgrade nextcloud nextcloud/nextcloud \ --set nextcloud.password=$APP_PASSWORD,nextcloud.host=$APP_HOST,service.type=ClusterIP,mariadb.enabled=false,externalDatabase.user=nextcloud,externalDatabase.database=nextcloud,externalDatabase.host=YOUR_EXTERNAL_DATABASE_HOST

What was expected:

In any case not warning about "Running Nextcloud with the integrated sqlite database is not recommended for production instances" since Nextcloud is not using the integrated sqlite database. Maybe a warning about not using an external database...

Full configuration and tests

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: {}

# Number of replicas to be deployed
replicaCount: 1

## Allowing use of ingress controllers
## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/
##
ingress:
  enabled: true
  className: nginx
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: 4G
    # kubernetes.io/tls-acme: "true"
    # cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/server-snippet: |-
      server_tokens off;
      proxy_hide_header X-Powered-By;

      rewrite ^/.well-known/webfinger /public.php?service=webfinger 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: ""
      hosts:
        - nextcloud.example.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: nextcloud.example.com
  username: admin
  password: changeme
  ## Use an existing secret
  existingSecret:
    enabled: false
    # secretName: nameofsecret
    # usernameKey: username
    # passwordKey: password
    # tokenKey: serverinfo_token
    # smtpUsernameKey: smtp_username
    # smtpPasswordKey: smtp_password
  update: 0
  # If web server is not binding default port, you can define it
  # containerPort: 8080
  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: false
  # 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:
    custom.config.php: |-
      <?php
      $CONFIG = array (
        'overwriteprotocol' => 'https',
        'overwrite.cli.url' => 'https://nextcloud.example.com',
        'filelocking.enabled' => 'true',
        'loglevel' => '2',
        'enable_previews' => true,
        'trusted_domains' =>
           [
            'nextcloud',
            'nextcloud.example.com'
           ]
      );

  # 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: 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"

  # Extra secuurityContext parameters. For example you may need to define runAsNonRoot directive
  # extraSecurityContext:
  #   runAsUser: "33"
  #   runAsGroup: "33"
  #   runAsNonRoot: true
  #   readOnlyRootFilesystem: true

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: {}

internalDatabase:
  enabled: false
  name: nextcloud

##
## External database configuration
##
externalDatabase:
  enabled: false

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

  ## Database host
  host:

  ## Database user
  user: nextcloud

  ## Database password
  password:

  ## Database name
  database: nextcloud

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

##
## MariaDB chart configuration
##
mariadb:
  ## Whether to deploy a mariadb server to satisfy the applications database requirements. To use an external database set this to false and configure the externalDatabase parameters
  enabled: false

  auth:
    database: nextcloud
    username: nextcloud
    password: changeme

  architecture: standalone

  ## Enable persistence using Persistent Volume Claims
  ## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
  ##
  primary:
    persistence:
      enabled: false
      # storageClass: ""
      accessMode: ReadWriteOnce
      size: 8Gi

##
## PostgreSQL chart configuration
## for more options see https://github.com/bitnami/charts/tree/master/bitnami/postgresql
##
postgresql:
  enabled: true
  global:
    postgresql:
      auth:
        username: nextcloud
        password: changeme
        database: nextcloud
  primary:
    persistence:
      enabled: false
      # storageClass: ""

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

redis:
  enabled: true
  auth:
    enabled: true
    password: 'changeme'

## 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

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

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: false
  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: 8Gi

  ## 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

  image:
    repository: xperimental/nextcloud-exporter
    tag: 0.5.1
    pullPolicy: IfNotPresent

  ## 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: {}

Nextcloud config.php

$ kubectl -n est exec nextcloud-7f7848765f-cc58g -- cat /var/www/html/config/config.php
Defaulted container "nextcloud" out of: nextcloud, postgresql-isready (init)
<?php
$CONFIG = array (
  'htaccess.RewriteBase' => '/',
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'apps_paths' => 
  array (
    0 => 
    array (
      'path' => '/var/www/html/apps',
      'url' => '/apps',
      'writable' => false,
    ),
    1 => 
    array (
      'path' => '/var/www/html/custom_apps',
      'url' => '/custom_apps',
      'writable' => true,
    ),
  ),
  'overwriteprotocol' => 'https',
  'overwrite.cli.url' => 'https://nextcloud.example.com',
  'filelocking.enabled' => 'true',
  'loglevel' => '2',
  'enable_previews' => true,
  'trusted_domains' => 
  array (
    0 => 'localhost',
  ),
  'memcache.distributed' => '\\OC\\Memcache\\Redis',
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'redis' => 
  array (
    'host' => 'nextcloud-redis-master',
    'port' => '6379',
    'password' => 'changeme',
  ),
  'passwordsalt' => 'jbgeWjygp6UFg8ArMaJ1zHmii3f+MR',
  'secret' => 'jwMqMeoDWG5xDBexNWGxzf3tkcaMe0MivIsRJYJSn5XKLSlF',
  'datadirectory' => '/var/www/html/data',
  'dbtype' => 'pgsql',
  'version' => '25.0.1.1',
  'dbname' => 'nextcloud',
  'dbhost' => 'nextcloud-postgresql',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'dbuser' => 'nextcloud',
  'dbpassword' => 'changeme',
  'installed' => true,
  'instanceid' => 'oc7qrttvmumf',
);

Nextcloud database in PostgreSQL container

$ kubectl -n test exec -it nextcloud-postgresql-0 -- psql -U nextcloud
Password for user nextcloud: 
psql (14.4)
Type "help" for help.

nextcloud=> \l
                                   List of databases
   Name    |   Owner   | Encoding |   Collate   |    Ctype    |    Access privileges    
-----------+-----------+----------+-------------+-------------+-------------------------
 nextcloud | nextcloud | UTF8     | en_US.UTF-8 | en_US.UTF-8 | nextcloud=CTc/nextcloud
 postgres  | postgres  | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0 | postgres  | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres            +
           |           |          |             |             | postgres=CTc/postgres
 template1 | postgres  | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres            +
           |           |          |             |             | postgres=CTc/postgres
(4 rows)

nextcloud=> \dt
                    List of relations
 Schema |            Name             | Type  |   Owner   
--------+-----------------------------+-------+-----------
 public | oc_accounts                 | table | nextcloud
 public | oc_accounts_data            | table | nextcloud
 public | oc_activity                 | table | nextcloud
 public | oc_activity_mq              | table | nextcloud
 public | oc_addressbookchanges       | table | nextcloud
 public | oc_addressbooks             | table | nextcloud
 public | oc_appconfig                | table | nextcloud
 public | oc_authorized_groups        | table | nextcloud
 public | oc_authtoken                | table | nextcloud
 public | oc_bruteforce_attempts      | table | nextcloud
 public | oc_calendar_invitations     | table | nextcloud
 public | oc_calendar_reminders       | table | nextcloud
 public | oc_calendar_resources       | table | nextcloud
 public | oc_calendar_resources_md    | table | nextcloud
 public | oc_calendar_rooms           | table | nextcloud
 public | oc_calendar_rooms_md        | table | nextcloud
 public | oc_calendarchanges          | table | nextcloud
 public | oc_calendarobjects          | table | nextcloud
 public | oc_calendarobjects_props    | table | nextcloud
 public | oc_calendars           
<EDITED>
nextcloud=> select * from oc_users;
  uid  | displayname |                                              password                                               | uid_lower 
-------+-------------+-----------------------------------------------------------------------------------------------------+-----------
 admin |             | 3|$argon2id$v=19$m=65536,t=4,p=1$Qk9KMGs1UDgxa2syVGxONg$zTMnxg1wGPmTvzCgv8s7TOAV+h1UiYRolkMeXXjIEl0 | admin
(1 row)
jessebot commented 1 year ago

Hoi @FredericLespez, thanks for all the info you've provided. It looks like your issue is that you need to update the following externalDatabse.enabled setting to true and then fill in your db info. Here's my values.yaml as an example:

  internalDatabase:
    # this must be set to false
    enabled: false

  # External database configuration
  externalDatabase:
    # this must be set to true
    enabled: true
    ## Supported database engines: mysql or postgresql
    type: postgresql
    host: localhost:5432
    # Database name
    database: nextcloud
    ## Use a existing secret for credentials
    existingSecret:
      enabled: true
      secretName: nextcloud-pgsql-credentials
      usernameKey: username
      passwordKey: nextcloudPassword

  # Uses: https://github.com/bitnami/charts/tree/master/bitnami/postgresql
  postgresql:
    enabled: true
    global:
      postgresql:
        auth:
          username: nextcloud
          database: nextcloud
          existingSecret: nextcloud-pgsql-credentials
          secretKeys:
            userPasswordKey: nextcloudPassword
            adminPasswordKey: postgresPassword

It may be worth a PR to update the documentation in the README, and then maybe we should consider refactoring this warning a bit in the future so that if internalDatabase.enabled is set to false, we perhaps display a warning about not being provided the external database settings. We could also default check the postgresql or maridb yaml setting for the info we need, but that could get messy if a user was testing one or the other, as there's a few different raise conditions there. Happy to chat more about it and review any PRs you want to submit, otherwise I'll at least try to make some time to fix the docs on this at a later time. Just let me know if you want to move forward on it, so I don't step on your toes :)

jessebot commented 1 year ago

We've recently added clarification to the documentation here: https://github.com/nextcloud/helm/tree/main/charts/nextcloud#database-configurations

I'll close this now, but if you have further issues, let us know by opening a new issue after updating your externalDatabase parameters. (you don't have to use our bundled postgres or mariadb charts, but you do need to fill in externalDatabase)