feat: Adds Nextcloud application deployment

Deploys Nextcloud using an FPM-alpine image with a Caddy sidecar for web serving.

Integrates with an external CloudNativePG cluster for PostgreSQL and a dedicated Valkey instance for caching. Configures S3-compatible object storage for file data.

Includes an initialization Job to create essential admin and Valkey secrets. Sets up Ingress for external access with automated TLS provisioning via cert-manager.

Configures local-path persistence for Nextcloud's core data to ensure state is maintained across pod restarts. Centralizes hostname configuration and migrates various Nextcloud settings to environment variables for streamlined management.

Adds ArgoCD ignore rules for `batch/Job` resource selectors and template labels, preventing spurious out-of-sync states caused by Kubernetes mutations and improving synchronization stability.
This commit is contained in:
Felix Wolf 2026-04-04 18:08:13 +02:00
parent 27647e6c5c
commit d1959dd6cf
27 changed files with 1279 additions and 0 deletions

View file

@ -0,0 +1,5 @@
#@data/values-schema
---
#@overlay/match-child-defaults missing_ok=True
application:
namespace: nextcloud

View file

@ -0,0 +1,16 @@
#@ load("@ytt:overlay", "overlay")
#@overlay/match by=overlay.all, expects="1+"
---
#@overlay/match-child-defaults missing_ok=True
spec:
ignoreDifferences:
- group: batch
kind: Job
jsonPointers:
- /spec/selector
- /spec/template/metadata/labels
syncPolicy:
syncOptions:
#@overlay/append
- RespectIgnoreDifferences=true

View file

@ -14,3 +14,4 @@ environment:
- proto: hcloud-csi - proto: hcloud-csi
- proto: cloudnative-pg - proto: cloudnative-pg
- proto: metrics-server - proto: metrics-server
- proto: nextcloud

View file

@ -0,0 +1,5 @@
#@data/values-schema
---
#@overlay/match-child-defaults missing_ok=True
application:
namespace: nextcloud

View file

@ -0,0 +1,198 @@
---
_hostname: &hostname nextcloud.tr1ceracop.de
replicaCount: 1
image:
flavor: fpm-alpine
nginx:
enabled: false
nextcloud:
host: *hostname
existingSecret:
enabled: true
secretName: nextcloud-admin-secret
usernameKey: nextcloud-username
passwordKey: nextcloud-password
objectStore:
s3:
enabled: true
bucket: nextcloud-tr1ceracop
host: nbg1.your-objectstorage.com
port: "443"
ssl: true
region: nbg1
usePathStyle: true
existingSecret: nextcloud-s3-credentials
secretKeys:
accessKey: ACCESS_KEY_ID
secretKey: SECRET_ACCESS_KEY
defaultConfigs:
.htaccess: false
apache-pretty-urls.config.php: false
apcu.config.php: false
apps.config.php: false
autoconfig.php: false
redis.config.php: false
reverse-proxy.config.php: false
s3.config.php: false
smtp.config.php: false
swift.config.php: false
upgrade-disable-web.config.php: false
helm-metrics.config.php: false
extraEnv:
- name: TRUSTED_PROXIES
value: "10.0.0.0/8"
- name: OVERWRITEPROTOCOL
value: "https"
- name: OVERWRITEHOST
value: *hostname
- name: OVERWRITECLIURL
value: "https://nextcloud.tr1ceracop.de"
- name: NC_default_phone_region
value: "DE"
phpConfigs:
uploadLimit.ini: |
upload_max_filesize = 16G
post_max_size = 16G
max_input_time = 3600
max_execution_time = 3600
opcache.ini: |
opcache.enable=1
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=10000
opcache.memory_consumption=256
opcache.save_comments=1
opcache.revalidate_freq=60
extraSidecarContainers:
- name: caddy
image: caddy:2-alpine
ports:
- name: http
containerPort: 80
protocol: TCP
volumeMounts:
- name: nextcloud-main
mountPath: /var/www/
subPath: root
- name: nextcloud-main
mountPath: /var/www/html
subPath: html
- name: nextcloud-main
mountPath: /var/www/html/data
subPath: data
- name: nextcloud-main
mountPath: /var/www/html/config
subPath: config
- name: nextcloud-main
mountPath: /var/www/html/custom_apps
subPath: custom_apps
- name: nextcloud-main
mountPath: /var/www/tmp
subPath: tmp
- name: nextcloud-main
mountPath: /var/www/html/themes
subPath: themes
- name: caddy-config
mountPath: /etc/caddy
resources:
requests:
cpu: 50m
memory: 32Mi
limits:
memory: 64Mi
livenessProbe:
httpGet:
path: /status.php
port: 80
httpHeaders:
- name: Host
value: *hostname
initialDelaySeconds: 30
periodSeconds: 15
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /status.php
port: 80
httpHeaders:
- name: Host
value: *hostname
initialDelaySeconds: 30
periodSeconds: 15
timeoutSeconds: 5
extraVolumes:
- name: caddy-config
configMap:
name: nextcloud-caddy-config
strategy:
type: Recreate
internalDatabase:
enabled: false
externalDatabase:
enabled: true
type: postgresql
host: nextcloud-cnpg-rw.nextcloud.svc:5432
database: nextcloud
existingSecret:
enabled: true
secretName: nextcloud-cnpg-app
usernameKey: username
passwordKey: password
mariadb:
enabled: false
postgresql:
enabled: false
redis:
enabled: false
externalRedis:
enabled: true
host: nextcloud-valkey.nextcloud.svc
port: "6379"
existingSecret:
enabled: true
secretName: nextcloud-valkey-password
passwordKey: password
cronjob:
enabled: true
persistence:
enabled: true
size: 2Gi
storageClass: local-path
annotations:
helm.sh/resource-policy: keep
ingress:
enabled: true
className: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt
tls:
- secretName: nextcloud-tls
hosts:
- *hostname
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
memory: 512Mi

