Non-Internal Database Prompts Admin creation window on deployment and subsequent updates
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.
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.
I get the same behavior. I can't recreate the same admin user. Is there any way around it?
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: {}
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:
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.
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
The issue still persists for me. The previously shared values.yaml is still valid for troubleshooting.
Thanks for your time!
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
nextclouddatabase user have full privileges to thenextclouddatabase? example:
ALTER DATABASE nextcloud OWNER TO nextcloud;
GRANT ALL PRIVILEGES ON DATABASE nextcloud TO nextcloud;
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
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 :)