Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions charts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Silver Helm Charts

This directory contains Helm charts for Silver services.

## Structure

- `silver/`: Umbrella chart that aggregates service subcharts.
- `silver/charts/opendkim/`: OpenDKIM service chart (first migrated service).

## Conventions

- Service charts live under `silver/charts/<service-name>/`.
- Every service chart should include:
- `values.yaml` with safe defaults.
- `templates/` for Kubernetes resources.
- `README.md` with install and operations guidance.
- Environment overlays should be kept in umbrella chart values files (`values-dev.yaml`, `values-prod.yaml`).

## Next Services

When adding future services (smtp, rspamd, raven, etc.), repeat the OpenDKIM chart pattern and add them as dependencies in the umbrella chart.
12 changes: 12 additions & 0 deletions charts/silver/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v2
name: silver
description: Umbrella chart for Silver mail platform services
type: application
version: 0.1.0
appVersion: "0.1.0"

dependencies:
- name: opendkim
version: 0.1.0
repository: file://charts/opendkim
condition: opendkim.enabled
6 changes: 6 additions & 0 deletions charts/silver/charts/opendkim/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
name: opendkim
description: OpenDKIM service chart for Silver
type: application
version: 0.1.0
appVersion: "main"
171 changes: 171 additions & 0 deletions charts/silver/charts/opendkim/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# OpenDKIM Helm Chart

This chart deploys OpenDKIM for Silver with configuration rendered from Helm values.

## Features

- Stateful OpenDKIM workload with persistent DKIM keys.
- `silver.yaml` generated from Helm values (`domains`).
- Generated `TrustedHosts`, `SigningTable`, and `KeyTable`.
- Security defaults aligned with compose (`cap_drop: all`, no privilege escalation).

## Install

```bash
helm upgrade --install silver charts/silver -f charts/silver/values-dev.yaml -n mail --create-namespace
```

## Required Values

Set at least one domain:

```yaml
domains:
- domain: example.com
dkimSelector: mail
dkimKeySize: 2048
```

## Persistence

- Default path: `/etc/dkimkeys`
- Configure `persistence.storageClass` to your cluster class.
- Use `persistence.existingClaim` if you manage PVC externally.

## Notes

- OpenDKIM container entrypoint still generates missing DKIM keys at startup.
- Config changes trigger rolling restart through checksum annotations.

## Local Testing (Step-by-Step)

Use this sequence to test OpenDKIM locally (for example with Minikube).

### 1. Go to project folder

```bash
cd silver
```

### 2. Create namespace (safe to run once)

```bash
kubectl create namespace mail
```

If it already exists, Kubernetes will print `AlreadyExists`. That is fine.

### 3. Deploy OpenDKIM chart

```bash
helm upgrade --install silver ./charts/silver -n mail \
--set opendkim.enabled=true \
--set 'opendkim.domains[0].domain=example.test' \
--set 'opendkim.domains[0].dkimSelector=mail' \
--set 'opendkim.domains[0].dkimKeySize=2048' \
--set opendkim.persistence.enabled=true \
--wait --timeout 5m
```

What this does:

- Installs or upgrades Helm release `silver`.
- Deploys OpenDKIM resources.
- Sets one test domain (`example.test`).
- Waits for resources to become ready.

### 4. Check resources

```bash
kubectl get all -n mail
kubectl get pvc -n mail
```

Expected:

- Pod is `Running`.
- StatefulSet is ready.
- Service exists.
- PVC is `Bound`.

### 5. Check OpenDKIM logs

```bash
kubectl logs -n mail statefulset/silver-opendkim -c opendkim --tail=200
```

You should see startup and key-generation output.

### 6. Run Helm connectivity test

```bash
helm test silver -n mail
```

Expected: test suite succeeds.

### 7. Manual port check from inside cluster

```bash
kubectl run -n mail dkim-probe --rm -it --restart=Never --image=busybox:1.36 -- \
sh -c "nc -zvw5 silver-opendkim 8891"
```

Expected: port `8891` is open.

### 8. Verify key generation

Get pod name:

```bash
POD=$(kubectl get pod -n mail -l app.kubernetes.io/name=opendkim -o jsonpath='{.items[0].metadata.name}')
echo "$POD"
```

List generated key files:

```bash
kubectl exec -n mail "$POD" -- sh -c "find /etc/dkimkeys -maxdepth 3 -type f | sort"
```

Show generated DNS TXT record file:

```bash
kubectl exec -n mail "$POD" -- sh -c "cat /etc/dkimkeys/example.test/mail.txt"
```

### 9. Test key persistence

Delete pod to force restart:

```bash
kubectl delete pod -n mail "$POD"
```

Wait for StatefulSet to recover:

```bash
kubectl rollout status statefulset/silver-opendkim -n mail --timeout=180s
```

Get new pod name:

```bash
NEWPOD=$(kubectl get pod -n mail -l app.kubernetes.io/name=opendkim -o jsonpath='{.items[0].metadata.name}')
echo "$NEWPOD"
```

Verify keys still exist:

```bash
kubectl exec -n mail "$NEWPOD" -- sh -c "find /etc/dkimkeys -maxdepth 3 -type f | sort"
```

If key files are still present, persistence is working.

### 10. Cleanup (optional)

```bash
helm uninstall silver -n mail
kubectl delete namespace mail
```
41 changes: 41 additions & 0 deletions charts/silver/charts/opendkim/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{{- define "opendkim.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{- define "opendkim.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{- define "opendkim.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{- define "opendkim.labels" -}}
helm.sh/chart: {{ include "opendkim.chart" . }}
app.kubernetes.io/name: {{ include "opendkim.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}

{{- define "opendkim.selectorLabels" -}}
app.kubernetes.io/name: {{ include "opendkim.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}

{{- define "opendkim.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{- default (include "opendkim.fullname" .) .Values.serviceAccount.name -}}
{{- else -}}
{{- default "default" .Values.serviceAccount.name -}}
{{- end -}}
{{- end -}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "opendkim.fullname" . }}-config
labels:
{{- include "opendkim.labels" . | nindent 4 }}
data:
opendkim.conf: |
{{ .Values.opendkimConf | indent 4 }}
29 changes: 29 additions & 0 deletions charts/silver/charts/opendkim/templates/configmap-tables.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "opendkim.fullname" . }}-tables
labels:
{{- include "opendkim.labels" . | nindent 4 }}
data:
TrustedHosts: |
{{- range .Values.trustedHosts.defaults }}
{{ . }}
{{- end }}
{{- range .Values.trustedHosts.additional }}
{{ . }}
{{- end }}
{{- range .Values.domains }}
{{ .domain }}
*.{{ .domain }}
{{- end }}

SigningTable: |
{{- range .Values.domains }}
*@{{ .domain }} {{ default "mail" .dkimSelector }}._domainkey.{{ .domain }}
*@*.{{ .domain }} {{ default "mail" .dkimSelector }}._domainkey.{{ .domain }}
{{- end }}

KeyTable: |
{{- range .Values.domains }}
{{ default "mail" .dkimSelector }}._domainkey.{{ .domain }} {{ .domain }}:{{ default "mail" .dkimSelector }}:/etc/dkimkeys/{{ .domain }}/{{ default "mail" .dkimSelector }}.private
{{- end }}
24 changes: 24 additions & 0 deletions charts/silver/charts/opendkim/templates/networkpolicy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{{- if .Values.networkPolicy.enabled }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ include "opendkim.fullname" . }}
labels:
{{- include "opendkim.labels" . | nindent 4 }}
spec:
podSelector:
matchLabels:
{{- include "opendkim.selectorLabels" . | nindent 6 }}
policyTypes:
- Ingress
ingress:
- from:
{{- if .Values.networkPolicy.allowedIngressFrom }}
{{ toYaml .Values.networkPolicy.allowedIngressFrom | indent 8 }}
{{- else }}
- podSelector: {}
{{- end }}
ports:
- protocol: TCP
port: {{ .Values.service.port }}
{{- end }}
15 changes: 15 additions & 0 deletions charts/silver/charts/opendkim/templates/secret-silver.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ include "opendkim.fullname" . }}-silver
labels:
{{- include "opendkim.labels" . | nindent 4 }}
type: Opaque
stringData:
silver.yaml: |
domains:
{{- range .Values.domains }}
- domain: {{ .domain | quote }}
dkim-selector: {{ default "mail" .dkimSelector | quote }}
dkim-key-size: {{ default 2048 .dkimKeySize }}
{{- end }}
17 changes: 17 additions & 0 deletions charts/silver/charts/opendkim/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{{- if .Values.service.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "opendkim.fullname" . }}
labels:
{{- include "opendkim.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: opendkim
protocol: TCP
name: opendkim
selector:
{{- include "opendkim.selectorLabels" . | nindent 4 }}
{{- end }}
12 changes: 12 additions & 0 deletions charts/silver/charts/opendkim/templates/serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "opendkim.serviceAccountName" . }}
labels:
{{- include "opendkim.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
14 changes: 14 additions & 0 deletions charts/silver/charts/opendkim/templates/tests/test-connection.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "opendkim.fullname" . }}-test-connection"
labels:
{{- include "opendkim.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox:1.36
command: ['sh', '-c', 'nc -zvw5 {{ include "opendkim.fullname" . }} {{ .Values.service.port }}']
restartPolicy: Never
Loading
Loading