Skip to content
Open
43 changes: 43 additions & 0 deletions .github/workflows/build-and-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Build & Deploy to Production
on:
push:
branches: ['chore/initial-k8-config']
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check Out Repo
uses: actions/checkout@v4
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push to mail-server
uses: docker/build-push-action@v5
with:
context: ./
file: ./Dockerfile
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/mail-server:${{ github.sha }}

deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: production
steps:
- uses: actions/checkout@v4

- name: Update mail-server image
uses: steebchen/kubectl@v2.0.0
with:
config: ${{ secrets.KUBE_CONFIG_DATA }}
command: set image --record deployment/mail-server mail-server=${{ secrets.DOCKERHUB_USERNAME }}/mail-server:${{ github.sha }} -n mail
- name: Verify mail-server rollout
uses: steebchen/kubectl@v2.0.0
with:
config: ${{ secrets.KUBE_CONFIG_DATA }}
command: rollout status deployment/mail-server -n mail
6 changes: 6 additions & 0 deletions deploy/charts/mail-server/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
name: mail-server
description: Internxt Mail Server (NestJS) — stateless service in front of Stalwart
type: application
version: 0.1.0
appVersion: "0.1.0"
72 changes: 72 additions & 0 deletions deploy/charts/mail-server/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: mail-server
labels:
app: mail-server
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: mail-server
template:
metadata:
labels:
app: mail-server
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:

Check warning on line 21 in deploy/charts/mail-server/templates/deployment.yaml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Bind this resource's automounted service account to RBAC or disable automounting.

See more on https://sonarcloud.io/project/issues?id=internxt_mail-server&issues=AZ3BusRnRuvhNyq5hzmZ&open=AZ3BusRnRuvhNyq5hzmZ&pullRequest=21

Check warning

Code scanning / SonarCloud

Service account permissions should be restricted Medium

Bind this resource's automounted service account to RBAC or disable automounting. See more on SonarQube Cloud
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
- name: mail-server

Check warning on line 22 in deploy/charts/mail-server/templates/deployment.yaml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Specify a storage request for this container.

See more on https://sonarcloud.io/project/issues?id=internxt_mail-server&issues=AZ3BusRnRuvhNyq5hzmY&open=AZ3BusRnRuvhNyq5hzmY&pullRequest=21
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

Check warning on line 23 in deploy/charts/mail-server/templates/deployment.yaml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a specific version tag for the image instead of "latest".

See more on https://sonarcloud.io/project/issues?id=internxt_mail-server&issues=AZ3BusRnRuvhNyq5hzma&open=AZ3BusRnRuvhNyq5hzma&pullRequest=21
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
env:
- name: NODE_ENV
value: {{ .Values.nodeEnv | quote }}
- name: PORT
value: {{ .Values.service.port | quote }}
- name: RDS_HOSTNAME
value: {{ .Values.database.host | quote }}
- name: RDS_PORT
value: {{ .Values.database.port | quote }}
- name: RDS_DBNAME
value: {{ .Values.database.name | quote }}
- name: RDS_USERNAME
value: {{ .Values.database.username | quote }}
- name: STALWART_JMAP_URL
value: {{ .Values.stalwart.jmapUrl | quote }}
- name: STALWART_ADMIN_URL
value: {{ .Values.stalwart.adminUrl | quote }}
- name: STALWART_ADMIN_USER
value: {{ .Values.stalwart.adminUser | quote }}
- name: STALWART_MASTER_USER
value: {{ .Values.stalwart.masterUser | quote }}
- name: PAYMENTS_API_URL
value: {{ .Values.paymentsApiUrl | quote }}
- name: REDIS_URL
value: {{ .Values.redisUrl | quote }}
- name: MTA_HOOKS_USERNAME
value: {{ .Values.mta.hooksUsername | quote }}

envFrom:
- secretRef:
name: {{ .Values.secretName }}
livenessProbe:
httpGet:
path: {{ .Values.probes.liveness.path }}
port: http
initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.liveness.periodSeconds }}
readinessProbe:
httpGet:
path: {{ .Values.probes.readiness.path }}
port: http
initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.readiness.periodSeconds }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
15 changes: 15 additions & 0 deletions deploy/charts/mail-server/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: mail-server
labels:
app: mail-server
spec:
type: {{ .Values.service.type }}
selector:
app: mail-server
ports:
- name: http
port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
53 changes: 53 additions & 0 deletions deploy/charts/mail-server/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
replicaCount: 2

image:
repository: internxt/mail-server
tag: latest
pullPolicy: IfNotPresent

imagePullSecrets: []

service:
type: LoadBalancer
port: 3100

resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi

nodeEnv: production

paymentsApiUrl: 'https://gateway.internxt.com/payments'

redisUrl: REPLACE_ME

