Adopt ten more services with Argo CD

This commit is contained in:
2026-10-18 15:54:12 +02:00
parent 995db7827c
commit 10415437be
50 changed files with 1288 additions and 0 deletions
+6
View File
@@ -16,6 +16,12 @@ container images and then commits the selected image tag here; it never receives
`apps/immich-crack/`, `apps/pfostendynamics-com/`, and
`apps/watschn-studio/` pin the shared PHP homepage chart and reference their
existing CephFS content claims.
- `apps/brunner-ninja/`, `apps/flaresolverr/`, `apps/ombi/`,
`apps/tautulli/`, `apps/uptime-kuma/`, and `apps/wiki-js/` pin their existing
upstream chart releases and cluster values.
- `apps/mosquitto/` and `apps/visual-studio-code/` preserve their small local
manifest contracts; `apps/artcraft/` and `apps/coturn/` use local adapter
charts for their repeated or multi-resource third-party integrations.
- `bootstrap/` contains Argo CD projects and Applications, including the
upstream Sealed Secrets controller and the five PHP sites above.
- `scripts/update-immich-sync-image.sh` is the single image-promotion interface used by CI.
+4
View File
@@ -0,0 +1,4 @@
apiVersion: v2
name: artcraft-homelab
type: application
version: 0.1.0
+45
View File
@@ -0,0 +1,45 @@
"""Download and unpack an official, versioned upstream web bundle."""
import os
from pathlib import Path
import shutil
import tempfile
import time
import urllib.request
import zipfile
url = os.environ["RELEASE_URL"]
if not url.startswith("https://github.com/storytold/"):
raise ValueError("Expected an official storytold GitHub release URL")
with tempfile.TemporaryDirectory() as tmp:
archive = Path(tmp) / "release.zip"
for attempt in range(4):
try:
with urllib.request.urlopen(url, timeout=120) as response, archive.open("wb") as out:
shutil.copyfileobj(response, out)
break
except Exception:
if attempt == 3:
raise
time.sleep(2 ** attempt)
unpacked = Path(tmp) / "unpacked"
with zipfile.ZipFile(archive) as bundle:
for member in bundle.infolist():
path = Path(member.filename)
if path.is_absolute() or ".." in path.parts or (member.external_attr >> 16) & 0o170000 == 0o120000:
raise ValueError(f"Unsafe archive entry: {path}")
bundle.extractall(unpacked)
roots = [p.parent for p in unpacked.glob("*/index.html")]
if (unpacked / "index.html").exists():
roots = [unpacked]
if len(roots) != 1:
raise ValueError("Expected exactly one web root")
if not any(roots[0].rglob("*.wasm")) and not any(roots[0].rglob("*.part-*")):
raise ValueError("Missing WebAssembly payload")
# Kubernetes owns the emptyDir root; do not try to chmod that directory.
for source in roots[0].iterdir():
target = Path("/srv/web") / source.name
if source.is_dir():
shutil.copytree(source, target, dirs_exist_ok=True)
else:
shutil.copy2(source, target)
print(f"Installed {url}", flush=True)
+37
View File
@@ -0,0 +1,37 @@
worker_processes auto;
pid /tmp/nginx.pid;
error_log /dev/stderr warn;
events { worker_connections 1024; }
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /dev/stdout;
client_body_temp_path /tmp/client_temp;
proxy_temp_path /tmp/proxy_temp;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
sendfile on;
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types application/wasm application/javascript text/javascript application/octet-stream text/css application/json;
server {
listen 8080;
root /srv/web;
index index.html;
add_header X-Content-Type-Options nosniff always;
# Some upstream apps use stable filenames. Revalidation prevents stale builds.
add_header Cache-Control no-cache always;
location / { try_files $uri $uri/ =404; }
location ~ /\. { deny all; }
location = /_headers { deny all; }
location = /nginx_status { return 404; }
}
server {
listen 127.0.0.1:8081;
access_log off;
location = /nginx_status { stub_status; }
location / { return 404; }
}
}
+243
View File
@@ -0,0 +1,243 @@
{{- range .Values.apps }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .name }}
namespace: {{ $.Release.Namespace }}
labels:
app.kubernetes.io/name: {{ .name }}
app.kubernetes.io/part-of: artcraft
spec:
replicas: 1
revisionHistoryLimit: 3
progressDeadlineSeconds: 900
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app.kubernetes.io/name: {{ .name }}
app.kubernetes.io/part-of: artcraft
template:
metadata:
labels:
app.kubernetes.io/name: {{ .name }}
app.kubernetes.io/part-of: artcraft
annotations:
artcraft.brunner.ninja/version: {{ .version | quote }}
spec:
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 101
runAsGroup: 101
fsGroup: 101
seccompProfile:
type: RuntimeDefault
initContainers:
- name: download-release
image: {{ $.Values.images.downloader }}
command: [python, /config/download.py]
env:
- name: RELEASE_URL
value: {{ .releaseUrl | quote }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
resources:
requests:
cpu: 25m
memory: 64Mi
limits:
cpu: "1"
memory: 512Mi
volumeMounts:
- name: web
mountPath: /srv/web
- name: config
mountPath: /config
readOnly: true
- name: tmp
mountPath: /tmp
containers:
- name: nginx
image: {{ $.Values.images.nginx }}
command: [nginx, -g, "daemon off;", -c, /config/nginx.conf]
ports:
- name: http
containerPort: 8080
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 500m
memory: 128Mi
startupProbe:
httpGet:
path: /index.html
port: http
periodSeconds: 2
timeoutSeconds: 2
failureThreshold: 30
readinessProbe:
httpGet:
path: /index.html
port: http
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /index.html
port: http
periodSeconds: 15
timeoutSeconds: 2
failureThreshold: 3
volumeMounts:
- name: web
mountPath: /srv/web
readOnly: true
- name: config
mountPath: /config
readOnly: true
- name: tmp
mountPath: /tmp
- name: nginx-exporter
image: {{ $.Values.images.exporter }}
args:
- --nginx.scrape-uri=http://127.0.0.1:8081/nginx_status
ports:
- name: metrics
containerPort: 9113
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
resources:
requests:
cpu: 5m
memory: 16Mi
limits:
cpu: 100m
memory: 64Mi
startupProbe:
httpGet:
path: /metrics
port: metrics
periodSeconds: 2
timeoutSeconds: 2
failureThreshold: 30
readinessProbe:
httpGet:
path: /metrics
port: metrics
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /metrics
port: metrics
periodSeconds: 20
timeoutSeconds: 2
failureThreshold: 3
volumes:
- name: web
emptyDir:
sizeLimit: 1Gi
- name: tmp
emptyDir:
sizeLimit: 1Gi
- name: config
configMap:
name: {{ $.Values.configMapName }}
nodeSelector:
odroid-h3: enabled
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
nodeTaintsPolicy: Honor
labelSelector:
matchLabels:
app.kubernetes.io/part-of: artcraft
---
apiVersion: v1
kind: Service
metadata:
name: {{ .name }}
namespace: {{ $.Release.Namespace }}
labels:
app.kubernetes.io/name: {{ .name }}
app.kubernetes.io/part-of: artcraft
spec:
selector:
app.kubernetes.io/name: {{ .name }}
app.kubernetes.io/part-of: artcraft
ports:
- name: http
port: 80
targetPort: http
- name: metrics
port: 9113
targetPort: metrics
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .name }}
namespace: {{ $.Release.Namespace }}
labels:
app.kubernetes.io/name: {{ .name }}
app.kubernetes.io/part-of: artcraft
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
tls:
- hosts:
- {{ .host }}
rules:
- host: {{ .host }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ .name }}
port:
name: http
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ .name }}
namespace: {{ $.Release.Namespace }}
labels:
app.kubernetes.io/name: {{ .name }}
app.kubernetes.io/part-of: artcraft
spec:
selector:
matchLabels:
app.kubernetes.io/name: {{ .name }}
app.kubernetes.io/part-of: artcraft
endpoints:
- port: metrics
path: /metrics
interval: 30s
scrapeTimeout: 10s
---
{{- end }}
+10
View File
@@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Values.configMapName }}
namespace: {{ .Release.Namespace }}
data:
nginx.conf: |
{{ .Files.Get "files/nginx.conf" | indent 4 }}
download.py: |
{{ .Files.Get "files/download.py" | indent 4 }}
+4
View File
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: {{ .Release.Namespace }}
+58
View File
@@ -0,0 +1,58 @@
configMapName: artcraft-config-4h2gh76d48
images:
downloader: docker.io/library/python:3.13-alpine
nginx: docker.io/library/nginx:1.30.6-alpine
exporter: docker.io/nginx/nginx-prometheus-exporter:1.5.3
apps:
- name: cadcraft
version: v0.7.0
releaseUrl: https://github.com/storytold/cadcraft/releases/download/v0.7.0/cadcraft-web-0.7.0.zip
host: autocad.brunner.ninja
- name: deckcraft
version: v0.7.0
releaseUrl: https://github.com/storytold/deckcraft/releases/download/v0.7.0/deckcraft-web-0.7.0.zip
host: powerpoint.brunner.ninja
- name: designcraft
version: v0.8.0
releaseUrl: https://github.com/storytold/designcraft/releases/download/v0.8.0/designcraft-web-0.8.0.zip
host: indesign.brunner.ninja
- name: effectcraft
version: v0.10.0
releaseUrl: https://github.com/storytold/effectcraft/releases/download/v0.10.0/effectcraft-web-0.10.0.zip
host: aftereffects.brunner.ninja
- name: figcraft
version: v0.6.0
releaseUrl: https://github.com/storytold/figcraft/releases/download/v0.6.0/figcraft-web-0.6.0.zip
host: figma.brunner.ninja
- name: filmcraft
version: v0.8.0
releaseUrl: https://github.com/storytold/filmcraft/releases/download/v0.8.0/filmcraft-web-0.8.0.zip
host: premiere.brunner.ninja
- name: gridcraft
version: v0.7.0
releaseUrl: https://github.com/storytold/gridcraft/releases/download/v0.7.0/gridcraft-web-0.7.0.zip
host: excel.brunner.ninja
- name: lightcraft
version: v0.8.0
releaseUrl: https://github.com/storytold/lightcraft/releases/download/v0.8.0/lightcraft-web-0.8.0.zip
host: lightroom.brunner.ninja
- name: pdfcraft
version: v0.8.0
releaseUrl: https://github.com/storytold/pdfcraft/releases/download/v0.8.0/pdfcraft-web-0.8.0.zip
host: acrobat.brunner.ninja
- name: photocraft
version: v0.9.0
releaseUrl: https://github.com/storytold/photocraft/releases/download/v0.9.0/photocraft-web-0.9.0.zip
host: photoshop.brunner.ninja
- name: soundcraft
version: v0.7.0
releaseUrl: https://github.com/storytold/soundcraft/releases/download/v0.7.0/soundcraft-web-0.7.0.zip
host: protools.brunner.ninja
- name: vectorcraft
version: v0.12.0
releaseUrl: https://github.com/storytold/vectorcraft/releases/download/v0.12.0/vectorcraft-web-0.12.0.zip
host: illustrator.brunner.ninja
- name: wordcraft
version: v0.7.0
releaseUrl: https://github.com/storytold/wordcraft/releases/download/v0.7.0/wordcraft-web-0.7.0.zip
host: word.brunner.ninja
+2
View File
@@ -0,0 +1,2 @@
Chart.lock
charts/
+8
View File
@@ -0,0 +1,8 @@
apiVersion: v2
name: brunner-ninja
type: application
version: 0.1.0
dependencies:
- name: php-homepage
version: 0.10.1
repository: https://brunner.ninja/charts
+23
View File
@@ -0,0 +1,23 @@
php-homepage:
fullnameOverride: brunner-ninja
apache:
serverAdmin: daniel@brunner.ninja
metrics:
enabled: true
serviceMonitor:
enabled: true
prometheusRule:
enabled: true
persistence:
existingClaim: brunner-ninja
ingress:
enabled: true
hosts:
- host: brunner.ninja
paths:
- path: /
pathType: Prefix
tls:
- hosts:
- brunner.ninja
secretName: brunner-ninja-tls
+4
View File
@@ -0,0 +1,4 @@
apiVersion: v2
name: coturn-homelab
type: application
version: 0.1.0
+4
View File
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: {{ .Release.Namespace }}
+54
View File
@@ -0,0 +1,54 @@
{{- range $protocol := list "tcp" "udp" }}
apiVersion: v1
kind: Service
metadata:
name: coturn-{{ $protocol }}
namespace: {{ $.Release.Namespace }}
labels:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
annotations:
metallb.io/loadBalancerIPs: {{ $.Values.loadBalancerIP | quote }}
metallb.io/allow-shared-ip: coturn
mikrotik.brunner.ninja/router: newgw
mikrotik.brunner.ninja/forwardings: {{ if eq $protocol "tcp" }}'[{"name":"3478-tcp","servicePort":"tcp","dstAddressList":"WANs"},{"name":"5349-tcp","servicePort":"tcp-tls","dstAddressList":"WANs"}]'{{ else }}'[{"name":"3478-udp","servicePort":"udp","dstAddressList":"WANs"},{"name":"5349-udp","servicePort":"udp-tls","dstAddressList":"WANs"}]'{{ end }}
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
ports:
- name: {{ $protocol }}
port: 3478
targetPort: {{ $protocol }}
protocol: {{ upper $protocol }}
- name: {{ $protocol }}-tls
port: 5349
targetPort: {{ $protocol }}-tls
protocol: {{ upper $protocol }}
---
{{- end }}
apiVersion: v1
kind: Service
metadata:
name: coturn-relay
namespace: {{ .Release.Namespace }}
annotations:
metallb.io/loadBalancerIPs: {{ .Values.loadBalancerIP | quote }}
metallb.io/allow-shared-ip: coturn
mikrotik.brunner.ninja/router: newgw
mikrotik.brunner.ninja/forwardings: '[{"name":"relay-udp","servicePortRange":"{{ .Values.relay.minPort }}-{{ .Values.relay.maxPort }}","dstAddressList":"WANs"}]'
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app.kubernetes.io/instance: coturn
app.kubernetes.io/name: coturn
ports:
{{- range $port := untilStep (int .Values.relay.minPort) (int (add1 .Values.relay.maxPort)) 1 }}
- name: relay-{{ $port }}
port: {{ $port }}
targetPort: {{ $port }}
protocol: UDP
{{- end }}
+137
View File
@@ -0,0 +1,137 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: coturn
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
automountServiceAccountToken: false
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: coturn
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
app.kubernetes.io/version: {{ .Values.image.tag | quote }}
spec:
replicas: 1
revisionHistoryLimit: 3
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
template:
metadata:
labels:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
spec:
serviceAccountName: coturn
automountServiceAccountToken: false
containers:
- name: coturn
image: {{ printf "%s:%s" .Values.image.repository .Values.image.tag }}
imagePullPolicy: IfNotPresent
args:
- --listening-port=3478
- --tls-listening-port=5349
- --fingerprint
- --cert=/etc/ssl/certs/cert.pem
- --pkey=/etc/ssl/private/privkey.pem
- --realm={{ .Values.realm }}
- --log-file=stdout
- --no-software-attribute
- --no-cli
- --use-auth-secret
- --static-auth-secret=$(TURN_SHARED_SECRET)
- --external-ip={{ .Values.externalIP }}
- --min-port={{ .Values.relay.minPort }}
- --max-port={{ .Values.relay.maxPort }}
- --no-multicast-peers
env:
- name: TURN_SHARED_SECRET
valueFrom:
secretKeyRef:
name: {{ .Values.sharedSecret.name }}
key: {{ .Values.sharedSecret.key }}
ports:
- name: tcp
containerPort: 3478
protocol: TCP
- name: udp
containerPort: 3478
protocol: UDP
- name: tcp-tls
containerPort: 5349
protocol: TCP
- name: udp-tls
containerPort: 5349
protocol: UDP
readinessProbe:
tcpSocket:
port: tcp
livenessProbe:
tcpSocket:
port: tcp
initialDelaySeconds: 30
resources:
requests:
cpu: 100m
memory: 50Mi
limits:
cpu: 100m
memory: 50Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
add: [NET_BIND_SERVICE]
drop: [ALL]
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65534
volumeMounts:
- name: certs
mountPath: /etc/ssl/certs
readOnly: true
- name: private
mountPath: /etc/ssl/private
readOnly: true
volumes:
- name: certs
secret:
secretName: {{ .Values.certificate.secretName }}
items:
- key: tls.crt
path: cert.pem
- name: private
secret:
secretName: {{ .Values.certificate.secretName }}
items:
- key: tls.key
path: privkey.pem
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: coturn
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
spec:
secretName: {{ .Values.certificate.secretName }}
dnsNames:
- {{ .Values.certificate.dnsName }}
issuerRef:
group: cert-manager.io
kind: ClusterIssuer
name: {{ .Values.certificate.issuerName }}
usages:
- digital signature
- key encipherment
+16
View File
@@ -0,0 +1,16 @@
image:
repository: coturn/coturn
tag: 4.10.0-r1
realm: brunner.ninja
externalIP: 37.186.4.16
loadBalancerIP: 192.168.0.19
relay:
minPort: 49160
maxPort: 49200
sharedSecret:
name: turn-shared-secret
key: shared-secret
certificate:
secretName: coturn
dnsName: brunner.ninja
issuerName: letsencrypt-dns
+2
View File
@@ -0,0 +1,2 @@
Chart.lock
charts/
+8
View File
@@ -0,0 +1,8 @@
apiVersion: v2
name: flaresolverr-homelab
type: application
version: 0.1.0
dependencies:
- name: flaresolverr
version: 6.2.0
repository: https://k8s-home-lab.github.io/helm-charts/
+13
View File
@@ -0,0 +1,13 @@
flaresolverr:
image:
tag: v3.5.2
ingress:
main:
enabled: true
ingressClassName: traefik
hosts:
- host: flaresolverr.brunner.ninja
paths:
- path: /
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
+4
View File
@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- resources.yaml
+54
View File
@@ -0,0 +1,54 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: mosquitto-config
data:
mosquitto.conf: |
listener 1883
allow_anonymous true
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mosquitto
spec:
selector:
matchLabels:
app: mosquitto
template:
metadata:
labels:
app: mosquitto
spec:
containers:
- name: mosquitto
image: eclipse-mosquitto:latest
imagePullPolicy: Always
ports:
- name: mqtt
containerPort: 1883
volumeMounts:
- name: mosquitto-config
mountPath: /mosquitto/config/mosquitto.conf
subPath: mosquitto.conf
volumes:
- name: mosquitto-config
configMap:
name: mosquitto-config
imagePullSecrets:
- name: quay-pull-secret
---
apiVersion: v1
kind: Service
metadata:
name: mosquitto
spec:
ports:
- name: mqtt
port: 1883
protocol: TCP
targetPort: 1883
selector:
app: mosquitto
type: LoadBalancer
loadBalancerIP: 192.168.0.11
+2
View File
@@ -0,0 +1,2 @@
Chart.lock
charts/
+8
View File
@@ -0,0 +1,8 @@
apiVersion: v2
name: ombi-homelab
type: application
version: 0.1.0
dependencies:
- name: ombi
version: 12.2.1
repository: https://k8s-home-lab.github.io/helm-charts/
+22
View File
@@ -0,0 +1,22 @@
ombi:
image:
tag: 4.53.10
env:
TZ: Europe/Vienna
ingress:
main:
enabled: true
ingressClassName: traefik
hosts:
- host: ombi.brunner.ninja
paths:
- path: /
annotations:
traefik.ingress.kubernetes.io/router.middlewares: default-authentik@kubernetescrd
traefik.ingress.kubernetes.io/router.entrypoints: websecure
persistence:
config:
enabled: true
size: 1Gi
storageClass: rook-ceph-block
accessMode: ReadWriteOnce
+2
View File
@@ -0,0 +1,2 @@
Chart.lock
charts/
+8
View File
@@ -0,0 +1,8 @@
apiVersion: v2
name: tautulli-homelab
type: application
version: 0.1.0
dependencies:
- name: tautulli
version: 12.3.0
repository: https://k8s-home-lab.github.io/helm-charts/
+33
View File
@@ -0,0 +1,33 @@
tautulli:
image:
repository: lscr.io/linuxserver/tautulli
tag: 2.18.2
env:
TZ: Europe/Vienna
ingress:
main:
enabled: true
ingressClassName: traefik
service:
name: main
port: http
hosts:
- host: tautulli.brunner.ninja
paths:
- path: /
pathType: Prefix
annotations:
traefik.ingress.kubernetes.io/router.middlewares: default-authentik@kubernetescrd
traefik.ingress.kubernetes.io/router.entrypoints: websecure
service:
main:
enabled: true
ports:
http:
port: 8181
persistence:
config:
enabled: true
size: 60Gi
storageClass: rook-ceph-block
accessMode: ReadWriteOnce
+2
View File
@@ -0,0 +1,2 @@
Chart.lock
charts/
+8
View File
@@ -0,0 +1,8 @@
apiVersion: v2
name: uptime-kuma-homelab
type: application
version: 0.1.0
dependencies:
- name: uptime-kuma
version: 4.2.0
repository: https://helm.irsigler.cloud
+31
View File
@@ -0,0 +1,31 @@
uptime-kuma:
image:
pullPolicy: Always
tag: 2.5.6-rootless
imagePullSecrets:
- name: quay-pull-secret
ingress:
enabled: true
className: traefik
annotations:
traefik.ingress.kubernetes.io/router.middlewares: default-authentik@kubernetescrd
traefik.ingress.kubernetes.io/router.entrypoints: websecure
hosts:
- host: status.brunner.ninja
paths:
- path: /
pathType: ImplementationSpecific
volume:
storageClassName: rook-ceph-block
strategy:
type: Recreate
readinessProbe:
timeoutSeconds: 5
resources:
requests:
cpu: 100m
memory: 256Mi
ephemeral-storage: 128Mi
limits:
memory: 1Gi
ephemeral-storage: 1Gi
@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- resources.yaml
+105
View File
@@ -0,0 +1,105 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: visual-studio-code
spec:
selector:
matchLabels:
app: visual-studio-code
template:
metadata:
labels:
app: visual-studio-code
spec:
containers:
- name: visual-studio-code
image: ghcr.io/coder/code-server:4.141.0
imagePullPolicy: IfNotPresent
args: [--auth, none]
ports:
- name: http
containerPort: 8080
startupProbe:
httpGet:
path: /healthz
port: http
failureThreshold: 30
periodSeconds: 2
readinessProbe:
httpGet:
path: /healthz
port: http
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: http
periodSeconds: 30
volumeMounts:
- name: brgkepler-com
mountPath: /home/coder/brgkepler-com
- name: brunner-ninja
mountPath: /home/coder/brunner-ninja
- name: gschissenes-equipment
mountPath: /home/coder/gschissenes-equipment
- name: immich-crack
mountPath: /home/coder/immich-crack
- name: pfostendynamics-com
mountPath: /home/coder/pfostendynamics-com
- name: watschn-studio
mountPath: /home/coder/watschn-studio
volumes:
- name: brgkepler-com
persistentVolumeClaim:
claimName: brgkepler-com
- name: brunner-ninja
persistentVolumeClaim:
claimName: brunner-ninja
- name: gschissenes-equipment
persistentVolumeClaim:
claimName: gschissenes-equipment
- name: immich-crack
persistentVolumeClaim:
claimName: immich-crack
- name: pfostendynamics-com
persistentVolumeClaim:
claimName: pfostendynamics-com
- name: watschn-studio
persistentVolumeClaim:
claimName: watschn-studio
imagePullSecrets:
- name: quay-pull-secret
---
apiVersion: v1
kind: Service
metadata:
name: visual-studio-code
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
selector:
app: visual-studio-code
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: visual-studio-code
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.middlewares: default-authentik@kubernetescrd
spec:
ingressClassName: traefik
rules:
- host: dev.brunner.ninja
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: visual-studio-code
port:
name: http
+2
View File
@@ -0,0 +1,2 @@
Chart.lock
charts/
+8
View File
@@ -0,0 +1,8 @@
apiVersion: v2
name: wiki-js-homelab
type: application
version: 0.1.0
dependencies:
- name: wiki
version: 3.0.0
repository: https://charts.js.wiki
+28
View File
@@ -0,0 +1,28 @@
wiki:
imagePullSecrets:
- name: quay-pull-secret
image:
repository: docker.io/requarks/wiki
tag: 2.5.316
ingress:
enabled: true
className: traefik
hosts:
- host: wiki.brunner.ninja
paths:
- path: /
pathType: Prefix
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
postgresql:
enabled: false
persistence:
enabled: false
externalPostgresql:
host: postgresql.default.svc.cluster.local
port: "5432"
database: wikijs
username: wikijs
existingSecret: wiki-js
existingSecretKey: postgresql-password
ssl: false
+26
View File
@@ -0,0 +1,26 @@
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: artcraft
namespace: argocd
spec:
description: Stateless Artcraft web applications
sourceRepos:
- https://code.brunner.ninja/feedc0de/homelab-gitops.git
destinations:
- namespace: artcraft
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ""
kind: Namespace
namespaceResourceWhitelist:
- group: ""
kind: ConfigMap
- group: ""
kind: Service
- group: apps
kind: Deployment
- group: networking.k8s.io
kind: Ingress
- group: monitoring.coreos.com
kind: ServiceMonitor
+21
View File
@@ -0,0 +1,21 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: artcraft
namespace: argocd
spec:
project: artcraft
source:
repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
path: apps/artcraft
helm:
releaseName: artcraft
destination:
server: https://kubernetes.default.svc
namespace: artcraft
syncPolicy:
automated:
enabled: true
prune: false
selfHeal: true
+21
View File
@@ -0,0 +1,21 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: brunner-ninja
namespace: argocd
spec:
project: homelab
source:
repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
path: apps/brunner-ninja
helm:
releaseName: brunner-ninja
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
enabled: true
prune: false
selfHeal: true
+24
View File
@@ -0,0 +1,24 @@
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: coturn
namespace: argocd
spec:
description: Coturn relay and certificate resources
sourceRepos:
- https://code.brunner.ninja/feedc0de/homelab-gitops.git
destinations:
- namespace: coturn
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ""
kind: Namespace
namespaceResourceWhitelist:
- group: ""
kind: Service
- group: ""
kind: ServiceAccount
- group: apps
kind: Deployment
- group: cert-manager.io
kind: Certificate
+21
View File
@@ -0,0 +1,21 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: coturn
namespace: argocd
spec:
project: coturn
source:
repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
path: apps/coturn
helm:
releaseName: coturn
destination:
server: https://kubernetes.default.svc
namespace: coturn
syncPolicy:
automated:
enabled: true
prune: false
selfHeal: true
+21
View File
@@ -0,0 +1,21 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: flaresolverr
namespace: argocd
spec:
project: homelab
source:
repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
path: apps/flaresolverr
helm:
releaseName: flaresolverr
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
enabled: true
prune: false
selfHeal: true
+19
View File
@@ -55,3 +55,22 @@ do
--for=jsonpath='{.status.health.status}'=Healthy \
--timeout=5m
done
for application in \
artcraft \
brunner-ninja \
coturn \
flaresolverr \
mosquitto \
ombi \
tautulli \
uptime-kuma \
visual-studio-code \
wiki-js
do
kubectl --namespace argocd wait "application/${application}" \
--for=jsonpath='{.status.sync.status}'=Synced \
--timeout=15m
kubectl --namespace argocd wait "application/${application}" \
--for=jsonpath='{.status.health.status}'=Healthy \
--timeout=15m
done
+12
View File
@@ -15,3 +15,15 @@ resources:
- immich-crack.yaml
- pfostendynamics-com.yaml
- watschn-studio.yaml
- artcraft-project.yaml
- coturn-project.yaml
- artcraft.yaml
- brunner-ninja.yaml
- coturn.yaml
- flaresolverr.yaml
- mosquitto.yaml
- ombi.yaml
- tautulli.yaml
- uptime-kuma.yaml
- visual-studio-code.yaml
- wiki-js.yaml
+19
View File
@@ -0,0 +1,19 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: mosquitto
namespace: argocd
spec:
project: homelab
source:
repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
path: apps/mosquitto
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
enabled: true
prune: false
selfHeal: true
+21
View File
@@ -0,0 +1,21 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: ombi
namespace: argocd
spec:
project: homelab
source:
repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
path: apps/ombi
helm:
releaseName: ombi
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
enabled: true
prune: false
selfHeal: true
+2
View File
@@ -17,6 +17,8 @@ spec:
kind: PersistentVolumeClaim
- group: ""
kind: Service
- group: ""
kind: ServiceAccount
- group: apps
kind: Deployment
- group: networking.k8s.io
+21
View File
@@ -0,0 +1,21 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: tautulli
namespace: argocd
spec:
project: homelab
source:
repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
path: apps/tautulli
helm:
releaseName: tautulli
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
enabled: true
prune: false
selfHeal: true
+21
View File
@@ -0,0 +1,21 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: uptime-kuma
namespace: argocd
spec:
project: homelab
source:
repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
path: apps/uptime-kuma
helm:
releaseName: uptime-kuma
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
enabled: true
prune: false
selfHeal: true
+19
View File
@@ -0,0 +1,19 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: visual-studio-code
namespace: argocd
spec:
project: homelab
source:
repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
path: apps/visual-studio-code
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
enabled: true
prune: false
selfHeal: true
+21
View File
@@ -0,0 +1,21 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: wiki-js
namespace: argocd
spec:
project: homelab
source:
repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
path: apps/wiki-js
helm:
releaseName: wiki-js
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
enabled: true
prune: false
selfHeal: true