# Plant-it - Self-hosted plant care companion # https://github.com/MDeLuise/plant-it # Version: v1.0.0 # Domain: plantit.dooplex.hu # Auth: Authentik Forward Auth (Proxy) - no native OIDC support # # Authentik Setup: # 1. Create Proxy Provider: # - Name: plantit # - External Host: https://plantit.dooplex.hu # - Mode: Forward auth (single application) # 2. Create Application linked to this provider # 3. Create Outpost (or add to existing) with this provider --- apiVersion: v1 kind: Namespace metadata: name: plantit-system labels: app.kubernetes.io/name: plantit --- apiVersion: apps/v1 kind: Deployment metadata: name: plantit-db namespace: plantit-system labels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit-db spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit-db strategy: type: Recreate template: metadata: labels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit-db spec: containers: - name: mysql image: mysql:8.4 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: plantit-db key: root-password - name: MYSQL_DATABASE valueFrom: secretKeyRef: name: plantit-db key: database - name: MYSQL_USER valueFrom: secretKeyRef: name: plantit-db key: username - name: MYSQL_PASSWORD valueFrom: secretKeyRef: name: plantit-db key: password ports: - containerPort: 3306 name: mysql resources: requests: cpu: 100m memory: 256Mi limits: cpu: 500m memory: 512Mi volumeMounts: - name: data mountPath: /var/lib/mysql livenessProbe: exec: command: - sh - -c - mysqladmin ping -u root -p$MYSQL_ROOT_PASSWORD initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: exec: command: - sh - -c - mysqladmin ping -u root -p$MYSQL_ROOT_PASSWORD initialDelaySeconds: 10 periodSeconds: 5 volumes: - name: data persistentVolumeClaim: claimName: plantit-db --- apiVersion: apps/v1 kind: Deployment metadata: name: plantit-cache namespace: plantit-system labels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit-cache spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit-cache template: metadata: labels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit-cache spec: containers: - name: redis image: redis:7.4.9 ports: - containerPort: 6379 name: redis resources: requests: cpu: 50m memory: 64Mi limits: cpu: 200m memory: 128Mi --- apiVersion: apps/v1 kind: Deployment metadata: name: plantit namespace: plantit-system labels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit app.kubernetes.io/version: "1.0.0" spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit strategy: type: Recreate template: metadata: labels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit app.kubernetes.io/version: "1.0.0" spec: containers: - name: plantit image: msdeluise/plant-it-server:0.10.0 env: # Database - name: MYSQL_HOST value: "plantit-db" - name: MYSQL_PORT value: "3306" - name: MYSQL_DATABASE valueFrom: secretKeyRef: name: plantit-db key: database - name: MYSQL_USERNAME valueFrom: secretKeyRef: name: plantit-db key: username - name: MYSQL_PSW valueFrom: secretKeyRef: name: plantit-db key: password # JWT - name: JWT_SECRET valueFrom: secretKeyRef: name: plantit-app key: jwt-secret - name: JWT_EXP value: "1" # Server config - name: API_PORT value: "8080" - name: USERS_LIMIT value: "-1" - name: UPLOAD_DIR value: "/upload-dir" - name: LOG_LEVEL value: "INFO" - name: ALLOWED_ORIGINS value: "*" # Cache - name: CACHE_TYPE value: "redis" - name: CACHE_TTL value: "86400" - name: CACHE_HOST value: "plantit-cache" - name: CACHE_PORT value: "6379" # FloraCodex API key (optional) - name: FLORACODEX_KEY value: "" ports: - containerPort: 8080 name: api - containerPort: 3000 name: frontend resources: requests: cpu: 100m memory: 256Mi limits: cpu: 500m memory: 512Mi volumeMounts: - name: uploads mountPath: /upload-dir readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 90 periodSeconds: 10 failureThreshold: 6 livenessProbe: tcpSocket: port: 8080 initialDelaySeconds: 120 periodSeconds: 30 failureThreshold: 5 volumes: - name: uploads persistentVolumeClaim: claimName: plantit-uploads --- apiVersion: v1 kind: Service metadata: name: plantit-db namespace: plantit-system labels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit-db spec: type: ClusterIP ports: - name: mysql port: 3306 targetPort: mysql selector: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit-db --- apiVersion: v1 kind: Service metadata: name: plantit-cache namespace: plantit-system labels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit-cache spec: type: ClusterIP ports: - name: redis port: 6379 targetPort: redis selector: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit-cache --- apiVersion: v1 kind: Service metadata: name: plantit namespace: plantit-system labels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit spec: type: ClusterIP ports: - name: frontend port: 3000 targetPort: frontend - name: api port: 8080 targetPort: api selector: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit --- # Ingress with Authentik forward auth apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: plantit namespace: plantit-system labels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit annotations: cert-manager.io/cluster-issuer: letsencrypt-prod external-dns.alpha.kubernetes.io/hostname: plantit.dooplex.hu,plantit.home nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/proxy-body-size: "50m" # Authentik forward auth nginx.ingress.kubernetes.io/auth-url: http://ak-outpost-plantit-outpost.auth-system.svc.cluster.local:9000/outpost.goauthentik.io/auth/nginx nginx.ingress.kubernetes.io/auth-signin: https://plantit.dooplex.hu/outpost.goauthentik.io/start?rd=$escaped_request_uri nginx.ingress.kubernetes.io/auth-snippet: | proxy_set_header X-Forwarded-Host $http_host; nginx.ingress.kubernetes.io/configuration-snippet: | set $geo_allowed 0; if ($remote_addr ~ "^192\.168\.") { set $geo_allowed 1; } if ($remote_addr ~ "^10\.") { set $geo_allowed 1; } if ($geoip2_country_code = "HU") { set $geo_allowed 1; } if ($geo_allowed = 0) { return 403 "Access restricted to Hungary"; } spec: ingressClassName: nginx-internal rules: - host: plantit.dooplex.hu http: paths: - path: / pathType: Prefix backend: service: name: plantit port: number: 3000 - path: /api pathType: Prefix backend: service: name: plantit port: number: 8080 - host: plantit.home http: paths: - path: / pathType: Prefix backend: service: name: plantit port: number: 3000 - path: /api pathType: Prefix backend: service: name: plantit port: number: 8080 tls: - hosts: - plantit.dooplex.hu secretName: plantit-tls --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: plantit-db namespace: plantit-system labels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit-db recurring-job-group.longhorn.io/needbackup: enabled recurring-job.longhorn.io/source: enabled spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: 2Gi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: plantit-uploads namespace: plantit-system labels: app.kubernetes.io/instance: plantit app.kubernetes.io/name: plantit-uploads recurring-job-group.longhorn.io/needbackup: enabled recurring-job.longhorn.io/source: enabled spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: 5Gi