database:
host: REPLACE_ME
port: '5432'
name: REPLACE_ME
username: REPLACE_ME

stalwart:
jmapUrl: http://stalwart:8080
adminUrl: http://stalwart:8080
adminUser: mail-server
masterUser: master

mta:
hooksUsername: stalwart

secretName: mail-server-secrets

probes:
liveness:
path: /health
initialDelaySeconds: 20
periodSeconds: 10
readiness:
path: /health
initialDelaySeconds: 5
periodSeconds: 5
6 changes: 6 additions & 0 deletions deploy/charts/stalwart/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
name: stalwart
description: Stalwart mail server (SMTP/IMAP/JMAP)
type: application
version: 0.1.0
appVersion: "0.11.0"
9 changes: 9 additions & 0 deletions deploy/charts/stalwart/templates/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: stalwart-config
labels:
app: stalwart
data:
config.toml: |
{{ tpl .Values.config . | indent 4 }}
39 changes: 39 additions & 0 deletions deploy/charts/stalwart/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: v1
kind: Service
metadata:
name: stalwart
labels:
app: stalwart
spec:
type: {{ .Values.service.type }}
selector:
app: stalwart
ports:
- name: http
port: {{ .Values.service.ports.http }}
targetPort: http
protocol: TCP
- name: smtp
port: {{ .Values.service.ports.smtp }}
targetPort: smtp
protocol: TCP
- name: submission
port: {{ .Values.service.ports.submission }}
targetPort: submission
protocol: TCP
- name: imap
port: {{ .Values.service.ports.imap }}
targetPort: imap
protocol: TCP
{{- if gt (int .Values.service.ports.submissions) 0 }}
- name: submissions
port: {{ .Values.service.ports.submissions }}
targetPort: submissions
protocol: TCP
{{- end }}
{{- if gt (int .Values.service.ports.imaps) 0 }}
- name: imaps
port: {{ .Values.service.ports.imaps }}
targetPort: imaps
protocol: TCP
{{- end }}
79 changes: 79 additions & 0 deletions deploy/charts/stalwart/templates/statefulset.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: stalwart
labels:
app: stalwart
spec:
serviceName: stalwart
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: stalwart
template:
metadata:
labels:
app: stalwart
annotations:
checksum/config: {{ .Values.config | sha256sum }}
spec:
containers:

Check warning on line 20 in deploy/charts/stalwart/templates/statefulset.yaml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Bind this resource's automounted service account to RBAC or disable automounting.

See more on https://sonarcloud.io/project/issues?id=internxt_mail-server&issues=AZ2RlqyS8vXIT0bFC5II&open=AZ2RlqyS8vXIT0bFC5II&pullRequest=21

Check warning

Code scanning / SonarCloud

Service account permissions should be restricted Medium

Bind this resource's automounted service account to RBAC or disable automounting. See more on SonarQube Cloud
- name: stalwart

Check warning on line 21 in deploy/charts/stalwart/templates/statefulset.yaml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Specify a storage limit for this container.

See more on https://sonarcloud.io/project/issues?id=internxt_mail-server&issues=AZ2RlqyS8vXIT0bFC5IJ&open=AZ2RlqyS8vXIT0bFC5IJ&pullRequest=21

Check warning on line 21 in deploy/charts/stalwart/templates/statefulset.yaml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Specify a storage request for this container.

See more on https://sonarcloud.io/project/issues?id=internxt_mail-server&issues=AZ2RlqyS8vXIT0bFC5IH&open=AZ2RlqyS8vXIT0bFC5IH&pullRequest=21

Check warning

Code scanning / SonarCloud

Storage limits should be enforced Medium

Specify a storage limit for this container. See more on SonarQube Cloud
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.ports.http }}
- name: smtp
containerPort: {{ .Values.service.ports.smtp }}
- name: submission
containerPort: {{ .Values.service.ports.submission }}
- name: imap
containerPort: {{ .Values.service.ports.imap }}
env:
{{- range $key, $value := .Values.env }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
envFrom:
- secretRef:
name: {{ .Values.secretName }}
livenessProbe:
httpGet:
path: /healthz/live
port: http
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /healthz/ready
port: http
initialDelaySeconds: 10
periodSeconds: 5
volumeMounts:
- name: config
mountPath: /opt/stalwart/etc/config.toml
subPath: config.toml
{{- if .Values.persistence.enabled }}
- name: data
mountPath: /opt/stalwart
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumes:
- name: config
configMap:
name: stalwart-config
{{- if .Values.persistence.enabled }}
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
{{- if .Values.persistence.storageClass }}
storageClassName: {{ .Values.persistence.storageClass }}
{{- end }}
resources:
requests:
storage: {{ .Values.persistence.size }}
{{- end }}
Loading
Loading