Compare commits

...

9 Commits

Author SHA1 Message Date
e8f1185412 fixing spec issues 2026-07-03 14:00:14 -03:00
f4044715e4 editing openwebui 2026-07-03 13:55:43 -03:00
ffa4059b07 adding secrets folder 2026-07-03 13:39:53 -03:00
735d00eaf0 updating grafana 2026-07-03 13:39:16 -03:00
1c6ffc6fad adding new applications 2026-07-03 13:38:16 -03:00
b5e1276977 updating openwebui 2026-07-03 13:31:59 -03:00
df4cf4ba77 moving things around 2026-07-03 13:27:31 -03:00
5ff3589fc9 fix(notepad): override entrypoint to skip chown on NFS-mounted _tmp
The notepad container's entrypoint runs chown -R www-data:www-data
on /var/www/html/_tmp, which fails because the NFS export on nebula
uses all_squash with anonuid=65534. Override the command to skip
chown and just create the dir + copy .htaccess before starting apache.
2026-06-28 15:22:10 -03:00
63b768ebf4 removing 2nd AdGuard 2026-05-26 20:16:02 -03:00
15 changed files with 648 additions and 293 deletions

4
.gitignore vendored
View File

@@ -11,3 +11,7 @@ cronjobs
*.crt
*.key
chacal/
secrets/

View File

