From d915d7f60b997c543dd012340fba5a7deb84a502 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Wed, 4 Mar 2026 08:33:08 +0100 Subject: [PATCH] added JARRs Dev environment --- argocd-apps/homelab.yaml | 29 +++ jarrs-system/jarr-dev.yaml | 470 +++++++++++++++++++++++++++++++++++++ 2 files changed, 499 insertions(+) create mode 100644 jarrs-system/jarr-dev.yaml diff --git a/argocd-apps/homelab.yaml b/argocd-apps/homelab.yaml index db1d8ad..df0df2a 100644 --- a/argocd-apps/homelab.yaml +++ b/argocd-apps/homelab.yaml @@ -1099,4 +1099,33 @@ spec: syncOptions: - CreateNamespace=true - ServerSideApply=true +--- +# JARR (dev environment) +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: jarr + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: homelab + source: + repoURL: https://gitea.dooplex.hu/admin/homelab-manifests.git + targetRevision: main + path: jarrs-system + destination: + server: https://kubernetes.default.svc + namespace: jarrs-system + syncPolicy: + syncOptions: + - CreateNamespace=true + - PruneLast=true + - ApplyOutOfSyncOnly=true + retry: + limit: 3 + backoff: + duration: 5s + factor: 2 + maxDuration: 3m --- \ No newline at end of file diff --git a/jarrs-system/jarr-dev.yaml b/jarrs-system/jarr-dev.yaml new file mode 100644 index 0000000..b864536 --- /dev/null +++ b/jarrs-system/jarr-dev.yaml @@ -0,0 +1,470 @@ +--- +# JARR Dev Environment +# Collaborative digital jar web application +# +# Prerequisites: +# 1. Replace placeholders in secrets below +# 2. Build and push the image: gitea.dooplex.hu/admin/jarr:dev +# +# Generate JWT secret: +# node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" +--- +apiVersion: v1 +kind: Namespace +metadata: + name: jarrs-system + labels: + app.kubernetes.io/name: jarr +--- +# Database credentials +apiVersion: v1 +kind: Secret +metadata: + name: dev-jarr-db + namespace: jarrs-system + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: postgres +type: Opaque +stringData: + username: jarr_dev + password: vz0RNgW5uhSXkByGlStp438U +--- +# Application secrets (JWT, Resend) +apiVersion: v1 +kind: Secret +metadata: + name: dev-jarr-app + namespace: jarrs-system + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: app +type: Opaque +stringData: + jwt-access-secret: ddaf79386b6614dbd2ea3f4a56b74dd785a54a30e7c0f739f86e935c12a5ab7c + resend-api-key: re_jpGHKsKL_HurdXBv57wjNnhPvcfdzH7NX +--- +# PostgreSQL PVC +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: dev-jarr-postgres + namespace: jarrs-system + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: postgres +spec: + accessModes: + - ReadWriteOnce + storageClassName: longhorn + resources: + requests: + storage: 5Gi +--- +# Redis PVC +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: dev-jarr-redis + namespace: jarrs-system + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: redis +spec: + accessModes: + - ReadWriteOnce + storageClassName: longhorn + resources: + requests: + storage: 1Gi +--- +# PostgreSQL 16 +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dev-jarr-postgres + namespace: jarrs-system + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: postgres +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: postgres + template: + metadata: + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: postgres + spec: + securityContext: + fsGroup: 999 + containers: + - name: postgres + image: postgres:16-alpine + imagePullPolicy: IfNotPresent + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: dev-jarr-db + key: username + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: dev-jarr-db + key: password + - name: POSTGRES_DB + value: jarr_dev + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + ports: + - containerPort: 5432 + name: postgres + protocol: TCP + volumeMounts: + - name: data + mountPath: /var/lib/postgresql/data + subPath: data + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: "1" + memory: 1Gi + livenessProbe: + exec: + command: + - pg_isready + - -U + - jarr_dev + initialDelaySeconds: 30 + periodSeconds: 10 + failureThreshold: 5 + timeoutSeconds: 5 + readinessProbe: + exec: + command: + - pg_isready + - -U + - jarr_dev + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 3 + timeoutSeconds: 5 + volumes: + - name: data + persistentVolumeClaim: + claimName: dev-jarr-postgres +--- +apiVersion: v1 +kind: Service +metadata: + name: dev-jarr-postgres + namespace: jarrs-system + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: postgres +spec: + type: ClusterIP + ports: + - port: 5432 + targetPort: postgres + protocol: TCP + name: postgres + selector: + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: postgres +--- +# Redis 7 +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dev-jarr-redis + namespace: jarrs-system + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: redis +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: redis + template: + metadata: + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: redis + spec: + containers: + - name: redis + image: redis:7-alpine + imagePullPolicy: IfNotPresent + args: + - redis-server + - --appendonly + - "yes" + - --maxmemory + - "64mb" + - --maxmemory-policy + - "allkeys-lru" + ports: + - containerPort: 6379 + name: redis + protocol: TCP + volumeMounts: + - name: data + mountPath: /data + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 200m + memory: 256Mi + livenessProbe: + exec: + command: + - redis-cli + - ping + initialDelaySeconds: 10 + periodSeconds: 10 + failureThreshold: 3 + timeoutSeconds: 5 + readinessProbe: + exec: + command: + - redis-cli + - ping + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 3 + timeoutSeconds: 5 + volumes: + - name: data + persistentVolumeClaim: + claimName: dev-jarr-redis +--- +apiVersion: v1 +kind: Service +metadata: + name: dev-jarr-redis + namespace: jarrs-system + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: redis +spec: + type: ClusterIP + ports: + - port: 6379 + targetPort: redis + protocol: TCP + name: redis + selector: + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: redis +--- +# JARR Application +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dev-jarr + namespace: jarrs-system + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: app +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: app + template: + metadata: + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: app + spec: + initContainers: + - name: wait-for-db + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for PostgreSQL..." + until nc -z dev-jarr-postgres 5432; do + echo "PostgreSQL not ready, waiting..." + sleep 2 + done + echo "PostgreSQL is ready!" + - name: wait-for-redis + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for Redis..." + until nc -z dev-jarr-redis 6379; do + echo "Redis not ready, waiting..." + sleep 2 + done + echo "Redis is ready!" + containers: + - name: jarr + image: gitea.dooplex.hu/admin/jarr:dev + imagePullPolicy: Always + env: + - name: NODE_ENV + value: development + - name: PORT + value: "3000" + - name: BASE_URL + value: "https://dev.jarrs.eu" + - name: WEB_URL + value: "https://dev.jarrs.eu" + # Database + - name: DB_USER + valueFrom: + secretKeyRef: + name: dev-jarr-db + key: username + - name: DB_PASS + valueFrom: + secretKeyRef: + name: dev-jarr-db + key: password + - name: DATABASE_URL + value: "postgresql://$(DB_USER):$(DB_PASS)@dev-jarr-postgres:5432/jarr_dev" + # Redis + - name: REDIS_URL + value: "redis://dev-jarr-redis:6379" + # JWT + - name: JWT_ACCESS_SECRET + valueFrom: + secretKeyRef: + name: dev-jarr-app + key: jwt-access-secret + - name: JWT_ACCESS_EXPIRES_IN + value: "15m" + - name: JWT_REFRESH_EXPIRES_IN + value: "30d" + # Email (Resend) + - name: RESEND_API_KEY + valueFrom: + secretKeyRef: + name: dev-jarr-app + key: resend-api-key + - name: EMAIL_FROM + value: "noreply@jarrs.eu" + # Rate limiting + - name: RATE_LIMIT_ENABLED + value: "false" + ports: + - containerPort: 3000 + name: http + protocol: TCP + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: "1" + memory: 1Gi + startupProbe: + httpGet: + path: /v1/health + port: http + periodSeconds: 10 + failureThreshold: 30 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /v1/health + port: http + initialDelaySeconds: 10 + periodSeconds: 10 + failureThreshold: 3 + timeoutSeconds: 5 + livenessProbe: + httpGet: + path: /v1/health + port: http + initialDelaySeconds: 30 + periodSeconds: 30 + failureThreshold: 5 + timeoutSeconds: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: dev-jarr + namespace: jarrs-system + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: app +spec: + type: ClusterIP + ports: + - port: 3000 + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: app +--- +# Ingress +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: dev-jarr + namespace: jarrs-system + labels: + app.kubernetes.io/name: jarr + app.kubernetes.io/instance: dev-jarr + app.kubernetes.io/component: app + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + external-dns.alpha.kubernetes.io/hostname: dev.jarrs.eu + nginx.ingress.kubernetes.io/ssl-redirect: "true" +spec: + ingressClassName: nginx-internal + rules: + - host: dev.jarrs.eu + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: dev-jarr + port: + number: 3000 + tls: + - hosts: + - dev.jarrs.eu + secretName: dev-jarr-tls