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
4 changes: 2 additions & 2 deletions charts/proton-bridge/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ apiVersion: v2
name: proton-bridge
description: Proton Mail Bridge deployment for in-cluster SMTP/IMAP access
type: application
version: 0.1.8
appVersion: "3.22.0"
version: 0.2.0
appVersion: "3.25.0"
24 changes: 21 additions & 3 deletions charts/proton-bridge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,32 @@ kubectl -n "$NAMESPACE" rollout status deploy/"$DEPLOYMENT"
- Service type: `ClusterIP`
- Service ports: SMTP `25`, IMAP `143` (mapped to container ports `1026`/`1144` by default)
- Image tag: `latest`
- Bridge mode: `grpc` (serves mail plus the gRPC API the metrics exporter scrapes)
- Metrics: exporter on container port `9154`; `PodMonitor` off by default
- Update strategy: `Recreate` (single `ReadWriteOnce` volume)
- PVC: enabled, `ReadWriteOnce`, `2Gi`

## Metrics

The image runs a Prometheus exporter (container port `container.metricsPort`,
default `9154`) when `bridge.mode=grpc` (the default). Enable scraping with the
Prometheus Operator:

```yaml
podMonitor:
enabled: true
```

## Required Runtime Configuration

The image requires the following environment variables:
The image requires the following environment variables (all set by the chart):

- `PROTON_BRIDGE_SMTP_PORT`
- `PROTON_BRIDGE_IMAP_PORT`
- `PROTON_BRIDGE_HOST`
- `CONTAINER_SMTP_PORT`
- `CONTAINER_IMAP_PORT`
- `CONTAINER_METRICS_PORT`

By default, the chart creates a Secret with values from `values.yaml`. Set `existingSecret` to reuse your own Secret.

Expand All @@ -88,11 +103,14 @@ helm upgrade --install proton-bridge ./charts/proton-bridge

Common overrides:

- `image.tag`
- `image.tag`, `image.digest` (pin by digest: referenced as `repo:tag@digest`)
- `bridge.mode` (`grpc` default, `noninteractive`, or `cli`)
- `strategy` (defaults to `Recreate`)
- `podMonitor.enabled`, `podMonitor.interval`, `podMonitor.labels`
- `service.type`
- `persistence.existingClaim`
- `bridge.host`, `bridge.smtpPort`, `bridge.imapPort`
- `container.smtpPort`, `container.imapPort`
- `container.smtpPort`, `container.imapPort`, `container.metricsPort`
- `container.enablePrivilegedPortBinding`
- `containerSecurityContext`
- `volumePermissions.enabled`
Expand Down
9 changes: 8 additions & 1 deletion charts/proton-bridge/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ metadata:
{{- include "proton-bridge.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
{{- with .Values.strategy }}
strategy:
{{- toYaml . | nindent 4 }}
{{- end }}
selector:
matchLabels:
{{- include "proton-bridge.selectorLabels" . | nindent 6 }}
Expand Down Expand Up @@ -69,7 +73,7 @@ spec:
{{- end }}
containers:
- name: proton-bridge
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}{{ with .Values.image.digest }}@{{ . }}{{ end }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{- $containerSecurityContext := deepCopy (.Values.containerSecurityContext | default dict) }}
{{- if .Values.container.enablePrivilegedPortBinding }}
Expand Down Expand Up @@ -101,6 +105,9 @@ spec:
- name: imap
containerPort: {{ $containerImapPort }}
protocol: TCP
- name: metrics
containerPort: {{ int .Values.container.metricsPort }}
protocol: TCP
{{- if .Values.persistence.enabled }}
volumeMounts:
- name: bridge-data
Expand Down
19 changes: 19 additions & 0 deletions charts/proton-bridge/templates/podmonitor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{{- if .Values.podMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: {{ include "proton-bridge.fullname" . }}
labels:
{{- include "proton-bridge.labels" . | nindent 4 }}
{{- with .Values.podMonitor.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
selector:
matchLabels:
{{- include "proton-bridge.selectorLabels" . | nindent 6 }}
podMetricsEndpoints:
- port: metrics
path: {{ .Values.podMonitor.path }}
interval: {{ .Values.podMonitor.interval }}
{{- end }}
1 change: 1 addition & 0 deletions charts/proton-bridge/templates/secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ stringData:
PROTON_BRIDGE_IMAP_PORT: {{ $bridgeImapPort | quote }}
CONTAINER_SMTP_PORT: {{ $containerSmtpPort | quote }}
CONTAINER_IMAP_PORT: {{ $containerImapPort | quote }}
CONTAINER_METRICS_PORT: {{ int .Values.container.metricsPort | quote }}
{{- end }}
22 changes: 21 additions & 1 deletion charts/proton-bridge/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@ replicaCount: 1
image:
repository: ghcr.io/mgarratt/docker-images/proton-bridge
tag: latest
# Pin by content digest (e.g. sha256:...). When set, the image is referenced as
# repository:tag@digest, so the tag stays readable but the digest is immutable
# (avoids stale pulls from a mirror that cached a re-pushed mutable tag).
digest: ""
pullPolicy: IfNotPresent

# Deployment update strategy. Recreate by default: bridge uses a single
# ReadWriteOnce volume, so a rolling update would deadlock on volume multi-attach.
strategy:
type: Recreate

imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
Expand All @@ -29,14 +38,25 @@ bridge:
host: "127.0.0.1"
smtpPort: 1025
imapPort: 1143
mode: noninteractive
# grpc serves mail plus the gRPC API the metrics exporter scrapes.
# Use noninteractive for a leaner run without metrics, or cli for first login.
mode: grpc

container:
smtpPort: 1026
imapPort: 1144
metricsPort: 9154
# Set true to add NET_BIND_SERVICE capability so non-root process can bind <1024 (e.g. 25/143).
enablePrivilegedPortBinding: false

# Prometheus Operator PodMonitor scraping the bridge metrics exporter.
podMonitor:
enabled: false
interval: 30s
path: /metrics
# Extra labels on the PodMonitor (e.g. to match a Prometheus ruleSelector).
labels: {}

# Pod-level security context defaults for the bridge image user (uid:gid 1000:1000).
podSecurityContext:
fsGroup: 1000
Expand Down
Loading