@@ -23,10 +23,13 @@ The repository name references my local TLD, `.haven` ;)
- Uptimekuma
- Vaultwarden
- OpenWebUI
- Paperless
- cloud
- Cloudreve
- Slink
- dns
- AdGuardHome
- AdGuardHome-2 (2nd instance)
- AdGuard-Sync
- AdGuardSync
- infra
- [Haven Notify](https://git.ivanch.me/ivanch/server-scripts/src/branch/main/haven-notify)
- Beszel

178
cloud/cloudreve.yaml Normal file
View File

@@ -0,0 +1,178 @@
# 2) Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloudreve
namespace: cloud
spec:
replicas: 1
selector:
matchLabels:
app: cloudreve
template:
metadata:
labels:
app: cloudreve
spec:
containers:
- name: cloudreve
image: cloudreve/cloudreve:v4
imagePullPolicy: Always
ports:
- containerPort: 5212
name: http
- containerPort: 6888
name: slave-tcp
protocol: TCP
- containerPort: 6888
name: slave-udp
protocol: UDP
env:
- name: CR_CONF_Database.Type
value: "postgres"
- name: CR_CONF_Database.Host
value: "postgresql.haven"
- name: CR_CONF_Database.Port
value: "5432"
- name: CR_CONF_Database.User
valueFrom:
secretKeyRef:
name: cloudreve-secret
key: DB_USER
- name: CR_CONF_Database.Name
valueFrom:
secretKeyRef:
name: cloudreve-secret
key: DB_NAME
- name: CR_CONF_Database.Password
valueFrom:
secretKeyRef:
name: cloudreve-secret
key: DB_PASSWORD
- name: CR_CONF_Database.SSLMode
value: "disable"
- name: CR_CONF_Redis.Server
value: ""
- name: CR_CONF_Redis.Password
valueFrom:
secretKeyRef:
name: cloudreve-secret
key: REDIS_PASSWORD
volumeMounts:
- name: cloudreve-data
mountPath: /cloudreve/data
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "1000m"
memory: "1Gi"
volumes:
- name: cloudreve-data
nfs:
server: 192.168.15.99
path: /export/Storage/Cloud
---
# 3) Service (HTTP)
apiVersion: v1
kind: Service
metadata:
name: cloudreve
namespace: cloud
spec:
type: ClusterIP
selector:
app: cloudreve
ports:
- port: 5212
targetPort: 5212
name: http
---
# 4) Service (Slave node / WebDAV — optional)
apiVersion: v1
kind: Service
metadata:
name: cloudreve-slave
namespace: cloud
spec:
type: ClusterIP
selector:
app: cloudreve
ports:
- port: 6888
targetPort: 6888
name: slave-tcp
protocol: TCP
- port: 6888
targetPort: 6888
name: slave-udp
protocol: UDP
---
# 5) PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cloudreve-data
namespace: cloud
annotations:
nfs.io/storage-path: "cloudreve-data"
spec:
storageClassName: "nfs-client"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
limits:
storage: 50Gi
---
# 6) Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cloudreve
namespace: cloud
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
spec:
ingressClassName: nginx
rules:
- host: cloud.haven
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: cloudreve
port:
number: 5212
---
# 7) Ingress Public
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cloudreve-public
namespace: cloud
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
spec:
ingressClassName: nginx
rules:
- host: cloud.ivanch.me
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: cloudreve
port:
number: 5212

136
cloud/slink.yaml Normal file
View File

@@ -0,0 +1,136 @@
# 1) Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: slink
namespace: cloud
spec:
replicas: 1
selector:
matchLabels:
app: slink
template:
metadata:
labels:
app: slink
spec:
containers:
- name: slink
image: anirdev/slink:latest
imagePullPolicy: Always
securityContext:
runAsUser: 1000
runAsGroup: 1000
env:
- name: PUID
value: "1000"
- name: PGID
value: "1000"
- name: ORIGIN
value: "http://slink.haven"
- name: TZ
value: "America/Sao_Paulo"
- name: USER_APPROVAL_REQUIRED
value: "true"
- name: USER_PASSWORD_MIN_LENGTH
value: "8"
- name: USER_PASSWORD_REQUIREMENTS
value: "15"
- name: ADMIN_USERNAME
valueFrom:
secretKeyRef:
name: slink-secret
key: ADMIN_USERNAME
- name: ADMIN_EMAIL
valueFrom:
secretKeyRef:
name: slink-secret
key: ADMIN_EMAIL
- name: ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: slink-secret
key: ADMIN_PASSWORD
- name: IMAGE_MAX_SIZE
value: "50M"
- name: IMAGE_STRIP_EXIF_METADATA
value: "true"
- name: IMAGE_COMPRESSION_QUALITY
value: "90"
- name: STORAGE_PROVIDER
value: "local"
ports:
- containerPort: 3000
name: slink-port
resources:
requests:
cpu: "100m"
memory: "64Mi"
limits:
cpu: "500m"
memory: "512Mi"
volumeMounts:
- name: slink-data
mountPath: /app/var/data
- name: slink-data
mountPath: /app/slink/images
volumes:
- name: slink-data
persistentVolumeClaim:
claimName: slink-data
---
# 2) Service
apiVersion: v1
kind: Service
metadata:
name: slink
namespace: cloud
spec:
type: ClusterIP
selector:
app: slink
ports:
- port: 3000
targetPort: slink-port
---
# 3) PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: slink-data
namespace: cloud
annotations:
nfs.io/storage-path: "slink-data"
spec:
storageClassName: "nfs-client"
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
limits:
storage: 15Gi
---
# 4) Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: slink
namespace: cloud
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
spec:
ingressClassName: nginx
rules:
- host: slink.haven
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: slink
port:
number: 3000

View File

@@ -26,6 +26,13 @@ spec:
secretKeyRef:
name: password
key: password
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "200m"
---
apiVersion: apps/v1
kind: Deployment
@@ -76,6 +83,13 @@ spec:
volumeMounts:
- name: archivebox-data
mountPath: /data
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "2Gi"
cpu: "3000m"
volumes:
- name: archivebox-data
persistentVolumeClaim:

View File

@@ -102,7 +102,7 @@ spec:
labels:
app.kubernetes.io/name: homepage
annotations:
configmap.reloader/checksum: "{{ include (print $.Template.BasePath \"/app/config/services.yaml\") . | sha256sum }}"
configmap.reloader/checksum: '{{ include (print $.Template.BasePath "/app/config/services.yaml") . | sha256sum }}'
spec:
serviceAccountName: homepage
automountServiceAccountToken: true
@@ -138,6 +138,13 @@ spec:
- name: homepage-config
mountPath: /app/public/images
subPath: images
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
volumes:
- name: homepage-config
persistentVolumeClaim:
@@ -167,7 +174,6 @@ metadata:
namespace: default
labels:
app.kubernetes.io/name: homepage
annotations:
spec:
type: ClusterIP
ports:
@@ -185,12 +191,6 @@ metadata:
namespace: default
labels:
app.kubernetes.io/name: homepage
# annotations:
# gethomepage.dev/description: Dynamically Detected Homepage
# gethomepage.dev/enabled: "true"
# gethomepage.dev/group: Cluster Management
# gethomepage.dev/icon: homepage.png
# gethomepage.dev/name: Homepage
spec:
ingressClassName: nginx
rules:

View File

@@ -26,6 +26,13 @@ spec:
port: 80
initialDelaySeconds: 5
periodSeconds: 10
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "200m"
---
apiVersion: v1
kind: Service

View File

@@ -19,8 +19,25 @@ spec:
- name: notepad
image: jdreinhardt/minimalist-web-notepad:latest
imagePullPolicy: Always
# The image entrypoint runs `chown -R www-data:www-data` on the NFS-mounted
# _tmp dir, which fails because the NFS export uses all_squash (anonuid=65534).
# Override the entrypoint to skip chown — ownership is handled by the NFS server.
command:
- sh
- -c
- >-
mkdir -p /var/www/html/_tmp &&
cp -n /var/www/html/notes.htaccess /var/www/html/_tmp/.htaccess 2>/dev/null;
exec docker-php-entrypoint apache2-foreground
ports:
- containerPort: 80
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
volumeMounts:
- name: notepad-data
mountPath: /var/www/html/_tmp
@@ -69,7 +86,7 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: notepad.lab
- host: notepad.haven
http:
paths:
- path: /

View File

@@ -14,12 +14,34 @@ spec:
labels:
app: openwebui
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- iris
containers:
- name: openwebui
image: ghcr.io/open-webui/open-webui:main-slim
imagePullPolicy: Always
ports:
- containerPort: 8080
env:
- name: PUID
value: "1000"
- name: PGID
value: "1000"
- name: TZ
value: "America/Sao_Paulo"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: openwebui-secret
key: DATABASE_URL
resources:
requests:
cpu: "250m"

131
default/paperless.yaml Normal file
View File

@@ -0,0 +1,131 @@
---
# 1) Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: paperless
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: paperless
template:
metadata:
labels:
app: paperless
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- iris
containers:
- name: paperless
image: ghcr.io/paperless-ngx/paperless-ngx:latest
imagePullPolicy: Always
env:
- name: PUID
value: "1000"
- name: PGID
value: "1000"
- name: PAPERLESS_URL
value: "http://paperless.haven"
- name: PAPERLESS_TIME_ZONE
value: "America/Sao_Paulo"
- name: PAPERLESS_OCR_LANGUAGE
value: "por"
- name: PAPERLESS_OCR_LANGUAGES
value: "por"
- name: PAPERLESS_OCR_USER_ARGS
value: '{"invalidate_digital_signatures": true}'
- name: PAPERLESS_DBHOST
value: postgresql.haven
- name: PAPERLESS_REDIS
value: "redis://redis.haven:6379"
- name: PAPERLESS_PORT
value: "8000"
ports:
- containerPort: 8000
name: paperless-port
resources:
requests:
cpu: "100m"
memory: "256Mi"
limits:
cpu: "4000m"
memory: "1Gi"
volumeMounts:
- name: paperless-data
subPath: data
mountPath: /usr/src/paperless/data
- name: paperless-data
subPath: media
mountPath: /usr/src/paperless/media
- name: paperless-data
subPath: export
mountPath: /usr/src/paperless/export
- name: paperless-data
subPath: consume
mountPath: /usr/src/paperless/consume
volumes:
- name: paperless-data
persistentVolumeClaim:
claimName: paperless-data
---
# 2) Service
apiVersion: v1
kind: Service
metadata:
name: paperless
namespace: default
spec:
type: ClusterIP
selector:
app: paperless
ports:
- port: 8000
targetPort: paperless-port
---
# 3) PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: paperless-data
namespace: default
annotations:
nfs.io/storage-path: "paperless-data"
spec:
storageClassName: "nfs-client"
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
limits:
storage: 15Gi
---
# 4) Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: paperless
namespace: default
spec:
ingressClassName: nginx
rules:
- host: paperless.haven
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: paperless
port:
number: 8000

View File

@@ -40,7 +40,7 @@ spec:
name: web-port
env:
- name: CRON
value: "*/2 * * * *"
value: "0 * * * *"
- name: RUN_ON_START
value: "true"
- name: LOG_LEVEL

View File

@@ -1,145 +0,0 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: adguardhome2-pvc
namespace: dns
annotations:
nfs.io/storage-path: "adguardhome2-config"
spec:
storageClassName: "nfs-client"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: adguardhome2
namespace: dns
spec:
strategy:
type: Recreate
replicas: 1
selector:
matchLabels:
app: adguardhome2
template:
metadata:
labels:
app: adguardhome2
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- iris
containers:
- name: adguardhome2
image: adguard/adguardhome:latest
imagePullPolicy: Always
ports:
- containerPort: 53
protocol: TCP
- containerPort: 53
protocol: UDP
- containerPort: 3000
protocol: TCP
name: install-port
- containerPort: 80
protocol: TCP
name: web-port
resources:
requests:
cpu: 100m
memory: 256Mi
volumeMounts:
- name: adguardhome2-storage
mountPath: /opt/adguardhome/work
- name: adguardhome2-storage
mountPath: /opt/adguardhome/conf
volumes:
- name: adguardhome2-storage
persistentVolumeClaim:
claimName: adguardhome2-pvc
---
apiVersion: v1
kind: Service
metadata:
name: adguardhome2-svc
namespace: dns
spec:
type: LoadBalancer
selector:
app: adguardhome2
loadBalancerIP: 192.168.15.201
ports:
- name: dns-tcp
port: 53
targetPort: 53
protocol: TCP
- name: dns-udp
port: 53
targetPort: 53
protocol: UDP
- name: web
port: 80
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: adguard2-install-svc
namespace: dns
spec:
type: ClusterIP
selector:
app: adguardhome2
ports:
- name: install
port: 3000
targetPort: 3000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: adguardhome2-ingress
namespace: dns
spec:
ingressClassName: nginx
rules:
- host: adguard2.haven
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: adguardhome2-svc
port:
number: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: adguardhome2-install-ingress
namespace: dns
spec:
ingressClassName: nginx
rules:
- host: install.adguard2.haven
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: adguard2-install-svc
port:
number: 3000

View File

@@ -1,44 +0,0 @@
# docker-node: iris.haven
# port: 4100
# Service
apiVersion: v1
kind: Service
metadata:
name: paperless-service
namespace: docker-ingress
spec:
ports:
- port: 80
targetPort: 4200
---
# Endpoints
apiVersion: v1
kind: Endpoints
metadata:
name: paperless-service
namespace: docker-ingress
subsets:
- addresses:
- ip: 192.168.20.100
ports:
- port: 4200
---
# Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: paperless-ingress
namespace: docker-ingress
spec:
rules:
- host: paperless.haven
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: paperless-service
port:
number: 80

View File

@@ -15,6 +15,16 @@ spec:
labels:
app: code-config
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- iris
containers:
- name: code-config
image: lscr.io/linuxserver/code-server:latest

View File

@@ -48,6 +48,9 @@ spec:
requests:
cpu: 250m
memory: 750Mi
limits:
memory: 1Gi
cpu: 500m
volumeMounts:
- mountPath: /var/lib/grafana
name: grafana-pv
@@ -103,3 +106,22 @@ spec:
name: grafana
port:
number: 3000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: monitoring
name: grafana-public
spec:
ingressClassName: nginx
rules:
- host: grafanah.ivanch.me
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: grafana
port:
number: 3000