From 1894faa7d28e4f71ac776a57700e3946b66239c9 Mon Sep 17 00:00:00 2001 From: Gabriel Windlin Date: Tue, 25 Nov 2025 12:07:37 +0100 Subject: [PATCH] Add official Kubernetes base manifests using ConfigMaps --- kubernetes/ingress.yaml | 28 +++++++ kubernetes/postgres.yaml | 93 +++++++++++++++++++++++ kubernetes/rallly-config.yaml | 21 +++++ kubernetes/rallly.yaml | 139 ++++++++++++++++++++++++++++++++++ kubernetes/secrets.yaml | 21 +++++ 5 files changed, 302 insertions(+) create mode 100644 kubernetes/ingress.yaml create mode 100644 kubernetes/postgres.yaml create mode 100644 kubernetes/rallly-config.yaml create mode 100644 kubernetes/rallly.yaml create mode 100644 kubernetes/secrets.yaml diff --git a/kubernetes/ingress.yaml b/kubernetes/ingress.yaml new file mode 100644 index 0000000..b58310c --- /dev/null +++ b/kubernetes/ingress.yaml @@ -0,0 +1,28 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: rallly + namespace: default + annotations: + # Example for cert-manager (uncomment if using) + # cert-manager.io/cluster-issuer: letsencrypt-prod + + # Example for NGINX ingress controller size limit + # nginx.ingress.kubernetes.io/proxy-body-size: "10m" +spec: + ingressClassName: nginx + rules: + - host: rallly.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: rallly + port: + number: 80 + tls: + - hosts: + - rallly.example.com + secretName: rallly-tls diff --git a/kubernetes/postgres.yaml b/kubernetes/postgres.yaml new file mode 100644 index 0000000..1961f16 --- /dev/null +++ b/kubernetes/postgres.yaml @@ -0,0 +1,93 @@ +# kubernetes/postgres.yaml +apiVersion: v1 +kind: Service +metadata: + name: postgres + namespace: default +spec: + ports: + - port: 5432 + selector: + app: postgres +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: postgres + namespace: default +spec: + selector: + matchLabels: + app: postgres + serviceName: "postgres" + replicas: 1 + template: + metadata: + labels: + app: postgres + spec: + securityContext: + # Run as standard Postgres user (UID 999) + fsGroup: 999 + runAsNonRoot: true + runAsUser: 999 + containers: + - name: postgres + image: postgres:15-alpine + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: rallly-secrets + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: rallly-secrets + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: rallly + ports: + - containerPort: 5432 + name: postgres + # Health Probes + livenessProbe: + exec: + command: + - /bin/sh + - -c + - pg_isready -U rallly + initialDelaySeconds: 30 + periodSeconds: 10 + readinessProbe: + exec: + command: + - /bin/sh + - -c + - pg_isready -U rallly + initialDelaySeconds: 10 + periodSeconds: 5 + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 500m + memory: 1Gi + volumeClaimTemplates: + - metadata: + name: postgres-data + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + # Note: Adjust storage size based on your data retention needs. + storage: 1Gi diff --git a/kubernetes/rallly-config.yaml b/kubernetes/rallly-config.yaml new file mode 100644 index 0000000..edd96e2 --- /dev/null +++ b/kubernetes/rallly-config.yaml @@ -0,0 +1,21 @@ +# kubernetes/rallly-config.yaml +# Stores all non-secret configuration variables. +apiVersion: v1 +kind: ConfigMap +metadata: + name: rallly-config + namespace: default +data: + # Base URL for the application (must match Ingress host) + NEXT_PUBLIC_BASE_URL: "https://rallly.example.com" + + # Email Settings + SUPPORT_EMAIL: "admin@example.com" + EMAIL_LOGIN_ENABLED: "true" + # SECURITY: This allows ANY email to register. Restrict to "*@example.com" or specific emails for production. + ALLOWED_EMAILS: "*" + + # SMTP Settings (Credentials will be in the Secret file) + SMTP_HOST: "smtp.example.com" + SMTP_PORT: "587" + SMTP_SECURE: "false" diff --git a/kubernetes/rallly.yaml b/kubernetes/rallly.yaml new file mode 100644 index 0000000..af6fcd5 --- /dev/null +++ b/kubernetes/rallly.yaml @@ -0,0 +1,139 @@ +# kubernetes/rallly.yaml +apiVersion: v1 +kind: Service +metadata: + name: rallly + namespace: default +spec: + selector: + app: rallly + ports: + - protocol: TCP + port: 80 + targetPort: 3000 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: rallly + namespace: default + labels: + app: rallly +spec: + # Note: For production, use replicas: 2 or more with a PodDisruptionBudget for HA. + replicas: 1 + selector: + matchLabels: + app: rallly + strategy: + type: RollingUpdate + template: + metadata: + labels: + app: rallly + spec: + securityContext: + fsGroup: 1000 + runAsNonRoot: true + runAsUser: 1000 + containers: + - name: rallly + # Pinned version for stability (latest stable at time of refactoring) + image: lukevella/rallly:v4.5.4 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + name: http + protocol: TCP + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + env: + # 1. Configuration (from ConfigMap) + - name: NEXT_PUBLIC_BASE_URL + valueFrom: + configMapKeyRef: + name: rallly-config + key: NEXT_PUBLIC_BASE_URL + - name: SUPPORT_EMAIL + valueFrom: + configMapKeyRef: + name: rallly-config + key: SUPPORT_EMAIL + - name: ALLOWED_EMAILS + valueFrom: + configMapKeyRef: + name: rallly-config + key: ALLOWED_EMAILS + - name: EMAIL_LOGIN_ENABLED + valueFrom: + configMapKeyRef: + name: rallly-config + key: EMAIL_LOGIN_ENABLED + - name: SMTP_HOST + valueFrom: + configMapKeyRef: + name: rallly-config + key: SMTP_HOST + - name: SMTP_PORT + valueFrom: + configMapKeyRef: + name: rallly-config + key: SMTP_PORT + - name: SMTP_SECURE + valueFrom: + configMapKeyRef: + name: rallly-config + key: SMTP_SECURE + + # 2. Secrets (from Secret) + - name: DATABASE_URL + valueFrom: + secretKeyRef: + name: rallly-secrets + key: DATABASE_URL + - name: SECRET_PASSWORD + valueFrom: + secretKeyRef: + name: rallly-secrets + key: SECRET_PASSWORD + - name: INITIAL_ADMIN_EMAIL + valueFrom: + secretKeyRef: + name: rallly-secrets + key: INITIAL_ADMIN_EMAIL + + # SMTP User/Password (optional usage) + # - name: SMTP_USER + # valueFrom: + # secretKeyRef: + # name: rallly-secrets + # key: SMTP_USER + # - name: SMTP_PASSWORD + # valueFrom: + # secretKeyRef: + # name: rallly-secrets + # key: SMTP_PASSWORD + + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 200m + memory: 512Mi + + livenessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 30 + periodSeconds: 10 + readinessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 30 + periodSeconds: 5 diff --git a/kubernetes/secrets.yaml b/kubernetes/secrets.yaml new file mode 100644 index 0000000..eb49b48 --- /dev/null +++ b/kubernetes/secrets.yaml @@ -0,0 +1,21 @@ +# kubernetes/secrets.yaml +apiVersion: v1 +kind: Secret +metadata: + name: rallly-secrets + namespace: default +type: Opaque +stringData: + # Database Connection String (postgres://user:password@service:port/db_name) + # IMPORTANT: The username/password here MUST match POSTGRES_USER/POSTGRES_PASSWORD below. + DATABASE_URL: "postgres://rallly:CHANGE_ME_PASSWORD@postgres:5432/rallly" + + # Random string for session encryption (generate with 'openssl rand -hex 32') + SECRET_PASSWORD: "CHANGE_ME_TO_A_LONG_RANDOM_STRING" + + # The email of the first admin user + INITIAL_ADMIN_EMAIL: "admin@example.com" + + # Database Credentials (used by the postgres StatefulSet) + POSTGRES_USER: "rallly" + POSTGRES_PASSWORD: "CHANGE_ME_PASSWORD"