View file

@ -0,0 +1,16 @@
#@ load("@ytt:data", "data")
#@ app = data.values.application
---
apiVersion: vendir.k14s.io/v1alpha1
kind: Config
directories:
- path: #@ "charts/" + app.name
contents:
- path: .
helmChart:
name: #@ app.name
version: #@ app.version
repository:
url: #@ app.url
lazy: true

View file

@ -0,0 +1,8 @@
#@data/values-schema
---
#@overlay/match-child-defaults missing_ok=True
application:
#! renovate: datasource=helm
name: nextcloud
url: https://nextcloud.github.io/helm/
version: 9.0.4

View file

@ -0,0 +1,85 @@
#@ load("@ytt:data", "data")
#@ ns = data.values.application.namespace
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nextcloud-secret-init
namespace: #@ ns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: nextcloud-secret-init
namespace: #@ ns
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: nextcloud-secret-init
namespace: #@ ns
subjects:
- kind: ServiceAccount
name: nextcloud-secret-init
namespace: #@ ns
roleRef:
kind: Role
name: nextcloud-secret-init
apiGroup: rbac.authorization.k8s.io
---
apiVersion: batch/v1
kind: Job
metadata:
name: nextcloud-secret-init
namespace: #@ ns
annotations:
argocd.argoproj.io/sync-options: Replace=true
spec:
ttlSecondsAfterFinished: 300
template:
spec:
serviceAccountName: nextcloud-secret-init
restartPolicy: OnFailure
containers:
- name: init
image: alpine/k8s:1.32.3
command:
- sh
- -c
- |
set -e
if ! kubectl get secret nextcloud-admin-secret -n ${NAMESPACE} >/dev/null 2>&1; then
PASSWORD=$(head -c 32 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9' | head -c 24)
kubectl create secret generic nextcloud-admin-secret \
-n ${NAMESPACE} \
--from-literal=nextcloud-username=admin \
--from-literal=nextcloud-password="${PASSWORD}"
echo "Created nextcloud-admin-secret"
else
echo "nextcloud-admin-secret already exists, skipping"
fi
if ! kubectl get secret nextcloud-valkey-password -n ${NAMESPACE} >/dev/null 2>&1; then
VALKEY_PASSWORD=$(head -c 32 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9' | head -c 24)
kubectl create secret generic nextcloud-valkey-password \
-n ${NAMESPACE} \
--from-literal=password="${VALKEY_PASSWORD}"
echo "Created nextcloud-valkey-password"
else
echo "nextcloud-valkey-password already exists, skipping"
fi
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace

View file

@ -0,0 +1,61 @@
#@ load("@ytt:data", "data")
#@ ns = data.values.application.namespace
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nextcloud-caddy-config
namespace: #@ ns
data:
Caddyfile: |
:80 {
root * /var/www/html
header {
Referrer-Policy "no-referrer"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
X-Permitted-Cross-Domain-Policies "none"
X-Robots-Tag "noindex, nofollow"
X-XSS-Protection "1; mode=block"
-X-Powered-By
}
redir /.well-known/carddav /remote.php/dav/ 301
redir /.well-known/caldav /remote.php/dav/ 301
redir /.well-known/* /index.php{uri} 301
@blocked path /build/* /tests/* /config/* /lib/* /3rdparty/* /templates/* /data/*
respond @blocked 404
@davclnt {
path /
header User-Agent DavClnt*
}
redir @davclnt /remote.php/webdav/ 302
redir /remote /remote.php{uri} 301
php_fastcgi 127.0.0.1:9000 {
env HTTPS on
env modHeadersAvailable true
env front_controller_active true
resolve_root_symlink
}
@static path *.css *.js *.mjs *.svg *.gif *.ico *.jpg *.png *.webp *.wasm *.tflite *.map *.ogg *.flac
header @static Cache-Control "max-age=15778463"
@fonts path *.otf *.woff *.woff2
header @fonts Cache-Control "max-age=604800"
encode gzip
file_server
request_body {
max_size 16GB
}
}

View file

@ -0,0 +1,36 @@
#@ load("@ytt:data", "data")
#@ ns = data.values.application.namespace
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: nextcloud-cnpg
namespace: #@ ns
spec:
instances: 2
bootstrap:
initdb:
database: nextcloud
owner: nextcloud
storage:
size: 5Gi
storageClass: hcloud-volumes
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 512Mi
postgresql:
parameters:
shared_buffers: "64MB"
effective_cache_size: "128MB"
work_mem: "4MB"
maintenance_work_mem: "32MB"
max_connections: "100"

View file

@ -0,0 +1,18 @@
#@ load("@ytt:data", "data")
#@ load("@ytt:overlay", "overlay")
#@ ns = data.values.application.namespace
---
apiVersion: v1
kind: Namespace
metadata:
name: #@ ns
labels:
pod-security.kubernetes.io/enforce: privileged
#@overlay/match by=overlay.all, expects="1+"
---
metadata:
#@overlay/match missing_ok=True
namespace: #@ ns

View file

@ -0,0 +1,78 @@
#@ load("@ytt:data", "data")
#@ ns = data.values.application.namespace
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nextcloud-valkey
namespace: #@ ns
labels:
app.kubernetes.io/name: valkey
app.kubernetes.io/instance: nextcloud
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: valkey
app.kubernetes.io/instance: nextcloud
template:
metadata:
labels:
app.kubernetes.io/name: valkey
app.kubernetes.io/instance: nextcloud
spec:
containers:
- name: valkey
image: valkey/valkey:8-alpine
args:
- valkey-server
- --requirepass
- $(VALKEY_PASSWORD)
env:
- name: VALKEY_PASSWORD
valueFrom:
secretKeyRef:
name: nextcloud-valkey-password
key: password
ports:
- name: valkey
containerPort: 6379
protocol: TCP
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
memory: 128Mi
livenessProbe:
tcpSocket:
port: valkey
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
tcpSocket:
port: valkey
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: nextcloud-valkey
namespace: #@ ns
labels:
app.kubernetes.io/name: valkey
app.kubernetes.io/instance: nextcloud
spec:
type: ClusterIP
ports:
- port: 6379
targetPort: valkey
protocol: TCP
name: valkey
selector:
app.kubernetes.io/name: valkey
app.kubernetes.io/instance: nextcloud

View file

@ -0,0 +1,32 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
annotations:
myks.dev/environment: production
finalizers:
- resources-finalizer.argocd.argoproj.io
name: app-production-nextcloud
namespace: argocd
spec:
destination:
namespace: nextcloud
server: https://kubernetes.default.svc
ignoreDifferences:
- group: batch
jsonPointers:
- /spec/selector
- /spec/template/metadata/labels
kind: Job
project: env-production
source:
path: rendered/envs/production/nextcloud
repoURL: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
targetRevision: main
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
- RespectIgnoreDifferences=true

View file

@ -0,0 +1,29 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
name: nextcloud-cnpg
namespace: nextcloud
spec:
bootstrap:
initdb:
database: nextcloud
owner: nextcloud
instances: 2
postgresql:
parameters:
effective_cache_size: 128MB
maintenance_work_mem: 32MB
max_connections: "100"
shared_buffers: 64MB
work_mem: 4MB
resources:
limits:
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
storage:
size: 5Gi
storageClass: hcloud-volumes

View file

@ -0,0 +1,58 @@
apiVersion: v1
data:
Caddyfile: |
:80 {
root * /var/www/html
header {
Referrer-Policy "no-referrer"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
X-Permitted-Cross-Domain-Policies "none"
X-Robots-Tag "noindex, nofollow"
X-XSS-Protection "1; mode=block"
-X-Powered-By
}
redir /.well-known/carddav /remote.php/dav/ 301
redir /.well-known/caldav /remote.php/dav/ 301
redir /.well-known/* /index.php{uri} 301
@blocked path /build/* /tests/* /config/* /lib/* /3rdparty/* /templates/* /data/*
respond @blocked 404
@davclnt {
path /
header User-Agent DavClnt*
}
redir @davclnt /remote.php/webdav/ 302
redir /remote /remote.php{uri} 301
php_fastcgi 127.0.0.1:9000 {
env HTTPS on
env modHeadersAvailable true
env front_controller_active true
resolve_root_symlink
}
@static path *.css *.js *.mjs *.svg *.gif *.ico *.jpg *.png *.webp *.wasm *.tflite *.map *.ogg *.flac
header @static Cache-Control "max-age=15778463"
@fonts path *.otf *.woff *.woff2
header @fonts Cache-Control "max-age=604800"
encode gzip
file_server
request_body {
max_size 16GB
}
}
kind: ConfigMap
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
name: nextcloud-caddy-config
namespace: nextcloud

View file

@ -0,0 +1,26 @@
apiVersion: v1
data:
opcache.ini: |-
opcache.enable=1
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=10000
opcache.memory_consumption=256
opcache.save_comments=1
opcache.revalidate_freq=60
uploadLimit.ini: |-
upload_max_filesize = 16G
post_max_size = 16G
max_input_time = 3600
max_execution_time = 3600
kind: ConfigMap
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/instance: nextcloud
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: nextcloud
app.kubernetes.io/version: 33.0.0
helm.sh/chart: nextcloud-9.0.4
name: nextcloud-phpconfig
namespace: nextcloud

View file

@ -0,0 +1,55 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/instance: nextcloud
app.kubernetes.io/name: valkey
name: nextcloud-valkey
namespace: nextcloud
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/instance: nextcloud
app.kubernetes.io/name: valkey
template:
metadata:
labels:
app.kubernetes.io/instance: nextcloud
app.kubernetes.io/name: valkey
spec:
containers:
- args:
- valkey-server
- --requirepass
- $(VALKEY_PASSWORD)
env:
- name: VALKEY_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: nextcloud-valkey-password
image: valkey/valkey:8-alpine
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 10
tcpSocket:
port: valkey
name: valkey
ports:
- containerPort: 6379
name: valkey
protocol: TCP
readinessProbe:
initialDelaySeconds: 5
periodSeconds: 5
tcpSocket:
port: valkey
resources:
limits:
memory: 128Mi
requests:
cpu: 50m
memory: 64Mi

View file

@ -0,0 +1,358 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/component: app
app.kubernetes.io/instance: nextcloud
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: nextcloud
app.kubernetes.io/version: 33.0.0
helm.sh/chart: nextcloud-9.0.4
name: nextcloud
namespace: nextcloud
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/component: app
app.kubernetes.io/instance: nextcloud
app.kubernetes.io/name: nextcloud
strategy:
type: Recreate
template:
metadata:
annotations:
hooks-hash: 9525c2748a6c7cd0e28ec740623d0b3fa5a75c83b51ccfd136bc89c76737b204
nextcloud-config-hash: 97fd373864ae7c5da0eb066761ee479483364e3957160cacca360fc6a66c03f7
php-config-hash: b638f66fd8d65de8364dbad6efc59a6524c7b2e2377b5623cf5e921e4d3d2400
labels:
app.kubernetes.io/component: app
app.kubernetes.io/instance: nextcloud
app.kubernetes.io/name: nextcloud
spec:
containers:
- env:
- name: POSTGRES_HOST
value: nextcloud-cnpg-rw.nextcloud.svc:5432
- name: POSTGRES_DB
value: nextcloud
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
key: username
name: nextcloud-cnpg-app
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: nextcloud-cnpg-app
- name: NEXTCLOUD_ADMIN_USER
valueFrom:
secretKeyRef:
key: nextcloud-username
name: nextcloud-admin-secret
- name: NEXTCLOUD_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
key: nextcloud-password
name: nextcloud-admin-secret
- name: NEXTCLOUD_TRUSTED_DOMAINS
value: nextcloud.tr1ceracop.de
- name: OPENMETRICS_ALLOWED_CLIENTS
value: 127.0.0.1,10.42.0.0/16,10.43.0.0/16
- name: NEXTCLOUD_DATA_DIR
value: /var/www/html/data
- name: REDIS_HOST
value: nextcloud-valkey.nextcloud.svc
- name: REDIS_HOST_PORT
value: "6379"
- name: REDIS_HOST_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: nextcloud-valkey-password
- name: OBJECTSTORE_S3_SSL
value: "true"
- name: OBJECTSTORE_S3_USEPATH_STYLE
value: "true"
- name: OBJECTSTORE_S3_AUTOCREATE
value: "false"
- name: OBJECTSTORE_S3_REGION
value: nbg1
- name: OBJECTSTORE_S3_PORT
value: "443"
- name: OBJECTSTORE_S3_STORAGE_CLASS
value: STANDARD
- name: OBJECTSTORE_S3_HOST
value: nbg1.your-objectstorage.com
- name: OBJECTSTORE_S3_BUCKET
value: nextcloud-tr1ceracop
- name: OBJECTSTORE_S3_KEY
valueFrom:
secretKeyRef:
key: ACCESS_KEY_ID
name: nextcloud-s3-credentials
- name: OBJECTSTORE_S3_SECRET
valueFrom:
secretKeyRef:
key: SECRET_ACCESS_KEY
name: nextcloud-s3-credentials
- name: OBJECTSTORE_S3_SSE_C_KEY
value: ""
- name: TRUSTED_PROXIES
value: 10.0.0.0/8
- name: OVERWRITEPROTOCOL
value: https
- name: OVERWRITEHOST
value: nextcloud.tr1ceracop.de
- name: OVERWRITECLIURL
value: https://nextcloud.tr1ceracop.de
- name: NC_default_phone_region
value: DE
image: docker.io/library/nextcloud:33.0.0-fpm-alpine
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
httpHeaders:
- name: Host
value: nextcloud.tr1ceracop.de
path: /status.php
port: 80
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
name: nextcloud
ports:
- containerPort: 80
name: http
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
httpHeaders:
- name: Host
value: nextcloud.tr1ceracop.de
path: /status.php
port: 80
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
resources:
limits:
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi
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
- mountPath: /var/www/html/custom_apps
name: nextcloud-main
subPath: custom_apps
- mountPath: /var/www/tmp
name: nextcloud-main
subPath: tmp
- mountPath: /var/www/html/themes
name: nextcloud-main
subPath: themes
- mountPath: /usr/local/etc/php/conf.d/opcache.ini
name: nextcloud-phpconfig
subPath: opcache.ini
- mountPath: /usr/local/etc/php/conf.d/uploadLimit.ini
name: nextcloud-phpconfig
subPath: uploadLimit.ini
- command:
- /cron.sh
env:
- name: POSTGRES_HOST
value: nextcloud-cnpg-rw.nextcloud.svc:5432
- name: POSTGRES_DB
value: nextcloud
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
key: username
name: nextcloud-cnpg-app
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: nextcloud-cnpg-app
- name: NEXTCLOUD_ADMIN_USER
valueFrom:
secretKeyRef:
key: nextcloud-username
name: nextcloud-admin-secret
- name: NEXTCLOUD_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
key: nextcloud-password
name: nextcloud-admin-secret
- name: NEXTCLOUD_TRUSTED_DOMAINS
value: nextcloud.tr1ceracop.de
- name: OPENMETRICS_ALLOWED_CLIENTS
value: 127.0.0.1,10.42.0.0/16,10.43.0.0/16
- name: NEXTCLOUD_DATA_DIR
value: /var/www/html/data
- name: REDIS_HOST
value: nextcloud-valkey.nextcloud.svc
- name: REDIS_HOST_PORT
value: "6379"
- name: REDIS_HOST_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: nextcloud-valkey-password
- name: OBJECTSTORE_S3_SSL
value: "true"
- name: OBJECTSTORE_S3_USEPATH_STYLE
value: "true"
- name: OBJECTSTORE_S3_AUTOCREATE
value: "false"
- name: OBJECTSTORE_S3_REGION
value: nbg1
- name: OBJECTSTORE_S3_PORT
value: "443"
- name: OBJECTSTORE_S3_STORAGE_CLASS
value: STANDARD
- name: OBJECTSTORE_S3_HOST
value: nbg1.your-objectstorage.com
- name: OBJECTSTORE_S3_BUCKET
value: nextcloud-tr1ceracop
- name: OBJECTSTORE_S3_KEY
valueFrom:
secretKeyRef:
key: ACCESS_KEY_ID
name: nextcloud-s3-credentials
- name: OBJECTSTORE_S3_SECRET
valueFrom:
secretKeyRef:
key: SECRET_ACCESS_KEY
name: nextcloud-s3-credentials
- name: OBJECTSTORE_S3_SSE_C_KEY
value: ""
- name: TRUSTED_PROXIES
value: 10.0.0.0/8
- name: OVERWRITEPROTOCOL
value: https
- name: OVERWRITEHOST
value: nextcloud.tr1ceracop.de
- name: OVERWRITECLIURL
value: https://nextcloud.tr1ceracop.de
- name: NC_default_phone_region
value: DE
image: docker.io/library/nextcloud:33.0.0-fpm-alpine
imagePullPolicy: IfNotPresent
name: nextcloud-cron
resources: {}
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
- mountPath: /var/www/html/custom_apps
name: nextcloud-main
subPath: custom_apps
- mountPath: /var/www/tmp
name: nextcloud-main
subPath: tmp
- mountPath: /var/www/html/themes
name: nextcloud-main
subPath: themes
- mountPath: /usr/local/etc/php/conf.d/opcache.ini
name: nextcloud-phpconfig
subPath: opcache.ini
- mountPath: /usr/local/etc/php/conf.d/uploadLimit.ini
name: nextcloud-phpconfig
subPath: uploadLimit.ini
- image: caddy:2-alpine
livenessProbe:
httpGet:
httpHeaders:
- name: Host
value: nextcloud.tr1ceracop.de
path: /status.php
port: 80
initialDelaySeconds: 30
periodSeconds: 15
timeoutSeconds: 5
name: caddy
ports:
- containerPort: 80
name: http
protocol: TCP
readinessProbe:
httpGet:
httpHeaders:
- name: Host
value: nextcloud.tr1ceracop.de
path: /status.php
port: 80
initialDelaySeconds: 30
periodSeconds: 15
timeoutSeconds: 5
resources:
limits:
memory: 64Mi
requests:
cpu: 50m
memory: 32Mi
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
- mountPath: /var/www/html/custom_apps
name: nextcloud-main
subPath: custom_apps
- mountPath: /var/www/tmp
name: nextcloud-main
subPath: tmp
- mountPath: /var/www/html/themes
name: nextcloud-main
subPath: themes
- mountPath: /etc/caddy
name: caddy-config
securityContext:
fsGroup: 33
volumes:
- name: nextcloud-main
persistentVolumeClaim:
claimName: nextcloud-nextcloud
- configMap:
name: nextcloud-phpconfig
name: nextcloud-phpconfig
- configMap:
name: nextcloud-caddy-config
name: caddy-config

View file

@ -0,0 +1,32 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
cert-manager.io/cluster-issuer: letsencrypt
labels:
app.kubernetes.io/component: app
app.kubernetes.io/instance: nextcloud
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: nextcloud
app.kubernetes.io/version: 33.0.0
helm.sh/chart: nextcloud-9.0.4
name: nextcloud
namespace: nextcloud
spec:
ingressClassName: traefik
rules:
- host: nextcloud.tr1ceracop.de
http:
paths:
- backend:
service:
name: nextcloud
port:
number: 8080
path: /
pathType: Prefix
tls:
- hosts:
- nextcloud.tr1ceracop.de
secretName: nextcloud-tls

View file

@ -0,0 +1,48 @@
apiVersion: batch/v1
kind: Job
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
argocd.argoproj.io/sync-options: Replace=true
name: nextcloud-secret-init
namespace: nextcloud
spec:
template:
spec:
containers:
- command:
- sh
- -c
- |
set -e
if ! kubectl get secret nextcloud-admin-secret -n ${NAMESPACE} >/dev/null 2>&1; then
PASSWORD=$(head -c 32 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9' | head -c 24)
kubectl create secret generic nextcloud-admin-secret \
-n ${NAMESPACE} \
--from-literal=nextcloud-username=admin \
--from-literal=nextcloud-password="${PASSWORD}"
echo "Created nextcloud-admin-secret"
else
echo "nextcloud-admin-secret already exists, skipping"
fi
if ! kubectl get secret nextcloud-valkey-password -n ${NAMESPACE} >/dev/null 2>&1; then
VALKEY_PASSWORD=$(head -c 32 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9' | head -c 24)
kubectl create secret generic nextcloud-valkey-password \
-n ${NAMESPACE} \
--from-literal=password="${VALKEY_PASSWORD}"
echo "Created nextcloud-valkey-password"
else
echo "nextcloud-valkey-password already exists, skipping"
fi
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: alpine/k8s:1.32.3
name: init
restartPolicy: OnFailure
serviceAccountName: nextcloud-secret-init
ttlSecondsAfterFinished: 300

View file

@ -0,0 +1,9 @@
apiVersion: v1
kind: Namespace
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
pod-security.kubernetes.io/enforce: privileged
name: nextcloud
namespace: nextcloud

View file

@ -0,0 +1,22 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
helm.sh/resource-policy: keep
labels:
app.kubernetes.io/component: app
app.kubernetes.io/instance: nextcloud
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: nextcloud
app.kubernetes.io/version: 33.0.0
helm.sh/chart: nextcloud-9.0.4
name: nextcloud-nextcloud
namespace: nextcloud
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: local-path

View file

@ -0,0 +1,15 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
name: nextcloud-secret-init
namespace: nextcloud
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- create

View file

@ -0,0 +1,15 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
name: nextcloud-secret-init
namespace: nextcloud
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: nextcloud-secret-init
subjects:
- kind: ServiceAccount
name: nextcloud-secret-init
namespace: nextcloud

View file

@ -0,0 +1,20 @@
apiVersion: v1
kind: Service
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/instance: nextcloud
app.kubernetes.io/name: valkey
name: nextcloud-valkey
namespace: nextcloud
spec:
ports:
- name: valkey
port: 6379
protocol: TCP
targetPort: valkey
selector:
app.kubernetes.io/instance: nextcloud
app.kubernetes.io/name: valkey
type: ClusterIP

View file

@ -0,0 +1,26 @@
apiVersion: v1
kind: Service
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/component: app
app.kubernetes.io/instance: nextcloud
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/monitor: enabled
app.kubernetes.io/name: nextcloud
app.kubernetes.io/version: 33.0.0
helm.sh/chart: nextcloud-9.0.4
name: nextcloud
namespace: nextcloud
spec:
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 80
selector:
app.kubernetes.io/component: app
app.kubernetes.io/instance: nextcloud
app.kubernetes.io/name: nextcloud
type: ClusterIP

View file

@ -0,0 +1,7 @@
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
name: nextcloud-secret-init
namespace: nextcloud