Index: k8s/backend.yaml
===================================================================
--- k8s/backend.yaml	(revision c0086c00a5899d38577d47ee07ef2f1dc672069e)
+++ k8s/backend.yaml	(revision 52fee067a36418ab0681c2c75998b221e425dfeb)
@@ -20,10 +20,9 @@
       containers:
         - name: backend
-          image: trekr-backend:latest  # overwritten by pipeline via kubectl set image
+          image: DOCKERHUB_USERNAME/trekr-backend:latest
+          envFrom:
+            - configMapRef:
+                name: backend-config
           env:
-            - name: SPRING_DATASOURCE_URL
-              value: jdbc:postgresql://postgres:5432/trekr
-            - name: SPRING_DATASOURCE_USERNAME
-              value: trekr
             - name: SPRING_DATASOURCE_PASSWORD
               valueFrom:
@@ -31,6 +30,4 @@
                   name: trekr-secrets
                   key: db-password
-            - name: SPRING_JPA_HIBERNATE_DDL_AUTO
-              value: none
             - name: JWT_SECRET
               valueFrom:
Index: k8s/configmaps.yaml
===================================================================
--- k8s/configmaps.yaml	(revision 52fee067a36418ab0681c2c75998b221e425dfeb)
+++ k8s/configmaps.yaml	(revision 52fee067a36418ab0681c2c75998b221e425dfeb)
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: backend-config
+  namespace: trekr
+data:
+  SPRING_DATASOURCE_URL: "jdbc:postgresql://postgres:5432/trekr"
+  SPRING_DATASOURCE_USERNAME: "trekr"
+  SPRING_JPA_HIBERNATE_DDL_AUTO: "none"
+  SPRING_JACKSON_SERIALIZATION_WRITE_DATES_AS_TIMESTAMPS: "false"
Index: k8s/deploy-local.sh
===================================================================
--- k8s/deploy-local.sh	(revision 52fee067a36418ab0681c2c75998b221e425dfeb)
+++ k8s/deploy-local.sh	(revision 52fee067a36418ab0681c2c75998b221e425dfeb)
@@ -0,0 +1,64 @@
+#!/bin/bash
+set -e
+
+# ── Config ────────────────────────────────────────────────────────────────────
+read -p "DockerHub username: " DOCKERHUB_USERNAME
+read -p "DB password (choose any): " DB_PASSWORD
+read -p "JWT secret (min 32 chars): " JWT_SECRET
+
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+
+echo ""
+echo "==> Switching to docker-desktop context..."
+kubectl config use-context docker-desktop
+
+echo "==> Applying namespace..."
+kubectl apply -f "$SCRIPT_DIR/namespace.yaml"
+
+echo "==> Creating secrets..."
+kubectl create secret generic trekr-secrets \
+  --namespace=trekr \
+  --from-literal=db-password="$DB_PASSWORD" \
+  --from-literal=jwt-secret="$JWT_SECRET" \
+  --save-config \
+  --dry-run=client -o yaml | kubectl apply -f -
+
+echo "==> Creating DB init ConfigMap from DDL..."
+kubectl create configmap trekr-db-init \
+  --namespace=trekr \
+  --from-file=01-ddl.sql="$SCRIPT_DIR/../db-scripts/ddl.sql" \
+  --save-config \
+  --dry-run=client -o yaml | kubectl apply -f -
+
+echo "==> Applying ConfigMaps..."
+kubectl apply -f "$SCRIPT_DIR/configmaps.yaml"
+
+echo "==> Applying Postgres StatefulSet..."
+kubectl apply -f "$SCRIPT_DIR/postgres.yaml"
+
+echo "==> Waiting for Postgres..."
+kubectl rollout status statefulset/postgres -n trekr --timeout=120s
+
+echo "==> Applying Backend Deployment..."
+sed "s|DOCKERHUB_USERNAME|$DOCKERHUB_USERNAME|g" "$SCRIPT_DIR/backend.yaml" | kubectl apply -f -
+
+echo "==> Applying Frontend Deployment..."
+sed "s|DOCKERHUB_USERNAME|$DOCKERHUB_USERNAME|g" "$SCRIPT_DIR/frontend.yaml" | kubectl apply -f -
+
+echo "==> Applying Ingress..."
+kubectl apply -f "$SCRIPT_DIR/ingress.yaml"
+
+echo "==> Waiting for backend rollout..."
+kubectl rollout status deployment/backend -n trekr --timeout=180s
+
+echo "==> Waiting for frontend rollout..."
+kubectl rollout status deployment/frontend -n trekr --timeout=60s
+
+echo ""
+echo "==> Adding trekr.local to /etc/hosts (needs sudo)..."
+if ! grep -q "trekr.local" /etc/hosts; then
+  echo "127.0.0.1 trekr.local" | sudo tee -a /etc/hosts
+fi
+
+echo ""
+echo "✅ Done! Open http://trekr.local in your browser."
Index: k8s/frontend.yaml
===================================================================
--- k8s/frontend.yaml	(revision c0086c00a5899d38577d47ee07ef2f1dc672069e)
+++ k8s/frontend.yaml	(revision 52fee067a36418ab0681c2c75998b221e425dfeb)
@@ -16,5 +16,5 @@
       containers:
         - name: frontend
-          image: trekr-frontend:latest  # overwritten by pipeline via kubectl set image
+          image: DOCKERHUB_USERNAME/trekr-frontend:latest
           ports:
             - containerPort: 80
@@ -32,5 +32,4 @@
   namespace: trekr
 spec:
-  type: NodePort
   selector:
     app: frontend
@@ -38,3 +37,2 @@
     - port: 80
       targetPort: 80
-      nodePort: 30080
Index: k8s/ingress.yaml
===================================================================
--- k8s/ingress.yaml	(revision 52fee067a36418ab0681c2c75998b221e425dfeb)
+++ k8s/ingress.yaml	(revision 52fee067a36418ab0681c2c75998b221e425dfeb)
@@ -0,0 +1,20 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: trekr-ingress
+  namespace: trekr
+  annotations:
+    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
+spec:
+  ingressClassName: nginx
+  rules:
+    - host: trekr.local
+      http:
+        paths:
+          - path: /
+            pathType: Prefix
+            backend:
+              service:
+                name: frontend
+                port:
+                  number: 80
Index: k8s/postgres.yaml
===================================================================
--- k8s/postgres.yaml	(revision c0086c00a5899d38577d47ee07ef2f1dc672069e)
+++ k8s/postgres.yaml	(revision 52fee067a36418ab0681c2c75998b221e425dfeb)
@@ -8,5 +8,5 @@
   resources:
     requests:
-      storage: 5Gi
+      storage: 2Gi
 ---
 apiVersion: apps/v1
@@ -51,4 +51,5 @@
             initialDelaySeconds: 5
             periodSeconds: 5
+            failureThreshold: 10
       volumes:
         - name: data
