diff --git a/apps/keila/db-init-job.yaml b/apps/keila/db-init-job.yaml new file mode 100644 index 0000000..01109fc --- /dev/null +++ b/apps/keila/db-init-job.yaml @@ -0,0 +1,63 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: keila-db-init +spec: + template: + metadata: + labels: + component: db-init + spec: + restartPolicy: OnFailure + securityContext: + runAsNonRoot: true + runAsUser: 999 + runAsGroup: 999 + seccompProfile: + type: RuntimeDefault + containers: + - name: postgres-init + image: postgres:15 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: false + env: + - name: PGHOST + value: {{ .apps.keila.dbHostname }} + - name: PGUSER + value: postgres + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: keila-secrets + key: apps.postgres.password + - name: DB_NAME + value: {{ .apps.keila.dbName }} + - name: DB_USER + value: {{ .apps.keila.dbUsername }} + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: keila-secrets + key: apps.keila.dbPassword + command: + - /bin/bash + - -c + - | + set -e + echo "Waiting for PostgreSQL to be ready..." + until pg_isready; do + echo "PostgreSQL is not ready - sleeping" + sleep 2 + done + echo "PostgreSQL is ready" + + echo "Creating database and user for Keila..." + psql -c "CREATE DATABASE ${DB_NAME};" || echo "Database ${DB_NAME} already exists" + psql -c "CREATE USER ${DB_USER} WITH PASSWORD '${DB_PASSWORD}';" || echo "User ${DB_USER} already exists" + psql -c "GRANT ALL PRIVILEGES ON DATABASE ${DB_NAME} TO ${DB_USER};" + psql -d ${DB_NAME} -c "GRANT ALL ON SCHEMA public TO ${DB_USER};" + echo "Database initialization complete" \ No newline at end of file diff --git a/apps/keila/deployment.yaml b/apps/keila/deployment.yaml new file mode 100644 index 0000000..8cbaf18 --- /dev/null +++ b/apps/keila/deployment.yaml @@ -0,0 +1,85 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: keila +spec: + replicas: 1 + selector: + matchLabels: + component: web + template: + metadata: + labels: + component: web + spec: + containers: + - name: keila + image: {{ .apps.keila.image }} + ports: + - containerPort: {{ .apps.keila.port }} + env: + - name: DB_URL + valueFrom: + secretKeyRef: + name: keila-secrets + key: apps.keila.dbUrl + - name: URL_HOST + value: {{ .apps.keila.domain }} + - name: URL_SCHEMA + value: https + - name: URL_PORT + value: "443" + - name: PORT + value: "{{ .apps.keila.port }}" + - name: SECRET_KEY_BASE + valueFrom: + secretKeyRef: + name: keila-secrets + key: apps.keila.secretKeyBase + - name: MAILER_SMTP_HOST + value: {{ .apps.keila.smtp.host }} + - name: MAILER_SMTP_PORT + value: "{{ .apps.keila.smtp.port }}" + - name: MAILER_ENABLE_SSL + value: {{ if eq .apps.keila.smtp.sslTlsOrStartTls "sslTls" }}"true"{{ else }}"false"{{ end }} + - name: MAILER_ENABLE_STARTTLS + value: {{ if eq .apps.keila.smtp.sslTlsOrStartTls "startTls" }}"true"{{ else }}"false"{{ end }} + - name: MAILER_SMTP_USER + value: {{ .apps.keila.smtp.user }} + - name: MAILER_SMTP_PASSWORD + valueFrom: + secretKeyRef: + name: keila-secrets + key: apps.keila.smtpPassword + - name: MAILER_SMTP_FROM_EMAIL + value: {{ .apps.keila.smtp.from }} + - name: DISABLE_REGISTRATION + value: "{{ .apps.keila.disableRegistration }}" + - name: KEILA_USER + value: "{{ .apps.keila.adminUser }}" + - name: KEILA_PASSWORD + valueFrom: + secretKeyRef: + name: keila-secrets + key: apps.keila.adminPassword + - name: USER_CONTENT_DIR + value: /var/lib/keila/uploads + volumeMounts: + - name: uploads + mountPath: /var/lib/keila/uploads + livenessProbe: + httpGet: + path: / + port: {{ .apps.keila.port }} + initialDelaySeconds: 30 + periodSeconds: 10 + readinessProbe: + httpGet: + path: / + port: {{ .apps.keila.port }} + initialDelaySeconds: 5 + periodSeconds: 5 + volumes: + - name: uploads + persistentVolumeClaim: + claimName: keila-uploads \ No newline at end of file diff --git a/apps/keila/ingress.yaml b/apps/keila/ingress.yaml new file mode 100644 index 0000000..0c93a9e --- /dev/null +++ b/apps/keila/ingress.yaml @@ -0,0 +1,26 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: keila + annotations: + traefik.ingress.kubernetes.io/router.tls: "true" + traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt + external-dns.alpha.kubernetes.io/target: {{ .cloud.domain }} + external-dns.alpha.kubernetes.io/cloudflare-proxied: "false" + traefik.ingress.kubernetes.io/router.middlewares: keila-cors@kubernetescrd +spec: + rules: + - host: {{ .apps.keila.domain }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: keila + port: + number: 80 + tls: + - secretName: "wildcard-wild-cloud-tls" + hosts: + - "{{ .apps.keila.domain }}" diff --git a/apps/keila/kustomization.yaml b/apps/keila/kustomization.yaml new file mode 100644 index 0000000..6fa003c --- /dev/null +++ b/apps/keila/kustomization.yaml @@ -0,0 +1,17 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: keila +labels: + - includeSelectors: true + pairs: + app: keila + managedBy: kustomize + partOf: wild-cloud +resources: + - namespace.yaml + - deployment.yaml + - service.yaml + - ingress.yaml + - pvc.yaml + - db-init-job.yaml + - middleware-cors.yaml \ No newline at end of file diff --git a/apps/keila/manifest.yaml b/apps/keila/manifest.yaml new file mode 100644 index 0000000..32a93cc --- /dev/null +++ b/apps/keila/manifest.yaml @@ -0,0 +1,29 @@ +name: keila +description: Keila is an open-source email marketing platform that allows you to send newsletters and manage mailing lists with privacy and control. +version: 1.0.0 +icon: https://www.keila.io/images/logo.svg +requires: + - name: postgres +defaultConfig: + image: pentacent/keila:latest + port: 4000 + storage: 1Gi + domain: keila.{{ .cloud.domain }} + dbHostname: postgres.postgres.svc.cluster.local + dbName: keila + dbUsername: keila + disableRegistration: "true" + adminUser: admin@{{ .cloud.domain }} + smtp: + host: {{ .cloud.smtp.host }} + port: {{ .cloud.smtp.port }} + from: {{ .cloud.smtp.from }} + user: {{ .cloud.smtp.user }} + sslTlsOrStartTls: {{ .cloud.smtp.sslTlsOrStartTls }} +requiredSecrets: + - apps.keila.secretKeyBase + - apps.keila.dbPassword + - apps.keila.dbUrl + - apps.keila.adminPassword + - apps.keila.smtpPassword + - apps.postgres.password \ No newline at end of file diff --git a/apps/keila/middleware-cors.yaml b/apps/keila/middleware-cors.yaml new file mode 100644 index 0000000..599e5c2 --- /dev/null +++ b/apps/keila/middleware-cors.yaml @@ -0,0 +1,28 @@ +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: cors +spec: + headers: + accessControlAllowCredentials: true + accessControlAllowHeaders: + - "Content-Type" + - "Authorization" + - "X-Requested-With" + - "Accept" + - "Origin" + - "Cache-Control" + - "X-File-Name" + accessControlAllowMethods: + - "GET" + - "POST" + - "PUT" + - "DELETE" + - "OPTIONS" + accessControlAllowOriginList: + - "http://localhost:1313" + - "https://*.{{ .cloud.domain }}" + - "https://{{ .cloud.domain }}" + accessControlExposeHeaders: + - "*" + accessControlMaxAge: 86400 \ No newline at end of file diff --git a/apps/keila/namespace.yaml b/apps/keila/namespace.yaml new file mode 100644 index 0000000..73d5f12 --- /dev/null +++ b/apps/keila/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: keila \ No newline at end of file diff --git a/apps/keila/pvc.yaml b/apps/keila/pvc.yaml new file mode 100644 index 0000000..2becff2 --- /dev/null +++ b/apps/keila/pvc.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: keila-uploads +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .apps.keila.storage }} \ No newline at end of file diff --git a/apps/keila/service.yaml b/apps/keila/service.yaml new file mode 100644 index 0000000..6800006 --- /dev/null +++ b/apps/keila/service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: keila +spec: + selector: + component: web + ports: + - port: 80 + targetPort: {{ .apps.keila.port }} + protocol: TCP \ No newline at end of file