├── .ci ├── ct-config.yaml ├── lint-config.yaml └── scripts │ ├── kube-score.sh │ └── local-ct-lint.sh ├── .github ├── CODEOWNERS └── workflows │ ├── on-push-lint-charts.yml │ └── on-push-master-publish-chart.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── TESTING.md ├── charts └── docker-mailserver │ ├── .helmignore │ ├── Chart.lock │ ├── Chart.yaml │ ├── OWNERS │ ├── README.md │ ├── ci │ ├── ci-haproxy.yaml │ └── ci-values.yaml │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── configmap.yaml │ ├── deployment.yaml │ ├── extra-list.yaml │ ├── ingress-rspamd.yaml │ ├── pvc.yaml │ ├── secret.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ └── servicemonitor.yaml │ ├── tests │ ├── __snapshot__ │ │ ├── configmap_test.yaml.snap │ │ ├── deployment_test.yaml.snap │ │ ├── pvc_test.yaml.snap │ │ └── secret_test.yaml.snap │ ├── configmap_test.yaml │ ├── deployment_test.yaml │ ├── pvc_test.yaml │ └── secret_test.yaml │ └── values.yaml ├── helm.yaml └── renovate.json /.ci/ct-config.yaml: -------------------------------------------------------------------------------- 1 | # This file defines the config for "ct" (chart tester) used by the helm linting GitHub workflow 2 | 3 | lint-conf: .ci/lint-config.yaml 4 | target-branch: master 5 | validate-maintainers: false 6 | check-version-increment: false 7 | -------------------------------------------------------------------------------- /.ci/lint-config.yaml: -------------------------------------------------------------------------------- 1 | rules: 2 | # One blank line is OK 3 | empty-lines: 4 | max-start: 1 5 | max-end: 1 6 | max: 1 -------------------------------------------------------------------------------- /.ci/scripts/kube-score.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | KUBE_SCORE=${KUBE_SCORE:-kube-score} 4 | 5 | for chart in `ls charts`; 6 | do 7 | helm template --values charts/$chart/ci/ci-values.yaml charts/$chart | ${KUBE_SCORE} score - \ 8 | --ignore-test pod-networkpolicy \ 9 | --ignore-test deployment-has-poddisruptionbudget \ 10 | --ignore-test deployment-has-host-podantiaffinity \ 11 | --ignore-test pod-probes \ 12 | --ignore-test container-image-tag \ 13 | --enable-optional-test container-security-context-privileged \ 14 | --ignore-test container-security-context \ 15 | --ignore-test container-security-context-user-group-id \ 16 | --ignore-test container-security-context-readonlyrootfilesystem \ 17 | # 18 | done -------------------------------------------------------------------------------- /.ci/scripts/local-ct-lint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker run --rm -it -w /repo -v $(pwd):/repo quay.io/helmpack/chart-testing ct lint --all --config .ci/ct-config.yaml 4 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @funkypenguin 2 | -------------------------------------------------------------------------------- /.github/workflows/on-push-lint-charts.yml: -------------------------------------------------------------------------------- 1 | name: Lint and Test Charts 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'charts/**' 7 | - '.github/**' 8 | pull_request: 9 | paths: 10 | - 'charts/**' 11 | - '.github/**' 12 | workflow_dispatch: 13 | 14 | env: 15 | KUBE_SCORE_VERSION: 1.17.0 16 | HELM_VERSION: v3.13.2 17 | 18 | concurrency: 19 | group: ${{ github.ref }} 20 | cancel-in-progress: true 21 | 22 | jobs: 23 | lint-test: 24 | runs-on: ubuntu-latest 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v4 28 | with: 29 | fetch-depth: 0 30 | 31 | - name: Set up Helm 32 | uses: azure/setup-helm@v3 33 | with: 34 | version: ${{ env.HELM_VERSION }} 35 | 36 | - name: Set up kube-score 37 | run: | 38 | mkdir /tmp/bin 39 | wget https://github.com/zegl/kube-score/releases/download/v${{ env.KUBE_SCORE_VERSION }}/kube-score_${{ env.KUBE_SCORE_VERSION }}_linux_amd64 -O /tmp/bin/kube-score 40 | chmod 755 /tmp/bin/kube-score 41 | 42 | - name: Kube-score generated manifests 43 | env: 44 | KUBE_SCORE: /tmp/bin/kube-score 45 | run: .ci/scripts/kube-score.sh 46 | 47 | unittest: 48 | runs-on: ubuntu-latest 49 | steps: 50 | - name: Checkout 51 | uses: actions/checkout@v4 52 | with: 53 | fetch-depth: 0 54 | 55 | - name: install helm unittest 56 | run: | 57 | helm plugin install https://github.com/helm-unittest/helm-unittest.git 58 | 59 | - name: Run helm unittest 60 | run: helm unittest charts/* 61 | 62 | chart-testing: 63 | runs-on: ubuntu-latest 64 | strategy: 65 | matrix: 66 | # Choose from https://hub.docker.com/r/kindest/node/tags 67 | KubeVersion: [ 1.30.10, 1.31.6, 1.32.2] 68 | 69 | steps: 70 | - name: Checkout 71 | uses: actions/checkout@v4 72 | with: 73 | fetch-depth: 0 74 | 75 | # python is a requirement for the chart-testing action below (supports yamllint among other tests) 76 | - uses: actions/setup-python@v5 77 | with: 78 | python-version: 3.11 79 | 80 | - name: Set up chart-testing 81 | uses: helm/chart-testing-action@v2.7.0 82 | 83 | - name: Run chart-testing (list-changed) 84 | id: list-changed 85 | run: | 86 | changed=$(ct list-changed --config .ci/ct-config.yaml) 87 | if [[ -n "$changed" ]]; then 88 | echo "::set-output name=changed::true" 89 | fi 90 | 91 | - name: Run chart-testing (lint) 92 | run: ct lint --config .ci/ct-config.yaml 93 | 94 | - name: Create ${{matrix.KubeVersion}} kind cluster 95 | uses: helm/kind-action@v1.5.0 96 | with: 97 | node_image: kindest/node:v${{matrix.KubeVersion}} 98 | cluster_name: kubernetes-${{matrix.KubeVersion}} 99 | if: steps.list-changed.outputs.changed == 'true' 100 | 101 | - name: Run chart-testing (install) against ${{matrix.KubeVersion}} 102 | run: ct install --config .ci/ct-config.yaml -------------------------------------------------------------------------------- /.github/workflows/on-push-master-publish-chart.yml: -------------------------------------------------------------------------------- 1 | name: Publish helm chart 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - main # assume that the branch name may change in future 8 | paths: 9 | - 'charts/**' 10 | - '.github/**' 11 | workflow_dispatch: 12 | 13 | jobs: 14 | publish-chart: 15 | 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | with: 22 | fetch-depth: 0 23 | 24 | - name: Configure Git 25 | run: | 26 | git config user.name "$GITHUB_ACTOR" 27 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 28 | 29 | - name: Run chart-releaser 30 | uses: helm/chart-releaser-action@v1.7.0 31 | env: 32 | CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 33 | 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | docker-compose.yml 3 | .idea 4 | .env 5 | test/config/empty/ 6 | test/config/without-accounts/ 7 | test/config/without-virtual/ 8 | test/config/with-domain/ 9 | test/config/postfix-accounts.cf 10 | test/config/letsencrypt/mail.my-domain.com/combined.pem 11 | test/onedir 12 | config/opendkim/ 13 | *.secret 14 | helm-chart/docker-mailserver/config/opendkim 15 | myvalues.yml 16 | helm-chart/manifests 17 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # :wave: How can I contribute? 2 | 3 | First off, thank you for helping to improve this chart! :heart_eyes: :pray: 4 | 5 | ## Testing 6 | 7 | To test the chart locally, before submitting changes, run `./.ci/scripts/local-ct-lint.sh` 8 | 9 | ## Submitting changes 10 | 11 | Please send a [GitHub Pull Request](https://github.com/funkypenguin/helm-docker-mailserver/pull/new/master) with a clear list of what you've done (read more about [pull requests](http://help.github.com/pull-requests/)). 12 | 13 | When you send a pull request, please make sure all of your commits are atomic (one feature per commit), and bump the chart version in `chart.yaml` 14 | 15 | Always write a clear log message for your commits. One-line messages are fine for small changes, but bigger changes should look like this: 16 | 17 | $ git commit -m "A brief summary of the commit 18 | > 19 | > A paragraph describing what changed and its impact." 20 | 21 | Thanks again! 22 | Funky Penguin :penguin: 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2019 David Young 4 | Copyright 2020 The docker-mailserver Helm Chart Authors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # K8s Helm Chart for docker-mailserver 2 | 3 | This repostitory contains a helm chart to deploy [docker-mailserver](https://github.com/docker-mailserver/docker-mailserver) into a Kubernetes cluster. docker-mailserver is a production-ready, fullstack mail server that supports SMTP, IMAP, LDAP, Anti-spam, Anti-virus, etc.). Just as importantly, it is designed to be simple to install and configure. 4 | 5 | ## Documentation 6 | 7 | Documentation is in the chart's [README.md](charts/docker-mailserver/README.md). 8 | -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | # How this chart is tested 2 | 3 | # Automated tests 4 | 5 | Every pull request to the master branch trigger the following tests: 6 | 7 | * ct lint 8 | * ct install 9 | 10 | 11 | [![Linting](https://github.com/funkypenguin/helm-docker-mailserver/workflows/Linting/badge.svg)](.github/workflows/on-pr-lint-charts.yml) 12 | [![Testing](https://github.com/funkypenguin/helm-docker-mailserver/workflows/Testing/badge.svg)](.github/workflows/on-pr-test-charts.yml) 13 | 14 | 15 | # Local testing 16 | 17 | If you're submitting a PR, and you want to ensure your changes will pass automated testing (above), here are your options: 18 | 19 | ## Linting 20 | 21 | We use helm's [chart-testing](https://github.com/helm/chart-testing) tool to lint our charts. The tool can be installed locally, or it can be run in a Docker container. 22 | 23 | To run in Docker: 24 | 25 | 1. Have Docker installed 26 | 2. Run `.ci/scripts/local-ct-lint.sh` 27 | 28 | To run locally: 29 | 30 | 1. Have ct installed (Get a binary package from https://github.com/helm/chart-testing/releases) 31 | 2. Run `ct lint --config=.ci/ct-config.yaml` 32 | 33 | ## Deployment testing 34 | 35 | *ct* can also test a chart by deploying it to a temporary namespace in a Kubernetes cluster, and waiting for indications that the deployment has been successful. This is a good way to test how the deployment behaves "for real". 36 | 37 | 38 | 39 | 40 | ct lint --config=.ci/ct-config.yaml 41 | 42 | Create a KinD cluster, by running `kind create cluster`: 43 | 44 | ``` 45 | ❯ kind create cluster 46 | Creating cluster "kind" ... 47 | ✓ Ensuring node image (kindest/node:v1.17.0) 🖼 48 | ✓ Preparing nodes 📦 49 | ✓ Writing configuration 📜 50 | ✓ Starting control-plane 🕹️ 51 | ✓ Installing CNI 🔌 52 | ✓ Installing StorageClass 💾 53 | Set kubectl context to "kind-kind" 54 | You can now use your cluster with: 55 | 56 | kubectl cluster-info --context kind-kind 57 | 58 | Have a nice day! 👋 59 | ``` 60 | 61 | Trigger a `ct install` test against the KinD cluster, by running `t install --config=.ci/ct-config.yaml`. **ct** will target your current context (be careful if you've got multiple contexts configured!), create a temporary namespace, and deploy the chart into that namespace, until `helm --wait` indicates success. After this, the helm release will be removed, the namespace deleted, and you can retire your KinD cluster by running `kind delete cluster`. 62 | -------------------------------------------------------------------------------- /charts/docker-mailserver/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | tests/ 23 | -------------------------------------------------------------------------------- /charts/docker-mailserver/Chart.lock: -------------------------------------------------------------------------------- 1 | dependencies: [] 2 | digest: sha256:643d5437104296e21d906ecb15b2c96ad278f20cfc4af53b12bb6069bd853726 3 | generated: "2024-01-28T21:49:18.990692471-08:00" 4 | -------------------------------------------------------------------------------- /charts/docker-mailserver/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | appVersion: "15.0.2" 3 | description: A fullstack but simple mailserver (smtp, imap, antispam, antivirus, ssl...) using Docker. 4 | name: docker-mailserver 5 | version: 4.2.1 6 | sources: 7 | - https://github.com/docker-mailserver/docker-mailserver-helm 8 | maintainers: 9 | - name: funkypenguin 10 | email: davidy@funkypenguin.co.nz 11 | keywords: 12 | - mailserver 13 | - postfix 14 | - dovecot 15 | - amavis 16 | - imap 17 | home: https://github.com/funkypenguin/helm-docker-mailserver 18 | icon: https://avatars.githubusercontent.com/u/76868633?s=400&v=4 19 | 20 | annotations: 21 | artifacthub.io/changes: | 22 | - Breaking : Standardized app labels to app.kubernetes.io/name for Istio workload/Cilium compatibility 23 | 24 | dependencies: [] 25 | -------------------------------------------------------------------------------- /charts/docker-mailserver/OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - funkypenguin 3 | reviewers: 4 | - funkypenguin -------------------------------------------------------------------------------- /charts/docker-mailserver/README.md: -------------------------------------------------------------------------------- 1 | # docker-mailserver Helm Chart 2 | 3 | ## Contents 4 | 5 | - [Introduction](#introduction) 6 | - [Prerequisites](#prerequisites) 7 | - [Getting Started](#getting-started) 8 | - [Configuration](#configuration) 9 | - [Volume](#volume) 10 | - [ConfigMaps](#configmaps) 11 | - [Secrets](#secrets) 12 | - [Values YAML](#values-yaml) 13 | - [Environment Variables](#environment-variables) 14 | - [Minimal Configuration](#minimal-configuration) 15 | - [Certificate](#certificate) 16 | - [Ports](#ports) 17 | - [Persistence](#persistence) 18 | - [Backing Storage](#backing-storage) 19 | - [Generic / All](#generic--all) 20 | - [NFS](#nfs) 21 | - [Upgrading to Version 3.0.0](#upgrading-to-version-3) 22 | - [Development](#development) 23 | - [Testing](#testing) 24 | 25 | (Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc.go)) 26 | 27 | ## Introduction 28 | 29 | This chart deploys [docker-mailserver](https://github.com/docker-mailserver/docker-mailserver) into a 30 | Kubernetes cluster. docker-mailserver is a production-ready, fullstack mail server that supports SMTP, IMAP, LDAP, Anti-spam, Anti-virus, etc.). Just as importantly, it is designed to be simple to install and configure. 31 | 32 | !!WARNING!! - Version 3.0.0 is not backwards compatible with previous versions. Please refer to the [upgrade](#upgrading-to-version-3) section for more information. 33 | 34 | ## Prerequisites 35 | 36 | - [Helm](https://helm.sh) 37 | - A [Kubernetes](https://kubernetes.io/releases/) cluster with persistent storage and access to email [ports](https://docker-mailserver.github.io/docker-mailserver/latest/config/security/understanding-the-ports/#overview-of-email-ports) 38 | - A custom domain name (for example, example.com) 39 | - Correctly configured [DNS](https://docker-mailserver.github.io/docker-mailserver/latest/usage/#minimal-dns-setup) 40 | - [Cert Manager](https://cert-manager.io/docs/) or a similar tool to create and renew TLS certificates 41 | 42 | ## Getting Started 43 | 44 | Setting up docker-mailserver requires generating a number of configuration [files](https://docker-mailserver.github.io/docker-mailserver/latest/config/advanced/optional-config/). To make this easier, docker-mailserver includes a `setup` command that can generate these files. 45 | 46 | To get started, first manually create a TLS Certificate, setting `metadata.name` and `spec.secretName` to the same value. Also set the fully-qualified domain name for your mail server in `spec.dnsNames` and `spec.issuerRef.name` to the name of an Issuer or ClusterIssuer, and `spec.issuerRef.kind` to `Issuer` or `ClusterIssuer`. 47 | ```yaml 48 | apiVersion: cert-manager.io/v1 49 | kind: Certificate 50 | 51 | metadata: 52 | name: mail-tls-certificate-rsa 53 | 54 | spec: 55 | secretName: mail-tls-certificate-rsa 56 | isCA: false 57 | privateKey: 58 | algorithm: RSA 59 | encoding: PKCS1 60 | size: 2048 61 | dnsNames: [mail.example.com] 62 | issuerRef: 63 | name: letsencrypt-production 64 | kind: Issuer 65 | ``` 66 | ```console 67 | kubectl apply -f certificate.yaml --namespace mail 68 | ``` 69 | 70 | Then add the helm repo: 71 | ```console 72 | helm repo add docker-mailserver https://docker-mailserver.github.io/docker-mailserver-helm 73 | ``` 74 | 75 | Create a Helm values file. See the comments in [values.yaml](https://github.com/docker-mailserver/docker-mailserver-helm/blob/master/charts/docker-mailserver/values.yaml) to understand all the options, or create a minimal file like this (where `mail-tls-certificate-rsa` is the name of the certificate you previously created and `example.com` is the name of your domain): 76 | ```yaml 77 | ## Specify the name of a TLS secret that contains a certificate and private key for your email domain. 78 | ## See https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets 79 | certificate: mail-tls-certificate-rsa 80 | 81 | deployment: 82 | env: 83 | OVERRIDE_HOSTNAME: example.com # You must OVERRIDE this! 84 | ``` 85 | 86 | Then install docker-mailserver using the values file: 87 | 88 | ```console 89 | helm upgrade --install docker-mailserver docker-mailserver/docker-mailserver --namespace mail --create-namespace -f values.yaml 90 | ``` 91 | 92 | Next open a command prompt to the running container. 93 | 94 | ```console 95 | kubectl exec -it --namespace mail deploy/docker-mailserver -- bash 96 | ``` 97 | 98 | And now create a new account for Postfix and Dovecot. 99 | 100 | ```console 101 | kubectl exec -it --namespace mail deploy/docker-mailserver -- bash 102 | 103 | setup email add user@example.com password 104 | ``` 105 | 106 | Alternatively you can do it one step like this: 107 | 108 | ```console 109 | $kubectl exec -it --namespace mail deploy/docker-mailserver -- setup email add user@example.com password 110 | ``` 111 | 112 | Account information will be saved in a file `postfix-accounts.cf` in the container path: 113 | 114 | ```console 115 | cat /tmp/docker-mailserver/postfix-accounts.cf 116 | ``` 117 | 118 | This path is [mapped](#persistence) to a Kubernetes Volume. 119 | 120 | ## Configuration 121 | 122 | Assuming you still have a command prompt [open](#getting-started) in the running container, run the setup command to see additional configuration options: 123 | 124 | ```console 125 | setup 126 | ``` 127 | 128 | As you run various setup commands, additional files will be generated. At a minimum you will want to run: 129 | 130 | ```console 131 | setup email add user@example.com password 132 | setup config dkim keysize 2048 domain 'example.com' 133 | ``` 134 | 135 | These paths are stored to the container path `/tmp/docker-mailserver` which is [mapped](#persistence) to a Kubernetes Volume. 136 | 137 | ### Volume 138 | 139 | Configuration files are stored on a Kubernetes [volume](#persistence) mounted at `/tmp/docker-mailserver` in the container. The PVC is named `mail-config`. You can of course add additional configuration files to the volume as needed. 140 | 141 | ### ConfigMaps 142 | 143 | Its is also possible to use ConfigMaps to mount configuration files in the container. This is done by adding to the `configFiles` key in a custom `values.yaml` file. For more information please see the [documentation](./values.yaml#L453) in values.yaml 144 | 145 | ### Secrets 146 | 147 | Secrets can also be used to mount configuration files in the container. For example, dkim keys could be stored in a secret as opposed to a file in the `mail-config` volume. Once again, for more information please see the [documentation](./values.yaml#L610) in values.yaml 148 | 149 | ## Values YAML 150 | 151 | In addition to the configuration files generated above, the `values.yaml` file contains a number of knobs for customizing the docker-mailserver installation. Please refer to the extensive comments in [values.yaml](./values.yaml) for additional information. 152 | 153 | ### Environment Variables 154 | 155 | Included in the knobs are **many** environment variables which allow you to customize the behaviour of `docker-mailserver`. These environment variables are documented in the `docker-mailserver's` [configuration](https://docker-mailserver.github.io/docker-mailserver/latest/config/environment/) page. Note that `docker-mailserver` expects any true/false values to be set as numbers (1/0) rather than boolean values (true/false). 156 | 157 | By default, the Chart enables `rspamd` and disables `opendkim`, `dmarc`, `policyd-spf` and `clamav`. This is the setup [recommended](https://docker-mailserver.github.io/docker-mailserver/latest/config/best-practices/dkim_dmarc_spf/) by the `docker-mailserver` project. 158 | 159 | Once you have created your own values.yaml files, then redeploy the chart like this: 160 | 161 | ```console 162 | helm upgrade docker-mailserver docker-mailserver --namespace mail --values 163 | ``` 164 | 165 | You can also override individual configuration setting with `helm upgrade --set`, specifying each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example: 166 | 167 | ```console 168 | $helm upgrade docker-mailserver docker-mailserver --namespace mail --set pod.dockermailserver.image="your/image:1.0.0" 169 | ``` 170 | 171 | ### Minimal Configuration 172 | 173 | There are various settings in `values.yaml` that you must override. 174 | 175 | | Parameter | Description | Default | 176 | | ------------------------------------ | ------------------------------------ | ---------------- | 177 | | deployment.env.[OVERRIDE_HOSTNAME](https://docker-mailserver.github.io/docker-mailserver/latest/config/environment/#override_hostname) | The hostname to be presented on SMTP banners | mail.example.com | 178 | | `certificate` | Name of a Kubernetes secret that stores TLS certificate for your mail domain | | 179 | 180 | ### Certificate 181 | 182 | You will need to setup a TLS certificate for your email domain. The easiest way to do this is use [cert-manager](https://cert-manager.io/). 183 | 184 | Once you acquire a certificate, you will need to store it in a TLS secret in the docker-mailserver namespace. Once you have done that, update the values.yaml file like this: 185 | 186 | ```yaml 187 | certificate: my-certificate-secret 188 | ``` 189 | 190 | The chart will then automatically copy the certificate and private key to the `/tmp/dms/custom-certs` director in the container and correctly set the `SSL_CERT_PATH` and `SSL_KEY_PATH` environment variables. 191 | 192 | ## Ports 193 | 194 | If you are running on a bare-metal Kubernetes cluster, you will have to expose ports to the internet to receive and send emails. In addition, you need to make sure that `docker-mailserver`` receives the correct client IP address so that spam filtering works. 195 | 196 | This can get a bit complicated, as explained in the `docker-mailserver` [documentation](https://docker-mailserver.github.io/docker-mailserver/latest/config/advanced/kubernetes/#exposing-your-mail-server-to-the-outside-world). 197 | 198 | One approach to preserving the client IP address is to use the PROXY protocol, which is explained in the [documentation](https://docker-mailserver.github.io/docker-mailserver/latest/config/advanced/kubernetes/#proxy-port-to-service-via-proxy-protocol). 199 | 200 | The Helm chart supports the use of the proxy protocol via the `proxyProtocol` key. To enable it set the `proxyProtocol.enable` key to true. You will also want to set the `trustedNetworks` key. 201 | 202 | ```yaml 203 | proxyProtocol: 204 | enabled: true 205 | # List of sources (in CIDR format, space-separated) to permit PROXY protocol from 206 | trustedNetworks: "10.0.0.0/8 192.168.0.0/16 172.16.0.0/16" 207 | ``` 208 | 209 | Enabling the PROXY protocol will create an additional port for each protocol (by adding 10,000 to the standard port value) that is configured to understand the PROXY protocol. Thus: 210 | 211 | | Protocol | Port | PROXY Port | 212 | | ---------- | ------- | ----------- | 213 | | submissions | 465 | 10465 | 214 | | submission | 587 | 10587 | 215 | | imap | 143 | 10143 | 216 | | imaps | 993 | 10993 | 217 | | pop3 | 110 | 10110 | 218 | | pop3s | 995 | 10995 | 219 | 220 | If you do not enable the PROXY protocol and your mail server is not exposed using a load-balancer service with an external traffic policy in "Local" mode, then all incoming mail traffic will look like it comes from a local Kubernetes cluster IP. 221 | 222 | ## Persistence 223 | 224 | Docker-mailserver assumes there are [four](https://docker-mailserver.github.io/docker-mailserver/latest/config/advanced/optional-config/#volumes) mounted volumes: 225 | 226 | * mail-config 227 | * mail-data 228 | * mail-state 229 | * mail-log 230 | 231 | Therefore the chart requests four PersistentVolumeClaims under the `persistent_volume_claims` key. Each PVC can be set to an existing claim by setting the `persistent_volume_claims..existing_claim` key or a new claims. To disable creation of a PVC, set `persistent_volume_claims..enabled` to false. The default PVCs have the following characteristics: 232 | 233 | | PVC Name | Default Size | Mount | Description | 234 | | ---------- | ------- | ----------------------- | -------------------------------------| 235 | | mail-config | 1Mi | /tmp/docker-mailserver | Stores generated [configuration](https://docker-mailserver.github.io/docker-mailserver/latest/faq/#what-about-the-docker-datadmsconfig-directory) files | 236 | | mail-data | 10Gi | /var/mail | Stores emails | 237 | | mail-state | 1Gi | /var/mail-state | Stores [state](https://docker-mailserver.github.io/docker-mailserver/latest/faq/#what-about-the-docker-datadmsmail-state-directory) for mail services | 238 | | mail-log | 1Gi | /var/log/mail | Stores log files | 239 | 240 | The PVCs are mounted to `volumeMounts` via the `persistence` key. Each `volumeMount` must specify a volume name and mount path. It is also possbile to set a subpath via the `subPath` key. 241 | 242 | Certain PV storage types may recommend or require additional external configuration. For more information, see the [Backing Storage](#backing-storage) section. 243 | 244 | Extra volumes and volume mounts may be added using the `extraVolumes` and `extraVolumeMounts` keys. 245 | 246 | ### Backing Storage 247 | 248 | This section contains configuration tweaks and quirks related to various PersistentVolume types. This section has been verified as of May 10, 2025. 249 | 250 | Common CSI driver-backed storage providers (such as various block storage providers) have not currently been tested while writing this section, but generic recommendations may still apply. 251 | 252 | #### Generic / All 253 | 254 | The DMS container image used inside this chart currently does not forcibly harden the permissions of the recommended persistent volume mounts. It does change ownership for directories where different services need it. 255 | 256 | For any posix-backed storage it is recommended to adjust the Unix octal permissions of `0755` (u:rwx, g:rx, o:rx) if they are not already. Additionally, the primary file ACL for the directory should be set to `u::rwx,g::rx,o:rx` if subPaths are going to be used to map multiple volume mounts to a single PersistentVolume. 257 | 258 | The DMS chart is currently not tested for replication, high availability. If subPaths are being used to merge multiple volume mount points to one PersistentVolume, this may potentially break being able to run with high availaility should it be actively tested in the future. 259 | 260 | #### NFS 261 | 262 | Docker Mailserver (the container) currently assumes that local posix-based storage (e.g. local or hostPath fs drivers) is used, and doesn't fully work with standard writable NFS shares (tested against NFS 4.2). Using fsGroup in the pod's securityContext won't help in this case as the container's root nor any other user seems to get it applied as a supplementary group. 263 | 264 | The current alternative is to apply the `no_root_squash` flag to any backing NFS shares, as well as ensure root ownership initially. If you do not know the caveats of [using the no_root_squash flag](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/4/html/security_guide/s2-server-nfs-noroot) and/or cannot properly mitigate the potential risk from using it, **consider not using NFS shares as backing storage at this time**. 265 | 266 | The reason `no_root_squash` is currently required is due to how DMS does initial fs setup. The container currently utilizes a lot of post-init directory creation and ownership changing done as root. 267 | 268 | DMS does not use techniques such as permissive initial directory creation that is locked down after various service users have made their respectively-owned subdirectories. 269 | 270 | Quirks from the generic section also apply to NFS-backed PersistentVolumes. 271 | 272 | ## Upgrading to Version 5 273 | Version 5.0 upgrades docker-mailserver to version 15. This version of the chart *does* include backwards incompatible changes 274 | 275 | ### PersistentVolumeClaims 276 | 277 | Previously by default the Chart created four persistent volume claims and then mounted them to the container. This made it difficult for users that want to use just one Volume. Therefore the `persistence` key was spit into two keys: 278 | 279 | * `persistent_volume_claims` 280 | * `persistence` 281 | 282 | This separate the creation of PVCs from mounting their associated volumes. If you previously overrode the creation of PVCs or their mount paths you will need to update your custom `values.yaml` file. 283 | 284 | ## Upgrading to Version 4 285 | Version 4.0 upgrades docker-mailserver to version 14. There are no backwards incompatible changes in the chart. 286 | 287 | ## Upgrading to Version 3 288 | 289 | Version 3.0 is not backwards compatible with previous versions. The biggest changes include: 290 | 291 | - Usage of four PersistentVolumeClaims (PVCs) instead of one 292 | - Usage of a PVC to store configuration files 293 | - Rearrangement of keys in `values.yaml` 294 | - Removal of RainLoop and HaProxy 295 | - Removal of Cert Manager 296 | - Enable rspamd by default 297 | 298 | ### PersistentVolumeClaims 299 | 300 | Previously the Chart created a single PVC to store emails, logs and the state of various `docker-mailserver` components. Now the Chart creates four PVCs, as described in the [persistence](#persistence) section. One of the PVCs is `mail-config` which is used to store configuration files. 301 | 302 | The addition of the `mail-config` PVC removes the requirement to use the `setup.sh` script and its dependency on Docker or Podman. Instead, you can directly deploy the chart to a Kubernetes cluster. For more information see the [configuration files](#configuration) section. 303 | 304 | To upgrade you will need to copy data from the existing PersistentVolume (PV) to one of the new PVs: 305 | 306 | | Original PV | Path | New PV | Path | 307 | | ----------------- | -----------| -----------|-------| 308 | | docker-mailserver | mail-data | mail-data | / | 309 | | docker-mailserver | mail-state | mail-state | / | 310 | | docker-mailserver | mail-log | mail-log | / | 311 | 312 | ### Rearrangement of keys 313 | 314 | The location of a number of keys has changed in the chart. Please see `values.yaml` for the changed locations. 315 | 316 | ### Rspamd 317 | 318 | The Chart now enables Rpsamd by default as recommened by the `docker-mailserver` documentation. You can disable this change by setting the environment variable `ENABLE_RSPAMD` to 0 and setting `ENABLE_OPENDKIM`, `ENABLE_OPENDMARC` and `ENABLE_POLICYD_SPF` to 1. 319 | 320 | If you keep this change, you will need to generate new DKIM signing keys (see the [configuration](#configuration) section for more information). In addition, you may wish to enable the Rspamd ingress (see `rspamd.ingress.enabled`) 321 | 322 | ### TLS 323 | 324 | Support for creating a TLS certificate using `cert-manager` has been removed. Instead, create a secret that contains a certificate *before* installing the chart and reference it via the `certificate` key. Of course you can use `cert-manager` to create this secret - it is just not part of this chart anymore. 325 | 326 | ### Proxy 327 | 328 | Support for installing HaProxy with the Chart has been removed. Instead, generic support for the Proxy protocol has been [added](#proxy). 329 | 330 | ## Development 331 | 332 | ### Testing 333 | 334 | [Unit tests](https://github.com/lrills/helm-unittest) are created for every chart template. Tests are applied to confirm expected behaviour and interaction between various configurations. 335 | 336 | In addition to tests above, a "snapshot" test is created for each manifest file. This permits a final test per-manifest, which confirms that the generated manifest matches exactly the previous snapshot. If a template change is made, or legit value in values.yaml changes (i.e., the app version) this snapshot test will fail. 337 | 338 | If you're comfortable with the changes to the saved snapshot, then regenerate the snapshots, by running the following from the root of the repo 339 | 340 | ```console 341 | helm plugin install https://github.com/helm-unittest/helm-unittest.git 342 | helm unittest -u charts/docker-mailserver 343 | ``` 344 | -------------------------------------------------------------------------------- /charts/docker-mailserver/ci/ci-haproxy.yaml: -------------------------------------------------------------------------------- 1 | service: 2 | type: ClusterIP 3 | -------------------------------------------------------------------------------- /charts/docker-mailserver/ci/ci-values.yaml: -------------------------------------------------------------------------------- 1 | service: 2 | type: ClusterIP 3 | 4 | configMaps: 5 | postfix-accounts.cf: 6 | create: true 7 | path: postfix-accounts.cf 8 | data: | 9 | user@example.com|{SHA512-CRYPT}$6$PLsyDsD5kMTmQbe/$b1jT8MvuoBfs/JeBQ9fBQ0JlnWJZ377SW/OxSlNe7ldjgRQ7K4ysGfM6OpkkxQkAu7c7pR7EAR5Y4aIty2/Qi. 10 | 11 | image: 12 | # Makes kube-score happy, otherwise it complains about the default pullPlicy of "IfNotPresent" 13 | pullPolicy: Always 14 | -------------------------------------------------------------------------------- /charts/docker-mailserver/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | GOOD NEWS! 2 | ==================== 3 | 4 | You've successfully installed the docker-mailserver helm chart! 5 | 6 | Initial Setup 7 | ------------ 8 | 9 | If you have not yet configured your mail server you'll need to quickly open a command 10 | prompt inside the running container (you have two minutes) and setup a first email account. 11 | 12 | kubectl exec -it --namespace mail deploy/docker-mailserver -- bash 13 | 14 | setup email add user@example.com password 15 | 16 | This will create a file: 17 | 18 | cat /tmp/docker-mailserver/postfix-accounts.cf 19 | 20 | Next, run the setup command to see additional options: 21 | 22 | setup 23 | 24 | For more information please refer to this Chart's README file. 25 | 26 | {{ if .Values.proxyProtocol.enabled -}} 27 | 28 | Proxy Ports 29 | ------------ 30 | You have enabled PROXY protocol support, likely because you are running on a bare metal Kubernetes cluster. This means additional ports have been created that are configured for the PROXY protocol. These ports are in the 10,000 range - thus IMAPs is 10993 (10000 + 993), SUBMISSION is 10587 (10000 + 587), etc. 31 | 32 | It is now up to you to configure incoming traffic to use these ports. For more information please refer to this Chart's README file. 33 | {{ end }} -------------------------------------------------------------------------------- /charts/docker-mailserver/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{define "dockermailserver.name"}}{{default "dockermailserver" .Values.nameOverride | trunc 63 | trimSuffix "-" }}{{end}} 6 | 7 | {{/* 8 | Create a default fully qualified app name. 9 | 10 | {{/* 11 | Create a default fully qualified app name. 12 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 13 | If release name contains chart name it will be used as a full name. 14 | */}} 15 | {{- define "dockermailserver.fullname" -}} 16 | {{- if .Values.fullnameOverride -}} 17 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 18 | {{- else -}} 19 | {{- $name := default .Chart.Name .Values.nameOverride -}} 20 | {{- if contains $name .Release.Name -}} 21 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 22 | {{- else -}} 23 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 24 | {{- end -}} 25 | {{- end -}} 26 | {{- end -}} 27 | 28 | {{/* 29 | Create the name of the controller service account to use 30 | */}} 31 | {{- define "dockermailserver.serviceAccountName" -}} 32 | {{- if .Values.serviceAccount.create -}} 33 | {{ default (include "dockermailserver.fullname" .) .Values.serviceAccount.name }} 34 | {{- else -}} 35 | {{ default "docker-mailserver" .Values.serviceAccount.name }} 36 | {{- end -}} 37 | {{- end -}} 38 | 39 | {{/* 40 | Renders a value that contains template perhaps with scope if the scope is present. 41 | Usage: 42 | {{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} 43 | {{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} 44 | */}} 45 | {{- define "common.tplvalues.render" -}} 46 | {{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} 47 | {{- if contains "{{" (toJson .value) }} 48 | {{- if .scope }} 49 | {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} 50 | {{- else }} 51 | {{- tpl $value .context }} 52 | {{- end }} 53 | {{- else }} 54 | {{- $value }} 55 | {{- end }} 56 | {{- end -}} 57 | -------------------------------------------------------------------------------- /charts/docker-mailserver/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- range $name, $config := .Values.configMaps }} 2 | {{- if $config.create }} 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | labels: 7 | app.kubernetes.io/name: {{ template "dockermailserver.fullname" $ }} 8 | chart: "{{ $.Chart.Name }}-{{ $.Chart.Version }}" 9 | heritage: "{{ $.Release.Service }}" 10 | release: "{{ $.Release.Name }}" 11 | name: {{ regexReplaceAll "[.]" $name "-" }} 12 | data: 13 | {{ $config.key | default $name }}: | 14 | {{ tpl $config.data $ | indent 6 }} 15 | --- 16 | {{- end }} 17 | {{- end }} -------------------------------------------------------------------------------- /charts/docker-mailserver/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: "apps/v1" 3 | kind: "Deployment" 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: {{ template "dockermailserver.fullname" . }} 7 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 8 | heritage: "{{ .Release.Service }}" 9 | release: "{{ .Release.Name }}" 10 | {{- if .Values.deployment.labels }} 11 | {{ toYaml .Values.deployment.labels | indent 4 }} 12 | {{ end }} 13 | name: {{ template "dockermailserver.fullname" . }} 14 | {{- if .Values.deployment.annotations }} 15 | annotations: 16 | {{ toYaml .Values.deployment.annotations | indent 4 }} 17 | {{ end }} 18 | spec: 19 | replicas: {{ .Values.deployment.replicas }} 20 | selector: 21 | matchLabels: 22 | app.kubernetes.io/name: {{ template "dockermailserver.fullname" . }} 23 | release: "{{ .Release.Name }}" 24 | strategy: {{- toYaml .Values.deployment.strategy | nindent 4 }} 25 | template: 26 | metadata: 27 | labels: 28 | app.kubernetes.io/name: {{ template "dockermailserver.fullname" . }} 29 | release: "{{ .Release.Name }}" 30 | {{- if .Values.deployment.labels }} 31 | {{ toYaml .Values.deployment.labels | indent 8 }} 32 | {{ end }} 33 | {{- if .Values.deployment.annotations }} 34 | annotations: 35 | {{ toYaml .Values.deployment.annotations | indent 8 }} 36 | {{ end }} 37 | spec: 38 | {{- if .Values.deployment.affinity }} 39 | affinity: {{- toYaml .Values.deployment.affinity | nindent 8 }} 40 | {{ end }} 41 | nodeSelector: {{- toYaml .Values.deployment.nodeSelector | nindent 8 }} 42 | runtimeClassName: {{ .Values.deployment.runtimeClassName }} 43 | priorityClassName: {{ .Values.deployment.priorityClassName }} 44 | restartPolicy: "Always" 45 | serviceAccountName: {{ template "dockermailserver.serviceAccountName" . }} 46 | securityContext: 47 | {{ toYaml .Values.securityContext | indent 8 }} 48 | {{- if .Values.deployment.tolerations }} 49 | tolerations: {{- toYaml .Values.deployment.tolerations | nindent 8 }} 50 | {{ end }} 51 | volumes: 52 | # ConfigMaps 53 | {{- range $name, $config := .Values.configMaps }} 54 | - name: {{ regexReplaceAll "[.]" $name "-" }} 55 | configMap: 56 | name: {{ regexReplaceAll "[.]" $name "-" }} 57 | {{- end }} 58 | 59 | # Secrets 60 | {{- range $name, $secret := .Values.secrets }} 61 | - name: {{ regexReplaceAll "[.]" $name "-" }} 62 | secret: 63 | secretName: {{ regexReplaceAll "[.]" $name "-" }} 64 | {{- end }} 65 | 66 | # Certificate 67 | {{- if .Values.certificate }} 68 | - name: certificate 69 | secret: 70 | secretName: {{ .Values.certificate }} 71 | {{- end }} 72 | 73 | # PVCs 74 | {{- range $name, $pvc := .Values.persistent_volume_claims }} 75 | {{- if $pvc.enabled }} 76 | - name: {{ $name }} 77 | persistentVolumeClaim: 78 | {{- if $pvc.existingClaim}} 79 | claimName: {{ $pvc.existingClaim }} 80 | {{ else }} 81 | claimName: {{ template "dockermailserver.fullname" $ }}-{{ $name }} 82 | {{ end }} 83 | {{- end }} 84 | {{- end }} 85 | 86 | # Extra volumes 87 | {{- with .Values.deployment.extraVolumes }} 88 | {{- toYaml . | nindent 8 }} 89 | {{- end }} 90 | 91 | {{- if .Values.deployment.initContainers }} 92 | initContainers: 93 | {{- with .Values.deployment.initContainers }} 94 | {{- toYaml . | nindent 8 }} 95 | {{- end }} 96 | {{- end }} 97 | 98 | containers: 99 | - name: docker-mailserver 100 | image: {{ .Values.image.name }}:{{ default .Chart.AppVersion .Values.image.tag }} 101 | imagePullPolicy: {{ .Values.image.pullPolicy }} 102 | env: 103 | {{- range $pkey, $pval := .Values.deployment.env }} 104 | - name: {{ $pkey }} 105 | {{- if kindIs "map" $pval }} 106 | {{- toYaml $pval | nindent 12 }} 107 | {{- else }} 108 | value: {{ quote $pval }} 109 | {{- end }} 110 | {{- end }} 111 | 112 | {{- if .Values.certificate }} 113 | - name: SSL_TYPE 114 | value: manual 115 | - name: SSL_CERT_PATH 116 | value: /tmp/dms/custom-certs/tls.crt 117 | - name: SSL_KEY_PATH 118 | value: /tmp/dms/custom-certs/tls.key 119 | {{- end }} 120 | 121 | {{- if .Values.deployment.secretEnvironments }} 122 | envFrom: 123 | {{- range .Values.deployment.secretEnvironments }} 124 | - secretRef: 125 | name: {{ . | quote }} 126 | {{- end }} 127 | {{- end }} 128 | 129 | resources: 130 | {{ toYaml .Values.deployment.resources | indent 12 }} 131 | securityContext: 132 | {{- if eq .Values.deployment.env.ENABLE_FAIL2BAN 1.0 }} 133 | capabilities: 134 | add: 135 | - "NET_ADMIN" 136 | {{ end }} 137 | {{ toYaml .Values.deployment.containerSecurityContext | indent 12 }} 138 | 139 | volumeMounts: 140 | # Certificate 141 | {{- if .Values.certificate }} 142 | - name: certificate 143 | mountPath: /tmp/dms/custom-certs 144 | readOnly: true 145 | {{- end }} 146 | 147 | # Config via ConfigMaps 148 | {{- range $name, $config := .Values.configMaps }} 149 | - name: {{ regexReplaceAll "[.]" $name "-" }} 150 | subPath: {{ $config.key | default $name }} 151 | {{- if isAbs $config.path }} 152 | mountPath: {{ $config.path }} 153 | {{- else }} 154 | mountPath: /tmp/docker-mailserver/{{ $config.path }} 155 | {{- end }} 156 | {{- end }} 157 | 158 | # Config via Secrets 159 | {{- range $name, $secret := .Values.secrets }} 160 | - name: {{ regexReplaceAll "[.]" $name "-" }} 161 | subPath: {{ $secret.key | default $name }} 162 | {{- if isAbs $secret.path }} 163 | mountPath: {{ $secret.path }} 164 | {{- else }} 165 | mountPath: /tmp/docker-mailserver/{{ $secret.path }} 166 | {{- end }} 167 | {{- end }} 168 | 169 | # Mount Volumes 170 | {{- range $name, $persistence := .Values.persistence }} 171 | - name: {{ $persistence.volumeName }} 172 | mountPath: {{ $persistence.mountPath }} 173 | {{- if $persistence.subPath }} 174 | subPath: {{ $persistence.subPath }} 175 | {{- end }} 176 | {{- end }} 177 | 178 | # Mount Extra Volumes 179 | {{- with $.Values.deployment.extraVolumeMounts }} 180 | {{- toYaml . | nindent 12 }} 181 | {{- end }} 182 | 183 | livenessProbe: 184 | exec: 185 | command: 186 | - /bin/bash 187 | - -c 188 | - supervisorctl status | grep -E "amavis|clamav|cron|dovecot|mailserver|opendkim|opendmarc|postfix|rsyslog" | grep RUNNING 189 | initialDelaySeconds: 10 190 | timeoutSeconds: 5 191 | failureThreshold: 3 192 | readinessProbe: 193 | exec: 194 | command: 195 | - /bin/bash 196 | - -c 197 | - supervisorctl status | grep -E "mailserver|postfix" | grep RUNNING 198 | initialDelaySeconds: 10 199 | timeoutSeconds: 5 200 | failureThreshold: 3 201 | ports: 202 | - name: smtp 203 | containerPort: 25 204 | 205 | - name: submissions 206 | containerPort: 465 207 | - name: submission 208 | containerPort: 587 209 | {{- if .Values.proxyProtocol.enabled }} 210 | - name: smtp-proxy 211 | containerPort: 12525 212 | - name: subs-proxy 213 | containerPort: 10465 214 | - name: sub-proxy 215 | containerPort: 10587 216 | {{- end }} 217 | 218 | {{- if and (.Values.deployment.env.ENABLE_IMAP) (not .Values.deployment.env.SMTP_ONLY) }} 219 | - name: imap 220 | containerPort: 143 221 | - name: imaps 222 | containerPort: 993 223 | {{- if .Values.proxyProtocol.enabled }} 224 | - name: imap-proxy 225 | containerPort: 10143 226 | - name: imaps-proxy 227 | containerPort: 10993 228 | {{- end }} 229 | {{- end }} 230 | 231 | {{- if and (.Values.deployment.env.ENABLE_POP3) (not .Values.deployment.env.SMTP_ONLY) }} 232 | - name: pop3 233 | containerPort: 110 234 | - name: pop3s 235 | containerPort: 995 236 | {{- if .Values.proxyProtocol.enabled }} 237 | - name: pop3-proxy 238 | containerPort: 10110 239 | - name: pop3s-proxy 240 | containerPort: 10995 241 | {{- end }} 242 | {{- end }} 243 | 244 | {{- if .Values.deployment.env.ENABLE_RSPAMD }} 245 | - name: rspamd 246 | containerPort: 11334 247 | {{- end }} 248 | 249 | {{- if and (.Values.deployment.env.ENABLE_MANAGESIEVE) (not .Values.deployment.env.SMTP_ONLY) }} 250 | - name: managesieve 251 | containerPort: 4190 252 | {{- if .Values.proxyProtocol.enabled }} 253 | - name: managesieve-proxy 254 | containerPort: 14190 255 | {{- end }} 256 | {{- end }} 257 | 258 | {{- if .Values.metrics.enabled }} 259 | - name: metrics-exporter 260 | image: {{ .Values.metrics.image.name }}:{{ .Values.metrics.image.tag }} 261 | imagePullPolicy: {{ .Values.metrics.image.pullPolicy }} 262 | command: ["/bin/postfix_exporter"] 263 | args: 264 | - "--postfix.showq_path" 265 | - "/var/mail-state/spool-postfix/public/showq" 266 | - "--postfix.logfile_path" 267 | - "/var/log/mail/mail.log" 268 | 269 | ports: 270 | - containerPort: 9154 271 | name: http 272 | protocol: TCP 273 | resources: 274 | {{ toYaml .Values.metrics.resources | indent 12 }} 275 | securityContext: 276 | {{ toYaml .Values.deployment.containerSecurityContext | indent 12 }} 277 | 278 | volumeMounts: 279 | {{- range $name, $persistence := pick .Values.persistence "mail-log" "mail-state" }} 280 | - name: {{ $name }} 281 | mountPath: {{ $persistence.mountPath }} 282 | {{- end }} 283 | {{- end }} 284 | -------------------------------------------------------------------------------- /charts/docker-mailserver/templates/extra-list.yaml: -------------------------------------------------------------------------------- 1 | {{- /* 2 | Copyright Broadcom, Inc. All Rights Reserved. 3 | SPDX-License-Identifier: APACHE-2.0 4 | */}} 5 | 6 | {{- range .Values.extraDeploy }} 7 | --- 8 | {{ include "common.tplvalues.render" (dict "value" . "context" $) }} 9 | {{- end }} 10 | -------------------------------------------------------------------------------- /charts/docker-mailserver/templates/ingress-rspamd.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (.Values.deployment.env.ENABLE_RSPAMD) (.Values.rspamd.ingress.enabled) -}} 2 | apiVersion: networking.k8s.io/v1 3 | kind: Ingress 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: {{ template "dockermailserver.fullname" . }} 7 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 8 | heritage: "{{ .Release.Service }}" 9 | release: "{{ .Release.Name }}" 10 | name: {{ template "dockermailserver.fullname" . }}-rspamd 11 | {{- with .Values.rspamd.ingress.annotations }} 12 | annotations: 13 | {{ toYaml . | indent 4 }} 14 | {{- end }} 15 | spec: 16 | ingressClassName: {{ .Values.rspamd.ingress.ingressClassName }} 17 | rules: 18 | - host: {{ .Values.rspamd.ingress.host }} 19 | http: 20 | paths: 21 | - pathType: Prefix 22 | path: {{ .Values.rspamd.ingress.path }} 23 | backend: 24 | service: 25 | name: {{ template "dockermailserver.fullname" . }} 26 | port: 27 | name: rspamd 28 | 29 | {{ if .Values.rspamd.ingress.tls.enabled }} 30 | tls: 31 | - secretName: {{ .Values.rspamd.ingress.tls.secret }} 32 | hosts: 33 | - {{ .Values.rspamd.ingress.host }} 34 | {{- end }} 35 | {{- end }} -------------------------------------------------------------------------------- /charts/docker-mailserver/templates/pvc.yaml: -------------------------------------------------------------------------------- 1 | {{- range $name, $pvc := .Values.persistent_volume_claims -}} 2 | {{- if and (not $pvc.existingClaim) ($pvc.enabled) }} 3 | kind: PersistentVolumeClaim 4 | apiVersion: v1 5 | metadata: 6 | name: {{ template "dockermailserver.fullname" $ }}-{{ $name }} 7 | {{- if $pvc.annotations }} 8 | annotations: 9 | {{ toYaml $pvc.annotations }} 10 | {{ end }} 11 | spec: 12 | accessModes: 13 | {{ toYaml $pvc.accessModes | indent 2 }} 14 | 15 | {{- if $pvc.storageClass }} 16 | storageClassName: {{ $pvc.storageClass | quote }} 17 | {{- end }} 18 | resources: 19 | requests: 20 | storage: {{ $pvc.size | quote }} 21 | {{- if $pvc.selector }} 22 | selector: 23 | {{ toYaml $pvc.selector | indent 4 }} 24 | {{ end }} 25 | --- 26 | {{- end }} 27 | {{- end }} 28 | -------------------------------------------------------------------------------- /charts/docker-mailserver/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | {{- range $secret := .Values.secrets }} 2 | {{- if $secret.create }} 3 | apiVersion: "v1" 4 | kind: "Secret" 5 | metadata: 6 | labels: 7 | app.kubernetes.io/name: {{ template "dockermailserver.fullname" $ }} 8 | chart: "{{ $.Chart.Name }}-{{ $.Chart.Version }}" 9 | heritage: "{{ $.Release.Service }}" 10 | release: "{{ $.Release.Name }}" 11 | name: {{ regexReplaceAll "[.]" $secret.name "-" }} 12 | data: 13 | {{ $secret.key | default $secret.name }}: | 14 | {{ tpl $secret.data $ | indent 6 }} 15 | --- 16 | {{- end }} 17 | {{- end }} 18 | 19 | -------------------------------------------------------------------------------- /charts/docker-mailserver/templates/service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: "Service" 3 | apiVersion: "v1" 4 | metadata: 5 | annotations: 6 | ## These annontations mark the service as monitorable by Prometheus, both directly as a service level metric and 7 | ## via the blackbox exporter. For more information, see 8 | ## values.yaml 9 | prometheus.io/scrape: {{ .Values.monitoring.service.scrape | quote }} 10 | prometheus.io/probe: {{ .Values.monitoring.service.probe | quote }} 11 | prometheus.io/path: {{ .Values.monitoring.service.path | quote }} 12 | prometheus.io/port: {{ .Values.monitoring.service.port | quote }} 13 | ## 14 | {{- if .Values.service.annotations }} 15 | {{ toYaml .Values.service.annotations | indent 4 }} 16 | {{ end }} 17 | labels: 18 | app.kubernetes.io/name: {{ template "dockermailserver.fullname" . }} 19 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 20 | heritage: "{{ .Release.Service }}" 21 | release: "{{ .Release.Name }}" 22 | {{- if .Values.service.labels }} 23 | {{ toYaml .Values.service.labels | indent 4 }} 24 | {{ end }} 25 | name: {{ template "dockermailserver.fullname" . }} 26 | spec: 27 | ## If a load balancer is being used, ensure that the newer type of LB that passes along IP information is used 28 | ## rather than the legacy one. 29 | {{- if or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer") }} 30 | {{- if .Values.service.externalTrafficPolicy }} 31 | externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy }} 32 | {{- end }} 33 | {{- if and (not .Values.service.externalTrafficPolicy) (eq .Values.service.type "LoadBalancer") }} 34 | externalTrafficPolicy: Local 35 | {{- end }} 36 | {{- if and (not .Values.service.externalTrafficPolicy) (eq .Values.service.type "NodePort") }} 37 | externalTrafficPolicy: Cluster 38 | {{- end }} 39 | {{- end }} 40 | selector: 41 | app.kubernetes.io/name: {{ template "dockermailserver.fullname" . }} 42 | release: "{{ .Release.Name }}" 43 | ports: 44 | - name: smtp 45 | port: 25 46 | targetPort: smtp 47 | {{- if eq .Values.service.type "NodePort" }} 48 | nodePort: {{ default "30025" .Values.service.nodePort.smtp }} 49 | {{- end }} 50 | 51 | - name: submissions 52 | targetPort: submissions 53 | port: 465 54 | {{- if eq .Values.service.type "NodePort" }} 55 | nodePort: {{ default "30465" .Values.service.nodePort.smtps }} 56 | {{- end }} 57 | - name: submission 58 | targetPort: submission 59 | port: 587 60 | {{- if eq .Values.service.type "NodePort" }} 61 | nodePort: {{ default "30587" .Values.service.nodePort.submission }} 62 | {{ end }} 63 | {{- if .Values.proxyProtocol.enabled }} 64 | - name: smtp-proxy 65 | targetPort: smtp-proxy 66 | port: 12525 67 | - name: subs-proxy 68 | targetPort: subs-proxy 69 | port: 10465 70 | - name: sub-proxy 71 | targetPort: sub-proxy 72 | port: 10587 73 | {{- end }} 74 | 75 | {{- if and (.Values.deployment.env.ENABLE_IMAP) (not .Values.deployment.env.SMTP_ONLY) }} 76 | - name: imap 77 | targetPort: imap 78 | port: 143 79 | {{- if eq .Values.service.type "NodePort" }} 80 | nodePort: {{ default "30143" .Values.service.nodePort.imap }} 81 | {{- end }} 82 | - name: imaps 83 | targetPort: imaps 84 | port: 993 85 | {{- if eq .Values.service.type "NodePort" }} 86 | nodePort: {{ default "30993" .Values.service.nodePort.imaps }} 87 | {{- end }} 88 | {{- if .Values.proxyProtocol.enabled }} 89 | - name: imap-proxy 90 | targetPort: imap-proxy 91 | port: 10143 92 | - name: imaps-proxy 93 | targetPort: imaps-proxy 94 | port: 10993 95 | {{- end }} 96 | {{- end }} 97 | 98 | {{- if and (.Values.deployment.env.ENABLE_POP3) (not .Values.deployment.env.SMTP_ONLY) }} 99 | - name: pop3 100 | targetPort: pop3 101 | port: 110 102 | {{- if eq .Values.service.type "NodePort" }} 103 | nodePort: {{ default "30110" .Values.service.nodePort.pop3 }} 104 | {{- end }} 105 | - name: pop3s 106 | targetPort: pop3s 107 | port: 995 108 | {{- if eq .Values.service.type "NodePort" }} 109 | nodePort: {{ default "30995" .Values.service.nodePort.pop3s }} 110 | {{- end }} 111 | {{- if .Values.proxyProtocol.enabled }} 112 | - name: pop3-proxy 113 | targetPort: pop3-proxy 114 | port: 10110 115 | - name: pop3s-proxy 116 | targetPort: pop3s-proxy 117 | port: 10995 118 | {{- end }} 119 | {{- end }} 120 | 121 | {{- if .Values.deployment.env.ENABLE_RSPAMD }} 122 | - name: rspamd 123 | targetPort: rspamd 124 | port: 11334 125 | {{- end }} 126 | 127 | {{- if and (.Values.deployment.env.ENABLE_MANAGESIEVE) (not .Values.deployment.env.SMTP_ONLY) }} 128 | - name: managesieve 129 | targetPort: managesieve 130 | port: 4190 131 | {{- if .Values.proxyProtocol.enabled }} 132 | - name: managesieve-proxy 133 | targetPort: managesieve-proxy 134 | port: 14190 135 | {{- end }} 136 | {{- end }} 137 | 138 | {{- if .Values.metrics.enabled }} 139 | - name: metrics 140 | port: 9154 141 | targetPort: 9154 142 | {{- end }} 143 | 144 | type: {{ default "ClusterIP" .Values.service.type }} 145 | {{- if eq .Values.service.type "LoadBalancer" }} 146 | {{- if .Values.service.loadBalancer.publicIp }} 147 | loadBalancerIP: {{ .Values.service.loadBalancer.publicIp }} 148 | {{- if .Values.service.loadBalancer.allowedIps }} 149 | loadBalancerSourceRanges: 150 | {{ .Values.service.loadBalancer.allowedIps | toYaml | indent 4 }} 151 | {{- end }} 152 | {{- end }} 153 | {{- end }} 154 | -------------------------------------------------------------------------------- /charts/docker-mailserver/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if or .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: {{ template "dockermailserver.fullname" . }} 7 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 8 | heritage: {{ .Release.Service }} 9 | release: {{ .Release.Name }} 10 | name: {{ template "dockermailserver.serviceAccountName" . }} 11 | {{- end -}} -------------------------------------------------------------------------------- /charts/docker-mailserver/templates/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.metrics.serviceMonitor.enabled }} 2 | 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | app.kubernetes.io/name: {{ template "dockermailserver.fullname" . }} 8 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 9 | heritage: "{{ .Release.Service }}" 10 | release: "{{ .Release.Name }}" 11 | {{- if .Values.metrics.serviceMonitor.labels }} 12 | {{ toYaml .Values.metrics.serviceMonitor.labels | indent 4 }} 13 | {{ end }} 14 | name: {{ template "dockermailserver.fullname" . }} 15 | spec: 16 | endpoints: 17 | - interval: {{ .Values.metrics.serviceMonitor.scrapeInterval }} 18 | path: /metrics 19 | port: metrics 20 | namespaceSelector: 21 | matchNames: 22 | - {{ .Release.Namespace }} 23 | selector: 24 | matchLabels: 25 | app.kubernetes.io/name: {{ template "dockermailserver.fullname" . }} 26 | release: "{{ .Release.Name }}" 27 | 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /charts/docker-mailserver/tests/__snapshot__/configmap_test.yaml.snap: -------------------------------------------------------------------------------- 1 | manifest should match snapshot: 2 | 1: | 3 | apiVersion: v1 4 | data: 5 | dovecot.cf: |2 6 | haproxy_trusted_networks = 10.0.0.0/8 192.168.0.0/16 172.16.0.0/12 7 | service imap-login { 8 | inet_listener imap { 9 | port = 143 10 | } 11 | 12 | inet_listener imaps { 13 | port = 993 14 | ssl = yes 15 | } 16 | 17 | inet_listener imap_proxy { 18 | haproxy = yes 19 | port = 10143 20 | ssl = no 21 | } 22 | 23 | inet_listener imaps_proxy { 24 | haproxy = yes 25 | port = 10993 26 | ssl = yes 27 | } 28 | } 29 | kind: ConfigMap 30 | metadata: 31 | labels: 32 | app.kubernetes.io/name: RELEASE-NAME-docker-mailserver 33 | chart: docker-mailserver-0.1.0 34 | heritage: Helm 35 | release: RELEASE-NAME 36 | name: dovecot-cf 37 | 2: | 38 | apiVersion: v1 39 | data: 40 | fts-xapian-plugin.conf: "" 41 | kind: ConfigMap 42 | metadata: 43 | labels: 44 | app.kubernetes.io/name: RELEASE-NAME-docker-mailserver 45 | chart: docker-mailserver-0.1.0 46 | heritage: Helm 47 | release: RELEASE-NAME 48 | name: fts-xapian-plugin-conf 49 | 3: | 50 | apiVersion: v1 51 | data: 52 | user-patches.sh: | 53 | #!/bin/bash 54 | # Make sure to keep this file in sync with https://github.com/docker-mailserver/docker-mailserver/blob/master/target/postfix/master.cf! 55 | cat <> /etc/postfix/master.cf 56 | 57 | # Submission with proxy 58 | 10587 inet n - n - - smtpd 59 | -o syslog_name=postfix/submission 60 | -o smtpd_tls_security_level=encrypt 61 | -o smtpd_sasl_auth_enable=yes 62 | -o smtpd_sasl_type=dovecot 63 | -o smtpd_reject_unlisted_recipient=no 64 | -o smtpd_sasl_authenticated_header=yes 65 | -o smtpd_client_restrictions=permit_sasl_authenticated,reject 66 | -o smtpd_relay_restrictions=permit_sasl_authenticated,reject 67 | -o smtpd_sender_restrictions=\$mua_sender_restrictions 68 | -o smtpd_discard_ehlo_keywords= 69 | -o milter_macro_daemon_name=ORIGINATING 70 | -o cleanup_service_name=sender-cleanup 71 | -o smtpd_upstream_proxy_protocol=haproxy 72 | 73 | # Submissions with proxy 74 | 10465 inet n - n - - smtpd 75 | -o syslog_name=postfix/submissions 76 | -o smtpd_tls_wrappermode=yes 77 | -o smtpd_sasl_auth_enable=yes 78 | -o smtpd_sasl_type=dovecot 79 | -o smtpd_reject_unlisted_recipient=no 80 | -o smtpd_sasl_authenticated_header=yes 81 | -o smtpd_client_restrictions=permit_sasl_authenticated,reject 82 | -o smtpd_relay_restrictions=permit_sasl_authenticated,reject 83 | -o smtpd_sender_restrictions=\$mua_sender_restrictions 84 | -o smtpd_discard_ehlo_keywords= 85 | -o milter_macro_daemon_name=ORIGINATING 86 | -o cleanup_service_name=sender-cleanup 87 | -o smtpd_upstream_proxy_protocol=haproxy 88 | 89 | # Smtp with proxy 90 | 12525 inet n - n - 1 postscreen 91 | -o syslog_name=postfix/smtp-proxy 92 | -o postscreen_upstream_proxy_protocol=haproxy 93 | -o postscreen_cache_map=btree:$data_directory/postscreen_10025_cache 94 | EOS 95 | kind: ConfigMap 96 | metadata: 97 | labels: 98 | app.kubernetes.io/name: RELEASE-NAME-docker-mailserver 99 | chart: docker-mailserver-0.1.0 100 | heritage: Helm 101 | release: RELEASE-NAME 102 | name: user-patches-sh 103 | -------------------------------------------------------------------------------- /charts/docker-mailserver/tests/__snapshot__/deployment_test.yaml.snap: -------------------------------------------------------------------------------- 1 | manifest should match snapshot: 2 | 1: | 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | labels: 7 | app.kubernetes.io/name: RELEASE-NAME-docker-mailserver 8 | chart: docker-mailserver-0.1.0 9 | heritage: Helm 10 | release: RELEASE-NAME 11 | name: RELEASE-NAME-docker-mailserver 12 | spec: 13 | replicas: 1 14 | selector: 15 | matchLabels: 16 | app.kubernetes.io/name: RELEASE-NAME-docker-mailserver 17 | release: RELEASE-NAME 18 | strategy: 19 | type: Recreate 20 | template: 21 | metadata: 22 | labels: 23 | app.kubernetes.io/name: RELEASE-NAME-docker-mailserver 24 | release: RELEASE-NAME 25 | spec: 26 | containers: 27 | - env: 28 | - name: AMAVIS_LOGLEVEL 29 | value: "0" 30 | - name: DOVECOT_INET_PROTOCOLS 31 | value: all 32 | - name: DOVECOT_MAILBOX_FORMAT 33 | value: maildir 34 | - name: ENABLE_AMAVIS 35 | value: "0" 36 | - name: ENABLE_CLAMAV 37 | value: "0" 38 | - name: ENABLE_DNSBL 39 | value: "0" 40 | - name: ENABLE_FAIL2BAN 41 | value: "0" 42 | - name: ENABLE_FETCHMAIL 43 | value: "0" 44 | - name: ENABLE_GETMAIL 45 | value: "0" 46 | - name: ENABLE_IMAP 47 | value: "1" 48 | - name: ENABLE_OPENDKIM 49 | value: "0" 50 | - name: ENABLE_OPENDMARC 51 | value: "0" 52 | - name: ENABLE_POLICYD_SPF 53 | value: "0" 54 | - name: ENABLE_POSTGREY 55 | value: "0" 56 | - name: ENABLE_QUOTAS 57 | value: "1" 58 | - name: ENABLE_RSPAMD 59 | value: "1" 60 | - name: ENABLE_RSPAMD_REDIS 61 | value: "1" 62 | - name: ENABLE_SASLAUTHD 63 | value: "0" 64 | - name: ENABLE_SPAMASSASSIN 65 | value: "0" 66 | - name: ENABLE_SPAMASSASSIN_KAM 67 | value: "0" 68 | - name: ENABLE_SRS 69 | value: "0" 70 | - name: ENABLE_UPDATE_CHECK 71 | value: "1" 72 | - name: FAIL2BAN_BLOCKTYPE 73 | value: drop 74 | - name: FETCHMAIL_PARALLEL 75 | value: "0" 76 | - name: FETCHMAIL_POLL 77 | value: "300" 78 | - name: GETMAIL_POLL 79 | value: "5" 80 | - name: LOGROTATE_COUNT 81 | value: "4" 82 | - name: LOGROTATE_INTERVAL 83 | value: weekly 84 | - name: LOG_LEVEL 85 | value: info 86 | - name: MARK_SPAM_AS_READ 87 | value: "0" 88 | - name: MOVE_SPAM_TO_JUNK 89 | value: "1" 90 | - name: OVERRIDE_HOSTNAME 91 | value: mail.example.com 92 | - name: PERMIT_DOCKER 93 | value: none 94 | - name: POSTFIX_INET_PROTOCOLS 95 | value: all 96 | - name: POSTFIX_REJECT_UNKNOWN_CLIENT_HOSTNAME 97 | value: "0" 98 | - name: POSTGREY_AUTO_WHITELIST_CLIENTS 99 | value: "5" 100 | - name: POSTGREY_DELAY 101 | value: "300" 102 | - name: POSTGREY_MAX_AGE 103 | value: "35" 104 | - name: POSTGREY_TEXT 105 | value: Delayed by Postgrey 106 | - name: POSTSCREEN_ACTION 107 | value: enforce 108 | - name: RELAY_PORT 109 | value: "25" 110 | - name: RSPAMD_CHECK_AUTHENTICATED 111 | value: "0" 112 | - name: RSPAMD_GREYLISTING 113 | value: "0" 114 | - name: RSPAMD_HFILTER 115 | value: "1" 116 | - name: RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE 117 | value: "6" 118 | - name: RSPAMD_LEARN 119 | value: "0" 120 | - name: RSPAMD_NEURAL 121 | value: "0" 122 | - name: SA_KILL 123 | value: "10" 124 | - name: SA_TAG 125 | value: "2" 126 | - name: SA_TAG2 127 | value: "6.31" 128 | - name: SPAMASSASSIN_SPAM_TO_INBOX 129 | value: "1" 130 | - name: SPAM_SUBJECT 131 | value: '***SPAM*** ' 132 | - name: SRS_SENDER_CLASSES 133 | value: envelope_sender 134 | - name: UPDATE_CHECK_INTERVAL 135 | value: 1d 136 | image: mailserver/docker-mailserver:0.1.0 137 | imagePullPolicy: IfNotPresent 138 | livenessProbe: 139 | exec: 140 | command: 141 | - /bin/bash 142 | - -c 143 | - supervisorctl status | grep -E "amavis|clamav|cron|dovecot|mailserver|opendkim|opendmarc|postfix|rsyslog" | grep RUNNING 144 | failureThreshold: 3 145 | initialDelaySeconds: 10 146 | timeoutSeconds: 5 147 | name: docker-mailserver 148 | ports: 149 | - containerPort: 25 150 | name: smtp 151 | - containerPort: 465 152 | name: submissions 153 | - containerPort: 587 154 | name: submission 155 | - containerPort: 12525 156 | name: smtp-proxy 157 | - containerPort: 10465 158 | name: subs-proxy 159 | - containerPort: 10587 160 | name: sub-proxy 161 | - containerPort: 143 162 | name: imap 163 | - containerPort: 993 164 | name: imaps 165 | - containerPort: 10143 166 | name: imap-proxy 167 | - containerPort: 10993 168 | name: imaps-proxy 169 | - containerPort: 11334 170 | name: rspamd 171 | readinessProbe: 172 | exec: 173 | command: 174 | - /bin/bash 175 | - -c 176 | - supervisorctl status | grep -E "mailserver|postfix" | grep RUNNING 177 | failureThreshold: 3 178 | initialDelaySeconds: 10 179 | timeoutSeconds: 5 180 | resources: 181 | limits: 182 | cpu: "2" 183 | ephemeral-storage: 500Mi 184 | memory: 2048Mi 185 | requests: 186 | cpu: "1" 187 | ephemeral-storage: 100Mi 188 | memory: 1536Mi 189 | securityContext: 190 | privileged: false 191 | readOnlyRootFilesystem: false 192 | volumeMounts: 193 | - mountPath: /tmp/docker-mailserver/dovecot.cf 194 | name: dovecot-cf 195 | subPath: dovecot.cf 196 | - mountPath: /etc/dovecot/conf.d/10-plugin.conf 197 | name: fts-xapian-plugin-conf 198 | subPath: fts-xapian-plugin.conf 199 | - mountPath: /tmp/docker-mailserver/user-patches.sh 200 | name: user-patches-sh 201 | subPath: user-patches.sh 202 | - mountPath: /tmp/docker-mailserver 203 | name: mail-config 204 | - mountPath: /var/mail 205 | name: mail-data 206 | - mountPath: /var/log/mail 207 | name: mail-log 208 | - mountPath: /var/mail-state 209 | name: mail-state 210 | nodeSelector: {} 211 | priorityClassName: null 212 | restartPolicy: Always 213 | runtimeClassName: null 214 | securityContext: null 215 | serviceAccountName: RELEASE-NAME-docker-mailserver 216 | volumes: 217 | - configMap: 218 | name: dovecot-cf 219 | name: dovecot-cf 220 | - configMap: 221 | name: fts-xapian-plugin-conf 222 | name: fts-xapian-plugin-conf 223 | - configMap: 224 | name: user-patches-sh 225 | name: user-patches-sh 226 | - name: mail-config 227 | persistentVolumeClaim: 228 | claimName: RELEASE-NAME-docker-mailserver-mail-config 229 | - name: mail-data 230 | persistentVolumeClaim: 231 | claimName: RELEASE-NAME-docker-mailserver-mail-data 232 | - name: mail-log 233 | persistentVolumeClaim: 234 | claimName: RELEASE-NAME-docker-mailserver-mail-log 235 | - name: mail-state 236 | persistentVolumeClaim: 237 | claimName: RELEASE-NAME-docker-mailserver-mail-state 238 | -------------------------------------------------------------------------------- /charts/docker-mailserver/tests/__snapshot__/pvc_test.yaml.snap: -------------------------------------------------------------------------------- 1 | manifest should match snapshot: 2 | 1: | 3 | apiVersion: v1 4 | kind: PersistentVolumeClaim 5 | metadata: 6 | name: RELEASE-NAME-docker-mailserver-mail-config 7 | spec: 8 | accessModes: 9 | - ReadWriteOnce 10 | resources: 11 | requests: 12 | storage: 1Mi 13 | 2: | 14 | apiVersion: v1 15 | kind: PersistentVolumeClaim 16 | metadata: 17 | name: RELEASE-NAME-docker-mailserver-mail-data 18 | spec: 19 | accessModes: 20 | - ReadWriteOnce 21 | resources: 22 | requests: 23 | storage: 10Gi 24 | 3: | 25 | apiVersion: v1 26 | kind: PersistentVolumeClaim 27 | metadata: 28 | name: RELEASE-NAME-docker-mailserver-mail-log 29 | spec: 30 | accessModes: 31 | - ReadWriteOnce 32 | resources: 33 | requests: 34 | storage: 1Gi 35 | 4: | 36 | apiVersion: v1 37 | kind: PersistentVolumeClaim 38 | metadata: 39 | name: RELEASE-NAME-docker-mailserver-mail-state 40 | spec: 41 | accessModes: 42 | - ReadWriteOnce 43 | resources: 44 | requests: 45 | storage: 1Gi 46 | should apply annotations from persistent_volume_claims.annotations: 47 | 1: | 48 | apiVersion: v1 49 | kind: PersistentVolumeClaim 50 | metadata: 51 | annotations: 52 | backup.banana.io/deltas: pancakes 53 | name: RELEASE-NAME-docker-mailserver-mail-config 54 | spec: 55 | accessModes: 56 | - ReadWriteOnce 57 | resources: 58 | requests: 59 | storage: 1Mi 60 | 2: | 61 | apiVersion: v1 62 | kind: PersistentVolumeClaim 63 | metadata: 64 | name: RELEASE-NAME-docker-mailserver-mail-data 65 | spec: 66 | accessModes: 67 | - ReadWriteOnce 68 | resources: 69 | requests: 70 | storage: 10Gi 71 | 3: | 72 | apiVersion: v1 73 | kind: PersistentVolumeClaim 74 | metadata: 75 | name: RELEASE-NAME-docker-mailserver-mail-log 76 | spec: 77 | accessModes: 78 | - ReadWriteOnce 79 | resources: 80 | requests: 81 | storage: 1Gi 82 | 4: | 83 | apiVersion: v1 84 | kind: PersistentVolumeClaim 85 | metadata: 86 | name: RELEASE-NAME-docker-mailserver-mail-state 87 | spec: 88 | accessModes: 89 | - ReadWriteOnce 90 | resources: 91 | requests: 92 | storage: 1Gi 93 | -------------------------------------------------------------------------------- /charts/docker-mailserver/tests/__snapshot__/secret_test.yaml.snap: -------------------------------------------------------------------------------- 1 | manifest should match snapshot: 2 | 1: | 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | labels: 7 | app.kubernetes.io/name: RELEASE-NAME-docker-mailserver 8 | chart: docker-mailserver-1.0.0 9 | heritage: Helm 10 | release: RELEASE-NAME 11 | name: RELEASE-NAME-docker-mailserver 12 | spec: 13 | replicas: 1 14 | selector: 15 | matchLabels: 16 | app.kubernetes.io/name: RELEASE-NAME-docker-mailserver 17 | release: RELEASE-NAME 18 | strategy: 19 | type: Recreate 20 | template: 21 | metadata: 22 | labels: 23 | app.kubernetes.io/name: RELEASE-NAME-docker-mailserver 24 | release: RELEASE-NAME 25 | spec: 26 | containers: 27 | - env: 28 | - name: AMAVIS_LOGLEVEL 29 | value: "0" 30 | - name: DOVECOT_INET_PROTOCOLS 31 | value: all 32 | - name: DOVECOT_MAILBOX_FORMAT 33 | value: maildir 34 | - name: ENABLE_AMAVIS 35 | value: "0" 36 | - name: ENABLE_CLAMAV 37 | value: "0" 38 | - name: ENABLE_DNSBL 39 | value: "0" 40 | - name: ENABLE_FAIL2BAN 41 | value: "0" 42 | - name: ENABLE_FETCHMAIL 43 | value: "0" 44 | - name: ENABLE_GETMAIL 45 | value: "0" 46 | - name: ENABLE_IMAP 47 | value: "1" 48 | - name: ENABLE_OPENDKIM 49 | value: "0" 50 | - name: ENABLE_OPENDMARC 51 | value: "0" 52 | - name: ENABLE_POLICYD_SPF 53 | value: "0" 54 | - name: ENABLE_POSTGREY 55 | value: "0" 56 | - name: ENABLE_QUOTAS 57 | value: "1" 58 | - name: ENABLE_RSPAMD 59 | value: "1" 60 | - name: ENABLE_RSPAMD_REDIS 61 | value: "1" 62 | - name: ENABLE_SASLAUTHD 63 | value: "0" 64 | - name: ENABLE_SPAMASSASSIN 65 | value: "0" 66 | - name: ENABLE_SPAMASSASSIN_KAM 67 | value: "0" 68 | - name: ENABLE_SRS 69 | value: "0" 70 | - name: ENABLE_UPDATE_CHECK 71 | value: "1" 72 | - name: FAIL2BAN_BLOCKTYPE 73 | value: drop 74 | - name: FETCHMAIL_PARALLEL 75 | value: "0" 76 | - name: FETCHMAIL_POLL 77 | value: "300" 78 | - name: GETMAIL_POLL 79 | value: "5" 80 | - name: LOGROTATE_COUNT 81 | value: "4" 82 | - name: LOGROTATE_INTERVAL 83 | value: weekly 84 | - name: LOG_LEVEL 85 | value: info 86 | - name: MARK_SPAM_AS_READ 87 | value: "0" 88 | - name: MOVE_SPAM_TO_JUNK 89 | value: "1" 90 | - name: OVERRIDE_HOSTNAME 91 | value: mail.example.com 92 | - name: PERMIT_DOCKER 93 | value: none 94 | - name: POSTFIX_INET_PROTOCOLS 95 | value: all 96 | - name: POSTFIX_REJECT_UNKNOWN_CLIENT_HOSTNAME 97 | value: "0" 98 | - name: POSTGREY_AUTO_WHITELIST_CLIENTS 99 | value: "5" 100 | - name: POSTGREY_DELAY 101 | value: "300" 102 | - name: POSTGREY_MAX_AGE 103 | value: "35" 104 | - name: POSTGREY_TEXT 105 | value: Delayed by Postgrey 106 | - name: POSTSCREEN_ACTION 107 | value: enforce 108 | - name: RELAY_PORT 109 | value: "25" 110 | - name: RSPAMD_CHECK_AUTHENTICATED 111 | value: "0" 112 | - name: RSPAMD_GREYLISTING 113 | value: "0" 114 | - name: RSPAMD_HFILTER 115 | value: "1" 116 | - name: RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE 117 | value: "6" 118 | - name: RSPAMD_LEARN 119 | value: "0" 120 | - name: RSPAMD_NEURAL 121 | value: "0" 122 | - name: SA_KILL 123 | value: "10" 124 | - name: SA_TAG 125 | value: "2" 126 | - name: SA_TAG2 127 | value: "6.31" 128 | - name: SPAMASSASSIN_SPAM_TO_INBOX 129 | value: "1" 130 | - name: SPAM_SUBJECT 131 | value: '***SPAM*** ' 132 | - name: SRS_SENDER_CLASSES 133 | value: envelope_sender 134 | - name: UPDATE_CHECK_INTERVAL 135 | value: 1d 136 | image: mailserver/docker-mailserver:0.1.0 137 | imagePullPolicy: IfNotPresent 138 | livenessProbe: 139 | exec: 140 | command: 141 | - /bin/bash 142 | - -c 143 | - supervisorctl status | grep -E "amavis|clamav|cron|dovecot|mailserver|opendkim|opendmarc|postfix|rsyslog" | grep RUNNING 144 | failureThreshold: 3 145 | initialDelaySeconds: 10 146 | timeoutSeconds: 5 147 | name: docker-mailserver 148 | ports: 149 | - containerPort: 25 150 | name: smtp 151 | - containerPort: 465 152 | name: submissions 153 | - containerPort: 587 154 | name: submission 155 | - containerPort: 12525 156 | name: smtp-proxy 157 | - containerPort: 10465 158 | name: subs-proxy 159 | - containerPort: 10587 160 | name: sub-proxy 161 | - containerPort: 143 162 | name: imap 163 | - containerPort: 993 164 | name: imaps 165 | - containerPort: 10143 166 | name: imap-proxy 167 | - containerPort: 10993 168 | name: imaps-proxy 169 | - containerPort: 11334 170 | name: rspamd 171 | readinessProbe: 172 | exec: 173 | command: 174 | - /bin/bash 175 | - -c 176 | - supervisorctl status | grep -E "mailserver|postfix" | grep RUNNING 177 | failureThreshold: 3 178 | initialDelaySeconds: 10 179 | timeoutSeconds: 5 180 | resources: 181 | limits: 182 | cpu: "2" 183 | ephemeral-storage: 500Mi 184 | memory: 2048Mi 185 | requests: 186 | cpu: "1" 187 | ephemeral-storage: 100Mi 188 | memory: 1536Mi 189 | securityContext: 190 | privileged: false 191 | readOnlyRootFilesystem: false 192 | volumeMounts: 193 | - mountPath: /tmp/docker-mailserver/dovecot.cf 194 | name: dovecot-cf 195 | subPath: dovecot.cf 196 | - mountPath: /etc/dovecot/conf.d/10-plugin.conf 197 | name: fts-xapian-plugin-conf 198 | subPath: fts-xapian-plugin.conf 199 | - mountPath: /tmp/docker-mailserver/user-patches.sh 200 | name: user-patches-sh 201 | subPath: user-patches.sh 202 | - mountPath: /tmp/docker-mailserver/secret.yaml 203 | name: mailserver-secret-yaml 204 | subPath: mailserver-secret.yaml 205 | - mountPath: /tmp/docker-mailserver 206 | name: mail-config 207 | - mountPath: /var/mail 208 | name: mail-data 209 | - mountPath: /var/log/mail 210 | name: mail-log 211 | - mountPath: /var/mail-state 212 | name: mail-state 213 | nodeSelector: {} 214 | priorityClassName: null 215 | restartPolicy: Always 216 | runtimeClassName: null 217 | securityContext: null 218 | serviceAccountName: RELEASE-NAME-docker-mailserver 219 | volumes: 220 | - configMap: 221 | name: dovecot-cf 222 | name: dovecot-cf 223 | - configMap: 224 | name: fts-xapian-plugin-conf 225 | name: fts-xapian-plugin-conf 226 | - configMap: 227 | name: user-patches-sh 228 | name: user-patches-sh 229 | - name: mailserver-secret-yaml 230 | secret: 231 | secretName: mailserver-secret-yaml 232 | - name: mail-config 233 | persistentVolumeClaim: 234 | claimName: RELEASE-NAME-docker-mailserver-mail-config 235 | - name: mail-data 236 | persistentVolumeClaim: 237 | claimName: RELEASE-NAME-docker-mailserver-mail-data 238 | - name: mail-log 239 | persistentVolumeClaim: 240 | claimName: RELEASE-NAME-docker-mailserver-mail-log 241 | - name: mail-state 242 | persistentVolumeClaim: 243 | claimName: RELEASE-NAME-docker-mailserver-mail-state 244 | 2: | 245 | apiVersion: v1 246 | data: 247 | mailserver-secret.yaml: | 248 | bWFpbHNlcnZlci11c2VybmFtZTogdGVzdAogICAgICAgICAgICBtYWlsc2VydmVyLXBhc3N3b3JkOiB0ZXN0 249 | kind: Secret 250 | metadata: 251 | labels: 252 | app.kubernetes.io/name: RELEASE-NAME-docker-mailserver 253 | chart: docker-mailserver-1.0.0 254 | heritage: Helm 255 | release: RELEASE-NAME 256 | name: mailserver-secret-yaml 257 | -------------------------------------------------------------------------------- /charts/docker-mailserver/tests/configmap_test.yaml: -------------------------------------------------------------------------------- 1 | suite: configmap 2 | templates: 3 | - configmap.yaml 4 | chart: 5 | version: 0.1.0 6 | appVersion: 0.1.0 7 | values: 8 | - ../values.yaml 9 | tests: 10 | - it: should configure imaps port 10993 if proxyProtocol enabled 11 | set: 12 | proxyProtocol.enabled: true 13 | documentIndex: 0 14 | asserts: 15 | - isKind: 16 | of: ConfigMap 17 | - matchRegex: 18 | path: data["dovecot.cf"] 19 | pattern: "10993" 20 | 21 | - it: manifest should match snapshot 22 | set: 23 | proxyProtocol: 24 | enabled: true 25 | asserts: 26 | - matchSnapshot: { } -------------------------------------------------------------------------------- /charts/docker-mailserver/tests/deployment_test.yaml: -------------------------------------------------------------------------------- 1 | suite: deployment tests 2 | templates: 3 | - deployment.yaml 4 | chart: 5 | version: 0.1.0 6 | appVersion: 0.1.0 7 | values: 8 | - ../values.yaml 9 | tests: 10 | - it: image and tag should end up in deployment 11 | set: 12 | image.name: bananas 13 | image.tag: in-pajamas 14 | asserts: 15 | - isKind: 16 | of: Deployment 17 | - matchRegex: 18 | path: metadata.name 19 | pattern: -docker-mailserver$ 20 | - equal: 21 | path: spec.template.spec.containers[0].image 22 | value: bananas:in-pajamas 23 | 24 | - it: should use subPath for volumes if defined 25 | set: 26 | persistence: 27 | mail-data: 28 | subPath: another-folder 29 | asserts: 30 | - equal: 31 | path: spec.template.spec.containers[0].volumeMounts[?(@.name=="mail-data")].subPath 32 | value: another-folder 33 | 34 | - it: manifest should match snapshot 35 | asserts: 36 | - matchSnapshot: { } -------------------------------------------------------------------------------- /charts/docker-mailserver/tests/pvc_test.yaml: -------------------------------------------------------------------------------- 1 | suite: pvc creation 2 | templates: 3 | - pvc.yaml 4 | values: 5 | - ../values.yaml 6 | chart: 7 | version: 0.1.0 8 | appVersion: 0.1.0 9 | tests: 10 | - it: should apply annotations from persistent_volume_claims.annotations 11 | set: 12 | persistent_volume_claims: 13 | mail-config: 14 | annotations: 15 | backup.banana.io/deltas: pancakes 16 | asserts: 17 | - matchSnapshot: { } 18 | 19 | - it: should create pvc of specified size 20 | set: 21 | persistent_volume_claims: 22 | mail-data: 23 | size: 1Pb 24 | documentIndex: 1 25 | asserts: 26 | - equal: 27 | path: spec.resources.requests.storage 28 | value: 1Pb 29 | 30 | - it: manifest should match snapshot 31 | asserts: 32 | - matchSnapshot: { } -------------------------------------------------------------------------------- /charts/docker-mailserver/tests/secret_test.yaml: -------------------------------------------------------------------------------- 1 | suite: secret 2 | templates: 3 | - secret.yaml 4 | - deployment.yaml 5 | chart: 6 | version: 1.0.0 7 | appVersion: 0.1.0 8 | values: 9 | - ../values.yaml 10 | tests: 11 | - it: manifest should match snapshot 12 | set: 13 | secrets: 14 | mailserver-secret.yaml: 15 | name: mailserver-secret.yaml 16 | create: true 17 | path: secret.yaml 18 | data: bWFpbHNlcnZlci11c2VybmFtZTogdGVzdAogICAgICAgICAgICBtYWlsc2VydmVyLXBhc3N3b3JkOiB0ZXN0 19 | asserts: 20 | - matchSnapshot: { } 21 | -------------------------------------------------------------------------------- /charts/docker-mailserver/values.yaml: -------------------------------------------------------------------------------- 1 | nameOverride: "" 2 | fullnameOverride: "" 3 | 4 | image: 5 | ## image.name is the name of the container image to use. Refer to https://hub.docker.com/r/mailserver/docker-mailserver 6 | name: "mailserver/docker-mailserver" 7 | ## image.tag is the tag of the container image to use. Refer to https://hub.docker.com/r/mailserver/docker-mailserver 8 | ## If image.tag is not defined it will default to `.Chart.appVersion` 9 | # tag: "latest" 10 | pullPolicy: "IfNotPresent" 11 | 12 | # Specify whether to create a serviceAccount for the pod. The name is generated from the 13 | # dockermailserver.serviceAccountName template 14 | serviceAccount: 15 | create: true 16 | 17 | ## Specify the name of a TLS secret that contains a certificate and private key for your email domain. 18 | ## See https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets 19 | certificate: 20 | 21 | # List extra RBL domains to use for hard reject filtering 22 | rblRejectDomains: [] 23 | 24 | deployment: 25 | ## How many versions of the deployment to run 26 | replicas: 1 27 | 28 | ## Optionally specify affinity for the deployment 29 | affinity: {} 30 | 31 | ## Optionally add additional annotations to the deployment 32 | annotations: {} 33 | 34 | ## Optionally add additional labels to the deployment 35 | labels: {} 36 | 37 | ## Optionally specify a runtimeClassName for the deployment 38 | runtimeClassName: 39 | 40 | ## Optionally specify a priorityClassName for the deployment 41 | priorityClassName: 42 | 43 | ## Optionally specify a nodeSelector for the deployment 44 | nodeSelector: {} 45 | 46 | ## Update strategy - only really applicable for deployments with RWO PVs attached 47 | ## If replicas = 1, an update can get "stuck", as the previous pod remains attached to the 48 | ## PV, and the "incoming" pod can never start. Setting the strategy to "Recreate" (our default) will 49 | ## terminate the single previous pod, so that the new, incoming pod can attach to the PV 50 | strategy: 51 | # rollingUpdate: 52 | # maxSurge: 1 53 | # maxUnavailable: 1 54 | type: "Recreate" 55 | 56 | ## The following variables affect the behaviour of docker-mailserver 57 | ## See https://docker-mailserver.github.io/docker-mailserver/latest/config/environment/ for details 58 | ## Note that an empty value indicates the default as described in the docs above 59 | env: 60 | # ----------------------------------------------- 61 | # --- Required Section --------------------------- 62 | # ----------------------------------------------- 63 | OVERRIDE_HOSTNAME: mail.example.com # You must OVERRIDE this! 64 | 65 | # ----------------------------------------------- 66 | # --- General Section --------------------------- 67 | # ----------------------------------------------- 68 | LOG_LEVEL: info 69 | SUPERVISOR_LOGLEVEL: 70 | DMS_VMAIL_UID: 71 | DMS_VMAIL_GID: 72 | ACCOUNT_PROVISIONER: 73 | POSTMASTER_ADDRESS: 74 | ENABLE_UPDATE_CHECK: 1 75 | UPDATE_CHECK_INTERVAL: 1d 76 | PERMIT_DOCKER: none 77 | TZ: 78 | NETWORK_INTERFACE: 79 | TLS_LEVEL: 80 | SPOOF_PROTECTION: 81 | ENABLE_SRS: 0 82 | ENABLE_OPENDKIM: 0 83 | ENABLE_OPENDMARC: 0 84 | ENABLE_POLICYD_SPF: 0 85 | ENABLE_POP3: 86 | ENABLE_IMAP: 1 87 | ENABLE_CLAMAV: 0 88 | ENABLE_RSPAMD: 1 89 | ENABLE_RSPAMD_REDIS: 1 90 | RSPAMD_LEARN: 0 91 | RSPAMD_CHECK_AUTHENTICATED: 0 92 | RSPAMD_GREYLISTING: 0 93 | RSPAMD_HFILTER: 1 94 | RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE: 6 95 | RSPAMD_NEURAL: 0 96 | ENABLE_AMAVIS: 0 97 | AMAVIS_LOGLEVEL: 0 98 | ENABLE_DNSBL: 0 99 | ENABLE_FAIL2BAN: 0 100 | FAIL2BAN_BLOCKTYPE: drop 101 | ENABLE_MANAGESIEVE: 102 | POSTSCREEN_ACTION: enforce 103 | SMTP_ONLY: 104 | # These values are automatically set by the chart based on the certificate key 105 | # SSL_TYPE: 106 | # SSL_CERT_PATH: 107 | # SSL_KEY_PATH: 108 | SSL_ALT_CERT_PATH: 109 | SSL_ALT_KEY_PATH: 110 | VIRUSMAILS_DELETE_DELAY: 111 | POSTFIX_DAGENT: 112 | POSTFIX_MAILBOX_SIZE_LIMIT: 113 | ENABLE_QUOTAS: 1 114 | POSTFIX_MESSAGE_SIZE_LIMIT: 115 | CLAMAV_MESSAGE_SIZE_LIMIT: 116 | PFLOGSUMM_TRIGGER: 117 | PFLOGSUMM_RECIPIENT: 118 | PFLOGSUMM_SENDER: 119 | LOGWATCH_INTERVAL: 120 | LOGWATCH_RECIPIENT: 121 | LOGWATCH_SENDER: 122 | REPORT_RECIPIENT: 123 | REPORT_SENDER: 124 | LOGROTATE_COUNT: 4 125 | LOGROTATE_INTERVAL: weekly 126 | POSTFIX_REJECT_UNKNOWN_CLIENT_HOSTNAME: 0 127 | POSTFIX_INET_PROTOCOLS: all 128 | DOVECOT_INET_PROTOCOLS: all 129 | 130 | # ----------------------------------------------- 131 | # --- SpamAssassin Section ---------------------- 132 | # ----------------------------------------------- 133 | ENABLE_SPAMASSASSIN: 0 134 | ENABLE_SPAMASSASSIN_KAM: 0 135 | SPAMASSASSIN_SPAM_TO_INBOX: 1 136 | MOVE_SPAM_TO_JUNK: 1 137 | MARK_SPAM_AS_READ: 0 138 | SA_TAG: 2.0 139 | SA_TAG2: 6.31 140 | SA_KILL: 10.0 141 | SPAM_SUBJECT: '***SPAM*** ' 142 | 143 | # ----------------------------------------------- 144 | # --- Fetchmail Section ------------------------- 145 | # ----------------------------------------------- 146 | ENABLE_FETCHMAIL: 0 147 | FETCHMAIL_POLL: 300 148 | FETCHMAIL_PARALLEL: 0 149 | ENABLE_GETMAIL: 0 150 | GETMAIL_POLL: 5 151 | 152 | # ----------------------------------------------- 153 | # --- LDAP Section ------------------------------ 154 | # ----------------------------------------------- 155 | LDAP_START_TLS: 156 | LDAP_SERVER_HOST: 157 | LDAP_SEARCH_BASE: 158 | LDAP_BIND_DN: 159 | LDAP_BIND_PW: 160 | LDAP_QUERY_FILTER_USER: 161 | LDAP_QUERY_FILTER_GROUP: 162 | LDAP_QUERY_FILTER_ALIAS: 163 | LDAP_QUERY_FILTER_DOMAIN: 164 | 165 | # ----------------------------------------------- 166 | # --- Dovecot Section --------------------------- 167 | # ----------------------------------------------- 168 | DOVECOT_TLS: 169 | DOVECOT_USER_FILTER: 170 | DOVECOT_PASS_FILTER: 171 | DOVECOT_MAILBOX_FORMAT: maildir 172 | DOVECOT_AUTH_BIND: 173 | 174 | # ----------------------------------------------- 175 | # --- Postgrey Section -------------------------- 176 | # ----------------------------------------------- 177 | ENABLE_POSTGREY: 0 178 | POSTGREY_DELAY: 300 179 | POSTGREY_MAX_AGE: 35 180 | POSTGREY_TEXT: "Delayed by Postgrey" 181 | POSTGREY_AUTO_WHITELIST_CLIENTS: 5 182 | 183 | # ----------------------------------------------- 184 | # --- SASL Section ------------------------------ 185 | # ----------------------------------------------- 186 | ENABLE_SASLAUTHD: 0 187 | SASLAUTHD_MECHANISMS: 188 | SASLAUTHD_MECH_OPTIONS: 189 | SASLAUTHD_LDAP_SERVER: 190 | SASLAUTHD_LDAP_BIND_DN: 191 | SASLAUTHD_LDAP_PASSWORD: 192 | SASLAUTHD_LDAP_SEARCH_BASE: 193 | SASLAUTHD_LDAP_FILTER: 194 | SASLAUTHD_LDAP_START_TLS: 195 | SASLAUTHD_LDAP_TLS_CHECK_PEER: 196 | SASLAUTHD_LDAP_TLS_CACERT_FILE: 197 | SASLAUTHD_LDAP_TLS_CACERT_DIR: 198 | SASLAUTHD_LDAP_PASSWORD_ATTR: 199 | SASLAUTHD_LDAP_AUTH_METHOD: 200 | SASLAUTHD_LDAP_MECH: 201 | 202 | # ----------------------------------------------- 203 | # --- SRS Section ------------------------------- 204 | # ----------------------------------------------- 205 | SRS_SENDER_CLASSES: envelope_sender 206 | SRS_EXCLUDE_DOMAINS: 207 | SRS_SECRET: 208 | 209 | # ----------------------------------------------- 210 | # --- Default Relay Host Section ---------------- 211 | # ----------------------------------------------- 212 | 213 | DEFAULT_RELAY_HOST: 214 | 215 | # ----------------------------------------------- 216 | # --- Multi-Domain Relay Section ---------------- 217 | # ----------------------------------------------- 218 | 219 | RELAY_HOST: 220 | RELAY_PORT: 25 221 | RELAY_USER: 222 | RELAY_PASSWORD: 223 | 224 | securityContext: 225 | runAsUser: 5000 226 | runAsGroup: 5000 227 | 228 | containerSecurityContext: 229 | readOnlyRootFilesystem: false # incompatible with the way docker-mailserver works 230 | privileged: false 231 | 232 | ## More generally, a "request" can be thought of as "how much is this container expected to need usually". it should be 233 | ## possible to burst outside these constraints (during a high load operation). However, Kubernetes may kill the pod 234 | ## if the node is under too higher load and the burst is outside its request 235 | ## 236 | ## Limits are hard limits. Violating them is either impossible, or results in container death. I'm not sure whether 237 | ## making these optional is a good idea or not; at the moment, I think I'm happy to defer QOS to the cluster and try 238 | ## and keep requests close to usage. 239 | ## 240 | ## Requests are what are used to determine whether more software "fits" onto the cluster. 241 | ## 242 | ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ 243 | ## Ref: https://github.com/kubernetes/kubernetes/blob/master/docs/design/resource-qos.md 244 | ## Ref: https://docs.docker.com/engine/reference/run/#/runtime-constraints-on-resources 245 | resources: 246 | requests: 247 | ## How much CPU this container is expected to need 248 | cpu: "1" 249 | ## How much memory this container is expected to need. 250 | ## Reduce these at requests your peril - too few resources can cause daemons (i.e., clamd) to fail, or timeouts to occur. 251 | ## A test installation with clamd running was killed when it consumed 1437Mi (which is why this value was increased to 1536) 252 | memory: "1536Mi" 253 | ephemeral-storage: "100Mi" 254 | limits: 255 | ## The max CPU this container should be allowed to use 256 | cpu: "2" 257 | ## The max memory this container should be allowed to use. Note: If a container exceeds its memory limit, 258 | ## it may terminated. 259 | memory: "2048Mi" 260 | ephemeral-storage: "500Mi" 261 | 262 | ## Optionally specify tolerations for the deployment 263 | tolerations: [] 264 | 265 | ## Optionally specify initContainers 266 | initContainers: [] 267 | # - name: init 268 | # image: alpine:3 269 | # command: [sh, -c] 270 | # args: 271 | # - echo "Hello, world!" > /mnt/extra-storage/test 272 | # volumeMounts: 273 | # - name: extra-storage 274 | # mountPath: /mnt/extra-storage 275 | # subPath: another-folder 276 | 277 | ## Optionally specify a list of extra mounts to add (normally used with extraVolumes) 278 | extraVolumeMounts: [] 279 | # - name: extra-storage 280 | # mountPath: /mnt/extra-storage 281 | # subPath: another-folder 282 | 283 | ## Optionally specify a list of extra volumes to add 284 | extraVolumes: [] 285 | # - name: extra-storage 286 | # emptyDir: {} 287 | 288 | service: 289 | ## What scope the service should be exposed in. One of: 290 | ## - LoadBalancer (to the world) 291 | ## - NodePort (to the world, via high port on a node) 292 | ## - ClusterIP (to the cluster) 293 | type: "ClusterIP" 294 | ## Manually overwrite the externalTrafficPolicy. One of: 295 | ## - Local 296 | ## - Cluster 297 | ## Set it to "Local" when used with type "LoadBalancer" and set it to "Cluster" when used with "NodePort", 298 | ## unless you have a good reason not to. 299 | # externalTrafficPolicy: "Cluster" 300 | ## If there is a port associated with a given service, expose it here. 301 | # port: 302 | ## If there is a particular IP that should be used for the service, specify it here. 303 | ## Note: It's quite unlikely that an IP should be specific. Normally, the best thing to do is leave it to Kubernetes 304 | ## to allocate a free IP from the pool. 305 | ## Default: Automatically assign a random IP 306 | # privateIp: 307 | ## Only relevant if the `type` above is "LoadBalancer" 308 | loadBalancer: 309 | ## If there is already a reserved public IP that this load balancer should use, indicate it here. 310 | ## Default: Automatically assign a random, ephemeral IP 311 | # publicIp: 312 | ## If there should be firewall rules restricting the load balancer to a limited set of IPs, specify those IPs below 313 | ## in CIDR format. If all IPs should be allowed access, set the CIDR as "0.0.0.0/0" 314 | allowedIps: 315 | - "0.0.0.0/0" 316 | ## If there is a Hostname associated with this site, add it here and it will be rendered in the documentation. 317 | # hostName: 318 | annotations: {} 319 | labels: {} 320 | 321 | # Note this is a dictionary and not a list so individual keys can be overridden by --set or --value helm parameters 322 | persistent_volume_claims: 323 | # Stores generated configuration files 324 | # https://docker-mailserver.github.io/docker-mailserver/edge/faq/#what-about-the-docker-datadmsconfig-directory 325 | mail-config: 326 | enabled: true 327 | existingClaim: "" 328 | size: 1Mi 329 | annotations: {} 330 | accessModes: 331 | - ReadWriteOnce 332 | storageClass: 333 | selector: {} 334 | 335 | # Stores emails 336 | mail-data: 337 | enabled: true 338 | existingClaim: "" 339 | size: 10Gi 340 | annotations: {} 341 | accessModes: 342 | - ReadWriteOnce 343 | storageClass: 344 | selector: {} 345 | 346 | # Stores state for Postfix, Dovecot, Fail2Ban, Amavis, PostGrey, ClamAV, SpamAssassin, Rspamd & Redis 347 | # https://docker-mailserver.github.io/docker-mailserver/edge/faq/#what-about-the-docker-datadmsmail-state-directory 348 | mail-state: 349 | enabled: true 350 | existingClaim: "" 351 | size: 1Gi 352 | annotations: {} 353 | accessModes: 354 | - ReadWriteOnce 355 | storageClass: 356 | selector: {} 357 | 358 | # Store mail logs 359 | mail-log: 360 | enabled: true 361 | existingClaim: "" 362 | size: 1Gi 363 | annotations: {} 364 | accessModes: 365 | - ReadWriteOnce 366 | storageClass: 367 | selector: {} 368 | 369 | persistence: 370 | # Stores generated configuration files 371 | # https://docker-mailserver.github.io/docker-mailserver/edge/faq/#what-about-the-docker-datadmsconfig-directory 372 | mail-config: 373 | volumeName: mail-config 374 | mountPath: /tmp/docker-mailserver 375 | subPath: 376 | 377 | # Stores emails 378 | mail-data: 379 | volumeName: mail-data 380 | mountPath: /var/mail 381 | subPath: 382 | 383 | # Stores state for Postfix, Dovecot, Fail2Ban, Amavis, PostGrey, ClamAV, SpamAssassin, Rspamd & Redis 384 | # https://docker-mailserver.github.io/docker-mailserver/edge/faq/#what-about-the-docker-datadmsmail-state-directory 385 | mail-state: 386 | volumeName: mail-state 387 | mountPath: /var/mail-state 388 | subPath: 389 | 390 | # Store mail logs 391 | mail-log: 392 | volumeName: mail-log 393 | mountPath: /var/log/mail 394 | subPath: 395 | 396 | ## Monitoring adds the prometheus.io annotations to pods and services, so that the Prometheus Kubernetes SD mechanism 397 | ## as configured in the examples will automatically discover both the pods and the services to query. 398 | ## 399 | ## This defaults on, as the annotations should do no harm where Prometheus is not available but will automatically 400 | ## expose the application where Prometheus is. 401 | ## 402 | ## See https://github.com/prometheus/docs/blob/master/content/docs/operating/configuration.md 403 | ## See https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml 404 | monitoring: 405 | ## Whether to scrape this service with the monitoring toolkit. Mostly useful for blackbox probing of a given service 406 | ## to ensure it's "up" 407 | service: 408 | ## monitoring should be configured to only scrape services that have a value of "true" 409 | scrape: "true" 410 | ## monitoring should be configured to only probe services that have a value of "true" 411 | probe: "false" 412 | ## Path on which metrics are exposed 413 | path: "/metrics" 414 | ## Port on which HTTP server is served 415 | port: "9102" 416 | ## Whether to scape the pods associated with this application. Useful for collecting metrics. 417 | pod: 418 | ## monitoring should be configured to only scrape pods that have a value of `true` 419 | scrape: "true" 420 | ## monitoring should be configured to only probe services that have a value of "true" 421 | probe: "false" 422 | ## Path on which metrics are exposed 423 | path: "/metrics" 424 | ## Port on which HTTP server is served 425 | port: "9102" 426 | 427 | rspamd: 428 | ingress: 429 | enabled: false 430 | ingressClassName: nginx 431 | annotations: {} 432 | host: rspamd.example.com 433 | path: / 434 | tls: 435 | enabled: false 436 | secret: 437 | 438 | dovecot: 439 | fullTextSearch: 440 | enabled: false 441 | verbose: 0 # 0 (silent), 1 (verbose) or 2 (debug) 442 | resources: 443 | memory: 2GB 444 | cron: 445 | enabled: true # Optimize index every day 446 | schedule: 0 4 * * * # Every day at 4am 447 | 448 | proxyProtocol: 449 | enabled: true 450 | # List of sources (in CIDR format, space-separated) to permit PROXY protocol from 451 | trustedNetworks: "10.0.0.0/8 192.168.0.0/16 172.16.0.0/12" 452 | 453 | # when metrics is enabled, we mount subpath log from pvc into /var/log/mail 454 | metrics: 455 | enabled: false 456 | image: 457 | name: blackflysolutions/postfix-exporter@sha256 458 | tag: 7ed7c0534112aff5b44757ae84a206bf659171631edfc325c3c1638d78e74f73 459 | pullPolicy: "IfNotPresent" 460 | 461 | resources: 462 | requests: 463 | memory: "256Mi" 464 | # cpu: "100M" 465 | #limits: 466 | # memory: "256Mi" 467 | # cpu: "500M" 468 | 469 | serviceMonitor: 470 | enabled: false 471 | scrapeInterval: 15s 472 | ## Optionally add additional labels to the deployment 473 | labels: {} 474 | 475 | ## ConfigMaps (and Secrets) are used to copy docker-mailserver configuration files 476 | ## into running containers. This chart automatically sets up any config files that 477 | ## are stored in its chart/config directory. 478 | ## 479 | ## However, Helm does not provide a way to save external files to a ConfigMap or Secret. 480 | ## This is problem for docker-mailserver because you need to setup postfix accounts, 481 | ## dovecot accounts, etc. 482 | ## 483 | ## The configs and secrets keys solve this problem. They allow you to add additional config 484 | ## files by either referencing existing ConfigMaps (that you create before installing the Chart) 485 | ## or by creating new ones (set the create key to true). 486 | ## 487 | configMaps: 488 | dovecot.cf: 489 | create: true 490 | path: dovecot.cf 491 | data: | 492 | {{- if .Values.proxyProtocol.enabled }} 493 | haproxy_trusted_networks = {{ .Values.proxyProtocol.trustedNetworks }} 494 | 495 | {{- if and (.Values.deployment.env.ENABLE_IMAP) (not .Values.deployment.env.SMTP_ONLY) }} 496 | service imap-login { 497 | inet_listener imap { 498 | port = 143 499 | } 500 | 501 | inet_listener imaps { 502 | port = 993 503 | ssl = yes 504 | } 505 | 506 | inet_listener imap_proxy { 507 | haproxy = yes 508 | port = 10143 509 | ssl = no 510 | } 511 | 512 | inet_listener imaps_proxy { 513 | haproxy = yes 514 | port = 10993 515 | ssl = yes 516 | } 517 | } 518 | {{- end -}} 519 | 520 | {{- if and (.Values.deployment.env.ENABLE_POP3) (not .Values.deployment.env.SMTP_ONLY) }} 521 | service pop3-login { 522 | inet_listener pop3 { 523 | port = 110 524 | } 525 | 526 | inet_listener pop3s { 527 | port = 995 528 | ssl = yes 529 | } 530 | 531 | inet_listener pop3_proxy { 532 | haproxy = yes 533 | port = 10110 534 | ssl = no 535 | } 536 | 537 | inet_listener pop3s_proxy { 538 | haproxy = yes 539 | port = 10995 540 | ssl = yes 541 | } 542 | } 543 | {{- end -}} 544 | 545 | {{- if and (.Values.deployment.env.ENABLE_MANAGESIEVE) (not .Values.deployment.env.SMTP_ONLY) }} 546 | service managesieve-login { 547 | inet_listener sieve { 548 | port = 4190 549 | } 550 | 551 | inet_listener sieve_proxy { 552 | port = 14190 553 | } 554 | } 555 | {{- end -}} 556 | {{- end -}} 557 | 558 | fts-xapian-plugin.conf: 559 | create: true 560 | path: /etc/dovecot/conf.d/10-plugin.conf 561 | data: | 562 | {{- if .Values.dovecot.fullTextSearch.enabled }} 563 | mail_plugins = $mail_plugins fts fts_xapian 564 | 565 | plugin { 566 | fts = xapian 567 | fts_xapian = partial=3 full=20 verbose={{ .Values.dovecot.fullTextSearch.verbose }} 568 | 569 | fts_autoindex = yes 570 | fts_enforced = yes 571 | 572 | # Index attachements 573 | fts_decoder = decode2text 574 | } 575 | 576 | service indexer-worker { 577 | # limit size of indexer-worker RAM usage, ex: 512MB, 1GB, 2GB 578 | vsz_limit = {{ .Values.dovecot.fullTextSearch.resources.memory }} 579 | } 580 | {{- end -}} 581 | 582 | user-patches.sh: 583 | create: true 584 | path: user-patches.sh 585 | data: | 586 | #!/bin/bash 587 | 588 | {{- if .Values.proxyProtocol.enabled }} 589 | # Make sure to keep this file in sync with https://github.com/docker-mailserver/docker-mailserver/blob/master/target/postfix/master.cf! 590 | cat <> /etc/postfix/master.cf 591 | 592 | # Submission with proxy 593 | 10587 inet n - n - - smtpd 594 | -o syslog_name=postfix/submission 595 | -o smtpd_tls_security_level=encrypt 596 | -o smtpd_sasl_auth_enable=yes 597 | -o smtpd_sasl_type=dovecot 598 | -o smtpd_reject_unlisted_recipient=no 599 | -o smtpd_sasl_authenticated_header=yes 600 | -o smtpd_client_restrictions=permit_sasl_authenticated,reject 601 | -o smtpd_relay_restrictions=permit_sasl_authenticated,reject 602 | -o smtpd_sender_restrictions=\$mua_sender_restrictions 603 | -o smtpd_discard_ehlo_keywords= 604 | -o milter_macro_daemon_name=ORIGINATING 605 | -o cleanup_service_name=sender-cleanup 606 | -o smtpd_upstream_proxy_protocol=haproxy 607 | 608 | # Submissions with proxy 609 | 10465 inet n - n - - smtpd 610 | -o syslog_name=postfix/submissions 611 | -o smtpd_tls_wrappermode=yes 612 | -o smtpd_sasl_auth_enable=yes 613 | -o smtpd_sasl_type=dovecot 614 | -o smtpd_reject_unlisted_recipient=no 615 | -o smtpd_sasl_authenticated_header=yes 616 | -o smtpd_client_restrictions=permit_sasl_authenticated,reject 617 | -o smtpd_relay_restrictions=permit_sasl_authenticated,reject 618 | -o smtpd_sender_restrictions=\$mua_sender_restrictions 619 | -o smtpd_discard_ehlo_keywords= 620 | -o milter_macro_daemon_name=ORIGINATING 621 | -o cleanup_service_name=sender-cleanup 622 | -o smtpd_upstream_proxy_protocol=haproxy 623 | 624 | # Smtp with proxy 625 | 12525 inet n - n - 1 postscreen 626 | -o syslog_name=postfix/smtp-proxy 627 | -o postscreen_upstream_proxy_protocol=haproxy 628 | -o postscreen_cache_map=btree:$data_directory/postscreen_10025_cache 629 | EOS 630 | {{- end }} 631 | 632 | ## The secrets key works the same way as the configs key. Use secrets to store sensitive information, 633 | ## such as DKIM signing keys. 634 | ## 635 | ## secrets: 636 | ## rspamd.example.com: 637 | ## name: rspamd.example.com # This is the name of the Secret 638 | ## create: true # If true, create a new Secret 639 | ## path: rspamd.dkim.rsa-2048-mail-example.com.private.txt 640 | ## data: abace # If create is true, then you must specify content. Must be base 64 encoded! 641 | ## 642 | ## rspamd.dkim.rsa-2048-mail-example.com.public: 643 | ## name: rspamd.dkim.rsa-2048-mail-example.com.public 644 | ## create: true 645 | ## path: rspamd/dkim/rsa-2048-mail-example.com.public 646 | ## data: abace # If create is true, then you must specify content. Must be base 64 encoded! 647 | ## 648 | ## If you set the create key to false, then you must manually create the ConfigMaps before deploying the chart. 649 | ## 650 | ## kubectl create secret rspamd.example.com --namespace mail --from-file=rspamd.dkim.rsa-2048-mail-example.com.private.txt= 651 | secrets: {} 652 | 653 | ## @param extraDeploy Array of extra objects to deploy with the release 654 | ## 655 | extraDeploy: [] 656 | -------------------------------------------------------------------------------- /helm.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Source: immich/templates/machine-learning.yaml 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | name: release-name-machine-learning 7 | labels: 8 | app.kubernetes.io/service: release-name-machine-learning 9 | app.kubernetes.io/instance: release-name 10 | app.kubernetes.io/managed-by: Helm 11 | app.kubernetes.io/name: machine-learning 12 | app.kubernetes.io/version: v1.119.0 13 | helm.sh/chart: immich-0.9.0 14 | annotations: 15 | spec: 16 | type: ClusterIP 17 | ports: 18 | - port: 3003 19 | targetPort: http 20 | protocol: TCP 21 | name: http 22 | selector: 23 | app.kubernetes.io/instance: release-name 24 | app.kubernetes.io/name: machine-learning 25 | --- 26 | # Source: immich/templates/server.yaml 27 | apiVersion: v1 28 | kind: Service 29 | metadata: 30 | name: release-name-server 31 | labels: 32 | app.kubernetes.io/service: release-name-server 33 | app.kubernetes.io/instance: release-name 34 | app.kubernetes.io/managed-by: Helm 35 | app.kubernetes.io/name: server 36 | app.kubernetes.io/version: v1.119.0 37 | helm.sh/chart: immich-0.9.0 38 | annotations: 39 | spec: 40 | type: ClusterIP 41 | ports: 42 | - port: 2283 43 | targetPort: http 44 | protocol: TCP 45 | name: http 46 | selector: 47 | app.kubernetes.io/instance: release-name 48 | app.kubernetes.io/name: server 49 | --- 50 | # Source: immich/templates/machine-learning.yaml 51 | apiVersion: apps/v1 52 | kind: Deployment 53 | metadata: 54 | name: release-name-machine-learning 55 | labels: 56 | app.kubernetes.io/instance: release-name 57 | app.kubernetes.io/managed-by: Helm 58 | app.kubernetes.io/name: machine-learning 59 | app.kubernetes.io/version: v1.119.0 60 | helm.sh/chart: immich-0.9.0 61 | spec: 62 | revisionHistoryLimit: 3 63 | replicas: 1 64 | strategy: 65 | type: Recreate 66 | selector: 67 | matchLabels: 68 | app.kubernetes.io/name: machine-learning 69 | app.kubernetes.io/instance: release-name 70 | template: 71 | metadata: 72 | labels: 73 | app.kubernetes.io/name: machine-learning 74 | app.kubernetes.io/instance: release-name 75 | spec: 76 | 77 | serviceAccountName: default 78 | automountServiceAccountToken: true 79 | dnsPolicy: ClusterFirst 80 | enableServiceLinks: true 81 | containers: 82 | - name: release-name-machine-learning 83 | image: ghcr.io/immich-app/immich-machine-learning:v1.119.0 84 | imagePullPolicy: IfNotPresent 85 | env: 86 | - name: DB_DATABASE_NAME 87 | value: immich 88 | - name: DB_HOSTNAME 89 | value: postgresql.data 90 | - name: DB_PASSWORD 91 | value: immich 92 | - name: DB_USERNAME 93 | value: immich 94 | - name: DB_VECTOR_EXTENSION 95 | value: pgvector 96 | - name: IMMICH_MACHINE_LEARNING_URL 97 | value: http://release-name-machine-learning:3003 98 | - name: IMMICH_TELEMETRY_INCLUDE 99 | value: all 100 | - name: REDIS_HOSTNAME 101 | value: redis-master.data 102 | - name: TRANSFORMERS_CACHE 103 | value: /cache 104 | ports: 105 | - name: http 106 | containerPort: 3003 107 | protocol: TCP 108 | volumeMounts: 109 | - name: cache 110 | mountPath: /cache 111 | livenessProbe: 112 | failureThreshold: 3 113 | httpGet: 114 | path: /ping 115 | port: http 116 | initialDelaySeconds: 0 117 | periodSeconds: 10 118 | timeoutSeconds: 1 119 | readinessProbe: 120 | failureThreshold: 3 121 | httpGet: 122 | path: /ping 123 | port: http 124 | initialDelaySeconds: 0 125 | periodSeconds: 10 126 | timeoutSeconds: 1 127 | startupProbe: 128 | failureThreshold: 60 129 | httpGet: 130 | path: /ping 131 | port: http 132 | initialDelaySeconds: 0 133 | periodSeconds: 10 134 | timeoutSeconds: 1 135 | volumes: 136 | - name: cache 137 | emptyDir: 138 | {} 139 | --- 140 | # Source: immich/templates/server.yaml 141 | apiVersion: apps/v1 142 | kind: Deployment 143 | metadata: 144 | name: release-name-server 145 | labels: 146 | app.kubernetes.io/instance: release-name 147 | app.kubernetes.io/managed-by: Helm 148 | app.kubernetes.io/name: server 149 | app.kubernetes.io/version: v1.119.0 150 | helm.sh/chart: immich-0.9.0 151 | spec: 152 | revisionHistoryLimit: 3 153 | replicas: 1 154 | strategy: 155 | type: Recreate 156 | selector: 157 | matchLabels: 158 | app.kubernetes.io/name: server 159 | app.kubernetes.io/instance: release-name 160 | template: 161 | metadata: 162 | labels: 163 | app.kubernetes.io/name: server 164 | app.kubernetes.io/instance: release-name 165 | spec: 166 | 167 | serviceAccountName: default 168 | automountServiceAccountToken: true 169 | dnsPolicy: ClusterFirst 170 | enableServiceLinks: true 171 | containers: 172 | - name: release-name-server 173 | image: ghcr.io/immich-app/immich-server:v1.119.0 174 | imagePullPolicy: IfNotPresent 175 | env: 176 | - name: DB_DATABASE_NAME 177 | value: immich 178 | - name: DB_HOSTNAME 179 | value: postgresql.data 180 | - name: DB_PASSWORD 181 | value: immich 182 | - name: DB_USERNAME 183 | value: immich 184 | - name: DB_VECTOR_EXTENSION 185 | value: pgvector 186 | - name: IMMICH_MACHINE_LEARNING_URL 187 | value: http://release-name-machine-learning:3003 188 | - name: IMMICH_TELEMETRY_INCLUDE 189 | value: all 190 | - name: REDIS_HOSTNAME 191 | value: redis-master.data 192 | ports: 193 | - name: http 194 | containerPort: 2283 195 | protocol: TCP 196 | volumeMounts: 197 | - name: library 198 | mountPath: /usr/src/app/upload 199 | - name: pictures 200 | mountPath: /pictures 201 | subPath: cfis 202 | livenessProbe: 203 | failureThreshold: 3 204 | httpGet: 205 | path: /api/server/ping 206 | port: http 207 | initialDelaySeconds: 0 208 | periodSeconds: 10 209 | timeoutSeconds: 1 210 | readinessProbe: 211 | failureThreshold: 3 212 | httpGet: 213 | path: /api/server/ping 214 | port: http 215 | initialDelaySeconds: 0 216 | periodSeconds: 10 217 | timeoutSeconds: 1 218 | startupProbe: 219 | failureThreshold: 30 220 | httpGet: 221 | path: /api/server/ping 222 | port: http 223 | initialDelaySeconds: 0 224 | periodSeconds: 10 225 | timeoutSeconds: 1 226 | volumes: 227 | - name: library 228 | persistentVolumeClaim: 229 | claimName: immich-library 230 | - name: pictures 231 | persistentVolumeClaim: 232 | claimName: pictures-cfis 233 | --- 234 | # Source: immich/templates/server.yaml 235 | apiVersion: networking.k8s.io/v1 236 | kind: Ingress 237 | metadata: 238 | name: release-name-server 239 | labels: 240 | app.kubernetes.io/instance: release-name 241 | app.kubernetes.io/managed-by: Helm 242 | app.kubernetes.io/name: server 243 | app.kubernetes.io/version: v1.119.0 244 | helm.sh/chart: immich-0.9.0 245 | annotations: 246 | nginx.ingress.kubernetes.io/proxy-body-size: "0" 247 | spec: 248 | ingressClassName: nginx 249 | rules: 250 | - host: "immich.savagexi.com" 251 | http: 252 | paths: 253 | - path: "/" 254 | pathType: Prefix 255 | backend: 256 | service: 257 | name: release-name-server 258 | port: 259 | number: 2283 260 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ], 6 | "regexManagers": [ 7 | { 8 | "description": "Update docker-mailserver docker image references in appVersion", 9 | "fileMatch": ["Chart\\.yaml$"], 10 | "matchStrings": ["appVersion:\\s+['\"]?(?\\d+\\.\\d+\\.\\d+)['\"]?"], 11 | "depNameTemplate": "mailserver/docker-mailserver", 12 | "datasourceTemplate": "docker", 13 | "versioningTemplate": "docker" 14 | } 15 | ] 16 | } 17 | --------------------------------------------------------------------------------