flux cd refactoring enable git repo, and global resources deploy

This commit is contained in:
Márcio Fernandes
2026-07-16 19:10:49 +00:00
parent 9ff3269f3d
commit cec785f203
53 changed files with 247 additions and 154 deletions
+3
View File
@@ -0,0 +1,3 @@
**
!.gitignore
!**.example
@@ -0,0 +1,5 @@
# values bust be equal to nextcloud deployment
MARIADB_USER=????
MARIADB_PASSWORD=????
MARIADB_ROOT_PASSWORD=???
MARIADB_DATABASE=???
+94
View File
@@ -0,0 +1,94 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: nextcloud-web-public
annotations:
kubernetes.io/ingress.class: traefik-public
spec:
entryPoints:
- websecure
tls:
secretName: cloud-limbosolutions-com-tls
domains:
- main: cloud.limbosolutions.com
routes:
# AUTHENTIK OUTPOST
- match: Host(`cloud.limbosolutions.com`) && PathPrefix(`/outpost.goauthentik.io`)
kind: Rule
services:
- name: ak-outpost-authentik-embedded-outpost
namespace: id-limbosolutions-com
port: 9000
middlewares:
- name: nextcloud-security-headers
- name: rate-limit
# PUBLIC SHARES (NO SSO)
- match: Host(`cloud.limbosolutions.com`) &&
(PathPrefix(`/s/`) ||
PathPrefix(`/index.php/s/`) ||
PathPrefix(`/public.php/`) ||
PathPrefix(`/remote.php/dav/public-files/`))
kind: Rule
services:
- name: nextcloud
port: 8080
middlewares:
- name: rate-limit
- name: nextcloud-security-headers
- name: nextcloud-deny-paths
# Sync clients + mobile app (no SSO)
- match: Host(`cloud.limbosolutions.com`) &&
(PathPrefix(`/remote.php/dav`) ||
PathPrefix(`/remote.php/webdav`) ||
PathPrefix(`/remote.php/caldav`) ||
PathPrefix(`/remote.php/carddav`) ||
PathPrefix(`/ocs/v1.php`) ||
PathPrefix(`/ocs/v2.php`) ||
PathPrefix(`/status.php`) ||
PathPrefix(`/index.php/login/v2`) ||
PathPrefix(`/index.php/login/v2/poll`))
kind: Rule
services:
- name: nextcloud
port: 8080
middlewares:
- name: webdav-strip-auth
- name: rate-limit
- name: nextcloud-deny-paths
- name: nextcloud-dav
- match: Host(`cloud.limbosolutions.com`) && PathPrefix(`/whiteboard`)
kind: Rule
services:
- name: nextcloud-whiteboard
port: 3002
middlewares:
- name: nextcloud-security-headers
- name: rate-limit
- name: nextcloud-deny-paths
- name: nextcloud-wellknown
- name: nextcloud-hostmeta
- name: nextcloud-dav
- name: strip-whiteboard
# 3) EVERYTHING ELSE (SSO REQUIRED)
- match: Host(`cloud.limbosolutions.com`)
kind: Rule
services:
- name: nextcloud
port: 8080
middlewares:
# - name: authentik-forward-auth
- name: nextcloud-security-headers
- name: rate-limit
- name: nextcloud-deny-paths
- name: nextcloud-wellknown
- name: nextcloud-hostmeta
+41
View File
@@ -0,0 +1,41 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: nextcloud-web
annotations:
kubernetes.io/ingress.class: traefik
spec:
entryPoints:
- websecure
tls:
secretName: cloud-limbosolutions-com-tls
domains:
- main: cloud.limbosolutions.com
routes:
- match: Host(`cloud.limbosolutions.com`)
kind: Rule
services:
- name: nextcloud
port: 8080
middlewares:
- name: nextcloud-security-headers
- name: rate-limit
- name: nextcloud-deny-paths
- name: nextcloud-wellknown
- name: nextcloud-hostmeta
- name: nextcloud-dav
- match: Host(`cloud.limbosolutions.com`) && PathPrefix(`/whiteboard`)
kind: Rule
services:
- name: nextcloud-whiteboard
port: 3002
middlewares:
- name: nextcloud-security-headers
- name: rate-limit
- name: nextcloud-deny-paths
- name: nextcloud-wellknown
- name: nextcloud-hostmeta
- name: nextcloud-dav
- name: strip-whiteboard
+19
View File
@@ -0,0 +1,19 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
generatorOptions:
disableNameSuffixHash: true
secretGenerator:
- name: nextcloud-mariadb
envs:
- ./.env.d/nextcloud-mariadb.env
resources:
- storage-limbosolutions-com
- ./mariadb-deploy.yaml
- ./ingress-web-public.yaml
- ./ingress-web.yaml
- ./network-policies.yaml
+68
View File
@@ -0,0 +1,68 @@
apiVersion: v1
kind: Service
metadata:
name: nextcloud-mariadb
spec:
clusterIP: None
selector:
app: nextcloud-mariadb
ports:
- name: mysql
port: 3306
targetPort: 3306
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nextcloud-mariadb
spec:
serviceName: nextcloud-mariadb
replicas: 1
selector:
matchLabels:
app: nextcloud-mariadb
template:
metadata:
labels:
app: nextcloud-mariadb
spec:
containers:
- name: mariadb
image: mariadb:11.4
env:
- name: MARIADB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: nextcloud-mariadb
key: MARIADB_ROOT_PASSWORD
- name: MARIADB_USER
valueFrom:
secretKeyRef:
name: nextcloud-mariadb
key: MARIADB_USER
- name: MARIADB_PASSWORD
valueFrom:
secretKeyRef:
name: nextcloud-mariadb
key: MARIADB_PASSWORD
- name: MARIADB_DATABASE
valueFrom:
secretKeyRef:
name: nextcloud-mariadb
key: MARIADB_DATABASE
ports:
- containerPort: 3306
volumeMounts:
- name: mariadb-data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mariadb-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
+122
View File
@@ -0,0 +1,122 @@
# Strip Authorization header for WebDAV so Authentik doesn't try to interpret Basic Auth
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: webdav-strip-auth
spec:
headers:
customRequestHeaders:
Authorization: ""
---
# Rate limit to protect from brute force / bots
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: rate-limit
spec:
rateLimit:
average: 100
burst: 500
---
# Optional: security headers for UI
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: nextcloud-security-headers
spec:
headers:
browserXssFilter: true
contentTypeNosniff: true
frameDeny: false
referrerPolicy: "no-referrer"
stsSeconds: 15552000
stsIncludeSubdomains: true
stsPreload: true
customResponseHeaders:
X-Powered-By: ""
X-Content-Type-Options: "nosniff"
X-Frame-Options: "SAMEORIGIN"
X-XSS-Protection: "1; mode=block"
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: authentik-forward-auth
spec:
forwardAuth:
address: "http://ak-outpost-authentik-embedded-outpost.id-limbosolutions-com.svc.cluster.local:9000/outpost.goauthentik.io/auth/traefik"
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
- X-authentik-entitlements
- X-authentik-email
- X-authentik-name
- X-authentik-uid
- X-authentik-jwt
- X-authentik-meta-jwks
- X-authentik-meta-outpost
- X-authentik-meta-provider
- X-authentik-meta-app
- X-authentik-meta-version
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: nextcloud-deny-paths
spec:
redirectRegex:
regex: "^/(build|tests|config|lib|3rdparty|templates|data|autotest|occ|issue|indie|db_|console)"
replacement: "/"
permanent: false
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: nextcloud-dav
spec:
redirectRegex:
regex: "^/.well-known/(carddav|caldav)$"
replacement: "/remote.php/dav"
permanent: true
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: nextcloud-wellknown
spec:
redirectRegex:
regex: "^/.well-known/(webfinger|nodeinfo)$"
replacement: "/index.php/.well-known/${1}"
permanent: true
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: nextcloud-hostmeta
spec:
redirectRegex:
regex: "^/.well-known/host-meta$"
replacement: "/public.php?service=host-meta"
permanent: true
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: nextcloud-hostmeta-json
spec:
redirectRegex:
regex: "^/.well-known/host-meta.json$"
replacement: "/public.php?service=host-meta-json"
permanent: true
+27
View File
@@ -0,0 +1,27 @@
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-traefik-to-nextcloud-ingress
spec:
endpointSelector:
matchLabels:
app.kubernetes.io/name: nextcloud
ingress:
# -------------------------------------------------------------
# Allow Traefik (internal and public) to reach nextcloud web port
# -------------------------------------------------------------
- fromEndpoints:
- matchLabels:
app.kubernetes.io/name: traefik
matchExpressions:
- key: k8s:io.kubernetes.pod.namespace
operator: In
values:
- traefik
- traefik-public
toPorts:
- ports:
- port: "80"
protocol: TCP
+267
View File
@@ -0,0 +1,267 @@
image:
repository: nextcloud
flavor: apache
tag: "33"
pullPolicy: Always
replicaCount: 1
livenessProbe:
initialDelaySeconds: 60
periodSeconds: 60
timeoutSeconds: 5
failureThreshold: 6
readinessProbe:
initialDelaySeconds: 60
periodSeconds: 60
timeoutSeconds: 5
failureThreshold: 12
# ------------------------------------------------------------------------------
# Nextcloud maintenance mode & Kubernetes probes
# ------------------------------------------------------------------------------
# When performing upgrades or running `occ upgrade`, Nextcloud may return 503
# on /status.php until the database migration is complete. During this period,
# Kubernetes will repeatedly kill the pod because the readiness/liveness probes
# fail before the upgrade finishes.
#
# To prevent Kubernetes from terminating the pod during maintenance or upgrades,
# temporarily disable both probes. This allows the container to stay alive long
# enough for you to exec into it and run:
#
# php occ upgrade
#
# After the upgrade completes, reenable the probes.
#
# Example:
#
# livenessProbe:
# enabled: false
#
# readinessProbe:
# enabled: false
# ------------------------------------------------------------------------------
internalDatabase:
enabled: false
mariadb:
enabled: false
externalDatabase:
enabled: true
type: mysql
host: nextcloud-mariadb.cloud-limbosolutions-com.svc.cluster.local
user: "SET_BY_PRIVATE_VALUES"
password: "SET_BY_PRIVATE_VALUES"
database: "SET_BY_PRIVATE_VALUES"
port: 3306
persistence:
enabled: true
accessMode: ReadWriteOnce
size: 8Gi
nextcloudData:
accessMode: ReadWriteOnce
size: 8Gi
resources:
limits:
cpu: "1"
memory: 3000Mi
requests:
cpu: "0.5"
memory: 512Mi
redis:
enabled: false
## Cronjob to execute Nextcloud background tasks
## ref: https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/background_jobs_configuration.html#cron
##
cronjob:
enabled: true
nextcloud:
extraEnv:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: nextcloud-redis
key: redis-password
defaultConfigs:
redis.config.php: false
extraInitContainers:
- name: data-folder-structure-fix
image: busybox
command:
- sh
- -c
- |
# Create only parents
mkdir -p /mnt/users
mkdir -p /mnt/shared
# Fix permissions on parents pvc folder data-folder-structure
chown 33:33 /mnt/users
chown 33:33 /mnt/shared
chown 33:33 /mnt/users/marcio.fernandes
chown 33:33 /mnt/users/marcio.fernandes/Documents
chown 33:33 /mnt/users/marcio.fernandes/Photos
chown 33:33 /mnt/shared/Gaming
chown 33:33 /mnt/shared/Music
chown 33:33 /mnt/shared/Videos
chown 33:33 /mnt/shared/NerdStuff
volumeMounts:
- name: data-folder-structure
mountPath: /mnt
- name: mf-nextcloud
mountPath: /mnt/users/marcio.fernandes
- name: mf-documents
mountPath: /mnt/users/marcio.fernandes/Documents
- name: mf-photos
mountPath: /mnt/users/marcio.fernandes/Photos
- name: media-gaming
mountPath: /mnt/shared/Gaming
- name: media-music
mountPath: /mnt/shared/Music
- name: media-videos
mountPath: /mnt/shared/Videos
- name: it-storage
mountPath: /mnt/shared/NerdStuff
securityContext:
runAsUser: 33
runAsGroup: 33
fsGroup: 33
fsGroupChangePolicy: "OnRootMismatch"
phpConfigs:
php.ini: |-
memory_limit = 1024M
extraVolumes:
- name: mf-documents
persistentVolumeClaim:
claimName: nextcloud-mf-documents
- name: mf-photos
persistentVolumeClaim:
claimName: nextcloud-mf-gallery
- name: media-gaming
persistentVolumeClaim:
claimName: nextcloud-media-gaming
- name: media-music
persistentVolumeClaim:
claimName: nextcloud-media-music
- name: media-videos
persistentVolumeClaim:
claimName: nextcloud-media-videos
- name: it-storage
persistentVolumeClaim:
claimName: nextcloud-it-storage
- name: mf-nextcloud
persistentVolumeClaim:
claimName: nextcloud-mf
- name: data-folder-structure
emptyDir: {}
extraVolumeMounts:
- name: data-folder-structure
mountPath: /mnt
- name: mf-nextcloud
mountPath: /mnt/users/marcio.fernandes
- name: mf-documents
mountPath: /mnt/users/marcio.fernandes/Documents
- name: mf-photos
mountPath: /mnt/users/marcio.fernandes/Photos
- name: media-gaming
mountPath: /mnt/shared/Gaming
- name: media-music
mountPath: /mnt/shared/Music
- name: media-videos
mountPath: /mnt/shared/Videos
- name: it-storage
mountPath: /mnt/shared/NerdStuff
configs:
global.config.php: |-
<?php
$CONFIG = array (
'allow_local_remote_servers' => true,
'loglevel' => 1
);
phone.config.php: |-
<?php
$CONFIG = array (
'default_phone_region' => 'PT',
);
https.config.php: |-
<?php
$CONFIG = array (
'overwritehost' => 'cloud.limbosolutions.com',
'overwrite.cli.url' => 'https://cloud.limbosolutions.com',
'overwriteprotocol' => 'https',
'trusted_proxies' =>
array (
0 => '127.0.0.1',
1 => '::1',
2 => '10.0.0.0/8',
),
);
# A value of 1 e.g. will only run these background jobs between 01:00am UTC and 05:00am UTC:
# https://docs.nextcloud.com/server/30/admin_manual/configuration_server/background_jobs_configuration.html
maintenance.config.php: |-
<?php
$CONFIG = array (
'maintenance_window_start' => 1,
);
redis.config.php: |-
<?php
$CONFIG = array (
'memcache.local' => '\OC\Memcache\APCu',
'memcache.distributed' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => array(
'host' => 'nextcloud-redis-master',
'port' => 6379,
'timeout' => 1.5,
'password' => getenv('REDIS_PASSWORD'),
'dbindex' => 0,
),
);
onlyoffice.config.php: |-
<?php
$CONFIG = array (
'onlyoffice' =>
array (
'verify_peer_off' => true,
'allow_local_remote_servers' => true,
'allow_external_storage' => true,
),
);
ingress:
enabled: false
+9
View File
@@ -0,0 +1,9 @@
architecture: standalone
auth:
enabled: true
password: "SET_BY_PRIVATE_VALUES"
master:
persistence:
enabled: false
replica:
replicaCount: 0
@@ -0,0 +1,12 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: cloud-limbosolutions-com
resources:
- nextcloud-mf-documents.yaml
- nextcloud-mf-gallery.yaml
- nextcloud-mf.yaml
- nextcloud-media-gaming.yaml
- nextcloud-media-music.yaml
- nextcloud-media-videos.yaml
- nextcloud-it-storage.yaml
@@ -0,0 +1,33 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: nextcloud-it-storage
spec:
storageClassName: storage-limbosolutions-com
accessModes:
- ReadWriteMany
capacity:
storage: 1000Gi
csi:
driver: storage-limbosolutions-com-csi-driver
volumeHandle: nextcloud-it-storage
volumeAttributes:
collection: storage
path: /buckets/storage
volumeServerAccess: filerProxy
persistentVolumeReclaimPolicy: Retain
volumeMode: Filesystem
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nextcloud-it-storage
spec:
storageClassName: storage-limbosolutions-com
volumeName: nextcloud-it-storage
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1000Gi
@@ -0,0 +1,37 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: nextcloud-media-gaming
spec:
storageClassName: storage-limbosolutions-com
accessModes:
- ReadWriteMany
capacity:
storage: 64Gi
csi:
driver: storage-limbosolutions-com-csi-driver
volumeHandle: nextcloud-media-gaming
volumeAttributes:
collection: media.gaming
path: /buckets/media.gaming
volumeServerAccess: filerProxy
persistentVolumeReclaimPolicy: Retain
volumeMode: Filesystem
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nextcloud-media-gaming
spec:
storageClassName: storage-limbosolutions-com
volumeName: nextcloud-media-gaming
accessModes:
- ReadWriteMany
resources:
requests:
storage: 64Gi
@@ -0,0 +1,37 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: nextcloud-media-music
spec:
storageClassName: storage-limbosolutions-com
accessModes:
- ReadWriteMany
capacity:
storage: 64Gi
csi:
driver: storage-limbosolutions-com-csi-driver
volumeHandle: nextcloud-media-music
volumeAttributes:
collection: media.music
path: /buckets/media.music
volumeServerAccess: filerProxy
persistentVolumeReclaimPolicy: Retain
volumeMode: Filesystem
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nextcloud-media-music
spec:
storageClassName: storage-limbosolutions-com
volumeName: nextcloud-media-music
accessModes:
- ReadWriteMany
resources:
requests:
storage: 64Gi
@@ -0,0 +1,34 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: nextcloud-media-videos
spec:
storageClassName: storage-limbosolutions-com
accessModes:
- ReadWriteMany
capacity:
storage: 2000Gi
csi:
driver: storage-limbosolutions-com-csi-driver
volumeHandle: nextcloud-media-videos
volumeAttributes:
collection: media.videos
path: /buckets/media.videos
volumeServerAccess: filerProxy
persistentVolumeReclaimPolicy: Retain
volumeMode: Filesystem
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nextcloud-media-videos
spec:
storageClassName: storage-limbosolutions-com
volumeName: nextcloud-media-videos
accessModes:
- ReadWriteMany
resources:
requests:
storage: 64Gi
@@ -0,0 +1,35 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: nextcloud-mf-documents
spec:
storageClassName: storage-limbosolutions-com
accessModes:
- ReadWriteMany
capacity:
storage: 64Gi
csi:
driver: storage-limbosolutions-com-csi-driver
volumeHandle: nextcloud-mf-documents
volumeAttributes:
collection: mf.documents
path: /buckets/mf.documents
volumeServerAccess: filerProxy
diskType: "ssd"
persistentVolumeReclaimPolicy: Retain
volumeMode: Filesystem
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nextcloud-mf-documents
spec:
storageClassName: storage-limbosolutions-com
volumeName: nextcloud-mf-documents
accessModes:
- ReadWriteMany
resources:
requests:
storage: 64Gi
@@ -0,0 +1,33 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: nextcloud-mf-gallery
spec:
storageClassName: storage-limbosolutions-com
accessModes:
- ReadWriteMany
capacity:
storage: 64Gi
csi:
driver: storage-limbosolutions-com-csi-driver
volumeHandle: nextcloud-mf-gallery
volumeAttributes:
collection: mf.gallery
path: /buckets/mf.gallery
volumeServerAccess: filerProxy
persistentVolumeReclaimPolicy: Retain
volumeMode: Filesystem
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nextcloud-mf-gallery
spec:
storageClassName: storage-limbosolutions-com
volumeName: nextcloud-mf-gallery
accessModes:
- ReadWriteMany
resources:
requests:
storage: 64Gi
@@ -0,0 +1,33 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: nextcloud-mf
spec:
storageClassName: storage-limbosolutions-com
accessModes:
- ReadWriteMany
capacity:
storage: 64Gi
csi:
driver: storage-limbosolutions-com-csi-driver
volumeHandle: nextcloud-mf
volumeAttributes:
collection: mf.ssd.nexcloud
path: /buckets/mf.ssd.nexcloud
volumeServerAccess: filerProxy
persistentVolumeReclaimPolicy: Retain
volumeMode: Filesystem
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nextcloud-mf
spec:
storageClassName: storage-limbosolutions-com
volumeName: nextcloud-mf
accessModes:
- ReadWriteMany
resources:
requests:
storage: 64Gi