This commit is contained in:
github-actions[bot] 2024-03-12 08:32:29 +00:00
parent fd5f60273d
commit 478b2f0a8c
10 changed files with 520 additions and 439 deletions

View File

@ -107,3 +107,37 @@ div.md-content article.md-content__inner a.toclink code {
.md-nav__item--nested > .md-nav__link { .md-nav__item--nested > .md-nav__link {
font-weight: 700; font-weight: 700;
} }
/* ============================================================================================================= */
/*
TaskList style for a pro/con list. Presently only used for this type of list in the kubernetes docs.
Uses a custom icon for the unchecked (con) state: :octicons-x-circle-fill-24:
https://github.com/squidfunk/mkdocs-material/discussions/6811#discussioncomment-8700795
TODO: Can better scope the style under a class name when migrating to block extension syntax:
https://github.com/facelessuser/pymdown-extensions/discussions/1973
*/
:root {
--md-tasklist-icon--failed: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12Zm8.036-4.024a.751.751 0 0 0-1.042.018.751.751 0 0 0-.018 1.042L10.939 12l-2.963 2.963a.749.749 0 0 0 .326 1.275.749.749 0 0 0 .734-.215L12 13.06l2.963 2.964a.75.75 0 0 0 1.061-1.06L13.061 12l2.963-2.964a.749.749 0 0 0-.326-1.275.749.749 0 0 0-.734.215L12 10.939Z"/></svg>');
}
.md-typeset [type="checkbox"] + .task-list-indicator::before {
background-color: rgb(216, 87, 48);
-webkit-mask-image: var(--md-tasklist-icon--failed);
mask-image: var(--md-tasklist-icon--failed);
}
/* More suitable shade of green */
.md-typeset [type=checkbox]:checked+.task-list-indicator:before {
background-color: rgb(97, 216, 42);
}
/* Tiny layout shift */
[dir=ltr] .md-typeset .task-list-indicator:before {
left: -1.6em;
top: 1px;
}
/* ============================================================================================================= */

View File

@ -2126,7 +2126,7 @@
</ul> </ul>
<div class="admonition example"> <div class="admonition example">
<p class="admonition-title">Setup Instructions</p> <p class="admonition-title">Setup Instructions</p>
<div class="tabbed-set tabbed-alternate" data-tabs="1:3"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">1. Docker Mailserver</label><label for="__tabbed_1_2">2. Authentik</label><label for="__tabbed_1_3">3. Roundcube</label></div> <div class="tabbed-set tabbed-alternate" data-tabs="1:3"><input checked="checked" id="1-docker-mailserver" name="__tabbed_1" type="radio" /><input id="2-authentik" name="__tabbed_1" type="radio" /><input id="3-roundcube" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="1-docker-mailserver">1. Docker Mailserver</label><label for="2-authentik">2. Authentik</label><label for="3-roundcube">3. Roundcube</label></div>
<div class="tabbed-content"> <div class="tabbed-content">
<div class="tabbed-block"> <div class="tabbed-block">
<p>Edit the following values in <code>mailserver.env</code>: <p>Edit the following values in <code>mailserver.env</code>:

View File

@ -2285,11 +2285,11 @@
<li>The network will also implicitly be assigned an IPv4 subnet (<em>from the Docker daemon config <code>default-address-pools</code></em>).</li> <li>The network will also implicitly be assigned an IPv4 subnet (<em>from the Docker daemon config <code>default-address-pools</code></em>).</li>
</ul> </ul>
</details> </details>
<div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">User-defined Network</label><label for="__tabbed_1_2">Default Bridge (daemon)</label></div> <div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="user-defined-network" name="__tabbed_1" type="radio" /><input id="default-bridge-daemon" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="user-defined-network">User-defined Network</label><label for="default-bridge-daemon">Default Bridge (daemon)</label></div>
<div class="tabbed-content"> <div class="tabbed-content">
<div class="tabbed-block"> <div class="tabbed-block">
<p>The preferred approach is with <a href="https://docs.docker.com/config/daemon/ipv6/#create-an-ipv6-network">user-defined networks</a> via <code>compose.yaml</code> (recommended) or CLI with <code>docker network create</code>:</p> <p>The preferred approach is with <a href="https://docs.docker.com/config/daemon/ipv6/#create-an-ipv6-network">user-defined networks</a> via <code>compose.yaml</code> (recommended) or CLI with <code>docker network create</code>:</p>
<div class="tabbed-set tabbed-alternate" data-tabs="2:2"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">Compose</label><label for="__tabbed_2_2">CLI</label></div> <div class="tabbed-set tabbed-alternate" data-tabs="2:2"><input checked="checked" id="compose" name="__tabbed_2" type="radio" /><input id="cli" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="compose">Compose</label><label for="cli">CLI</label></div>
<div class="tabbed-content"> <div class="tabbed-content">
<div class="tabbed-block"> <div class="tabbed-block">
<p>Create the network in <code>compose.yaml</code> and attach a service to it:</p> <p>Create the network in <code>compose.yaml</code> and attach a service to it:</p>

View File

@ -1417,72 +1417,12 @@
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
<a href="#manifests" class="md-nav__link"> <a href="#manually-writing-manifests" class="md-nav__link">
<span class="md-ellipsis"> <span class="md-ellipsis">
Manifests Manually Writing Manifests
</span> </span>
</a> </a>
<nav class="md-nav" aria-label="Manifests">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#configuration" class="md-nav__link">
<span class="md-ellipsis">
Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#persistence" class="md-nav__link">
<span class="md-ellipsis">
Persistence
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#service" class="md-nav__link">
<span class="md-ellipsis">
Service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#deployments" class="md-nav__link">
<span class="md-ellipsis">
Deployments
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#certificates-an-example" class="md-nav__link">
<span class="md-ellipsis">
Certificates - An Example
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#sensitive-data" class="md-nav__link">
<span class="md-ellipsis">
Sensitive Data
</span>
</a>
</li>
</ul>
</nav>
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
@ -1492,72 +1432,6 @@
</span> </span>
</a> </a>
<nav class="md-nav" aria-label="Exposing your Mail Server to the Outside World">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#external-ips-service" class="md-nav__link">
<span class="md-ellipsis">
External IPs Service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#proxy-port-to-service" class="md-nav__link">
<span class="md-ellipsis">
Proxy port to Service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#bind-to-concrete-node-and-use-host-network" class="md-nav__link">
<span class="md-ellipsis">
Bind to concrete Node and use host network
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#proxy-port-to-service-via-proxy-protocol" class="md-nav__link">
<span class="md-ellipsis">
Proxy Port to Service via PROXY Protocol
</span>
</a>
<nav class="md-nav" aria-label="Proxy Port to Service via PROXY Protocol">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#configure-your-ingress" class="md-nav__link">
<span class="md-ellipsis">
Configure your Ingress
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#configure-the-mailserver" class="md-nav__link">
<span class="md-ellipsis">
Configure the Mailserver
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li> </li>
</ul> </ul>
@ -2204,72 +2078,12 @@
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
<a href="#manifests" class="md-nav__link"> <a href="#manually-writing-manifests" class="md-nav__link">
<span class="md-ellipsis"> <span class="md-ellipsis">
Manifests Manually Writing Manifests
</span> </span>
</a> </a>
<nav class="md-nav" aria-label="Manifests">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#configuration" class="md-nav__link">
<span class="md-ellipsis">
Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#persistence" class="md-nav__link">
<span class="md-ellipsis">
Persistence
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#service" class="md-nav__link">
<span class="md-ellipsis">
Service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#deployments" class="md-nav__link">
<span class="md-ellipsis">
Deployments
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#certificates-an-example" class="md-nav__link">
<span class="md-ellipsis">
Certificates - An Example
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#sensitive-data" class="md-nav__link">
<span class="md-ellipsis">
Sensitive Data
</span>
</a>
</li>
</ul>
</nav>
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
@ -2279,72 +2093,6 @@
</span> </span>
</a> </a>
<nav class="md-nav" aria-label="Exposing your Mail Server to the Outside World">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#external-ips-service" class="md-nav__link">
<span class="md-ellipsis">
External IPs Service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#proxy-port-to-service" class="md-nav__link">
<span class="md-ellipsis">
Proxy port to Service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#bind-to-concrete-node-and-use-host-network" class="md-nav__link">
<span class="md-ellipsis">
Bind to concrete Node and use host network
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#proxy-port-to-service-via-proxy-protocol" class="md-nav__link">
<span class="md-ellipsis">
Proxy Port to Service via PROXY Protocol
</span>
</a>
<nav class="md-nav" aria-label="Proxy Port to Service via PROXY Protocol">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#configure-your-ingress" class="md-nav__link">
<span class="md-ellipsis">
Configure your Ingress
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#configure-the-mailserver" class="md-nav__link">
<span class="md-ellipsis">
Configure the Mailserver
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li> </li>
</ul> </ul>
@ -2381,19 +2129,30 @@
<h1>Kubernetes</h1> <h1>Kubernetes</h1>
<h2 id="introduction"><a class="toclink" href="#introduction">Introduction</a></h2> <h2 id="introduction"><a class="toclink" href="#introduction">Introduction</a></h2>
<p>This article describes how to deploy DMS to Kubernetes. Please note that there is also a <a href="https://github.com/docker-mailserver/docker-mailserver-helm">Helm chart</a> available.</p> <p>This article describes how to deploy DMS to Kubernetes. We highly recommend everyone to use our community <a href="https://github.com/docker-mailserver/docker-mailserver-helm">DMS Helm chart</a>.</p>
<div class="admonition attention"> <div class="admonition note">
<p class="admonition-title">Requirements</p> <p class="admonition-title">Requirements</p>
<p>We assume basic knowledge about Kubernetes from the reader. Moreover, we assume the reader to have a basic understanding of mail servers. Ideally, the reader has deployed DMS before in an easier setup with Docker (Compose).</p> <ol>
<li>Basic knowledge about Kubernetes from the reader.</li>
<li>A basic understanding of mail servers.</li>
<li>Ideally, the reader has already deployed DMS before with a simpler setup (<em><code>docker run</code> or Docker Compose</em>).</li>
</ol>
</div> </div>
<div class="admonition warning"> <div class="admonition warning">
<p class="admonition-title">About Support for Kubernetes</p> <p class="admonition-title">Limited Support</p>
<p>Please note that Kubernetes <strong>is not</strong> officially supported and we do not build images specifically designed for it. When opening an issue, please remember that only Docker &amp; Docker Compose are officially supported.</p> <p>DMS <strong>does not officially support Kubernetes</strong>. This content is entirely community-supported. If you find errors, please open an issue and raise a PR.</p>
<p>This content is entirely community-supported. If you find errors, please open an issue and provide a PR.</p>
</div> </div>
<h2 id="manifests"><a class="toclink" href="#manifests">Manifests</a></h2> <h2 id="manually-writing-manifests"><a class="toclink" href="#manually-writing-manifests">Manually Writing Manifests</a></h2>
<h3 id="configuration"><a class="toclink" href="#configuration">Configuration</a></h3> <p>If using our Helm chart is not viable for you, here is some guidance to start with your own manifests.</p>
<p>We want to provide the basic configuration in the form of environment variables with a <code>ConfigMap</code>. Note that this is just an example configuration; tune the <code>ConfigMap</code> to your needs.</p> <!-- This empty quote block is purely for a visual border -->
<div class="admonition quote">
<div class="tabbed-set tabbed-alternate" data-tabs="1:5"><input checked="checked" id="configmap" name="__tabbed_1" type="radio" /><input id="persistentvolumeclaim" name="__tabbed_1" type="radio" /><input id="service" name="__tabbed_1" type="radio" /><input id="certificate" name="__tabbed_1" type="radio" /><input id="deployment" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="configmap"><code>ConfigMap</code></label><label for="persistentvolumeclaim"><code>PersistentVolumeClaim</code></label><label for="service"><code>Service</code></label><label for="certificate"><code>Certificate</code></label><label for="deployment"><code>Deployment</code></label></div>
<div class="tabbed-content">
<div class="tabbed-block">
<p>Provide the basic configuration via environment variables with a <code>ConfigMap</code>.</p>
<div class="admonition example">
<p class="admonition-title">Example</p>
<p>Below is only an example configuration, adjust the <code>ConfigMap</code> to your own needs.</p>
<div class="highlight"><pre><span></span><code><span class="nn">---</span> <div class="highlight"><pre><span></span><code><span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span> <span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ConfigMap</span> <span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ConfigMap</span>
@ -2427,7 +2186,11 @@
<span class="w"> </span><span class="nt">SSL_CERT_PATH</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/secrets/ssl/rsa/tls.crt</span> <span class="w"> </span><span class="nt">SSL_CERT_PATH</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/secrets/ssl/rsa/tls.crt</span>
<span class="w"> </span><span class="nt">SSL_KEY_PATH</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/secrets/ssl/rsa/tls.key</span> <span class="w"> </span><span class="nt">SSL_KEY_PATH</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/secrets/ssl/rsa/tls.key</span>
</code></pre></div> </code></pre></div>
<p>We can also make use of user-provided configuration files, e.g. <code>user-patches.sh</code>, <code>postfix-accounts.cf</code> and more, to adjust DMS to our likings. We encourage you to have a look at <a href="https://kustomize.io/">Kustomize</a> for creating <code>ConfigMap</code>s from multiple files, but for now, we will provide a simple, hand-written example. This example is absolutely minimal and only goes to show what can be done.</p> </div>
<p>You can also make use of user-provided configuration files (<em>e.g. <code>user-patches.sh</code>, <code>postfix-accounts.cf</code>, etc</em>), to customize DMS to your needs.</p>
<details class="example">
<summary>Providing config files</summary>
<p>Here is a minimal example that supplies a <code>postfix-accounts.cf</code> file inline with two users:</p>
<div class="highlight"><pre><span></span><code><span class="nn">---</span> <div class="highlight"><pre><span></span><code><span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span> <span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ConfigMap</span> <span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ConfigMap</span>
@ -2440,13 +2203,22 @@
<span class="w"> </span><span class="no">test@example.com|{SHA512-CRYPT}$6$someHashValueHere</span> <span class="w"> </span><span class="no">test@example.com|{SHA512-CRYPT}$6$someHashValueHere</span>
<span class="w"> </span><span class="no">other@example.com|{SHA512-CRYPT}$6$someOtherHashValueHere</span> <span class="w"> </span><span class="no">other@example.com|{SHA512-CRYPT}$6$someOtherHashValueHere</span>
</code></pre></div> </code></pre></div>
<div class="admonition attention"> <div class="admonition warning">
<p class="admonition-title">Static Configuration</p> <p class="admonition-title">Static Configuration</p>
<p>With the configuration shown above, you can <strong>not</strong> dynamically add accounts as the configuration file mounted into the mail server can not be written to.</p> <p>The inline <code>postfix-accounts.cf</code> config example above provides file content that is static. It is mounted as read-only at runtime, thus cannot support modifications.</p>
<p>Use persistent volumes for production deployments.</p> <p>For production deployments, use persistent volumes instead (via <code>PersistentVolumeClaim</code>). That will enable files like <code>postfix-account.cf</code> to add and remove accounts, while also persisting those changes externally from the container.</p>
</div> </div>
<h3 id="persistence"><a class="toclink" href="#persistence">Persistence</a></h3> </details>
<p>Thereafter, we need persistence for our data. Make sure you have a storage provisioner and that you choose the correct <code>storageClassName</code>.</p> <div class="admonition tip">
<p class="admonition-title">Modularize your <code>ConfigMap</code></p>
<p><a href="https://kustomize.io/">Kustomize</a> can be a useful tool as it supports creating a <code>ConfigMap</code> from multiple files.</p>
</div>
</div>
<div class="tabbed-block">
<p>To persist data externally from the DMS container, configure a <code>PersistentVolumeClaim</code> (PVC).</p>
<p>Make sure you have a storage system (like Longhorn, Rook, etc.) and that you choose the correct <code>storageClassName</code> (according to your storage system).</p>
<div class="admonition example">
<p class="admonition-title">Example</p>
<div class="highlight"><pre><span></span><code><span class="nn">---</span> <div class="highlight"><pre><span></span><code><span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span> <span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">PersistentVolumeClaim</span> <span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">PersistentVolumeClaim</span>
@ -2462,9 +2234,13 @@
<span class="w"> </span><span class="nt">requests</span><span class="p">:</span> <span class="w"> </span><span class="nt">requests</span><span class="p">:</span>
<span class="w"> </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">25Gi</span> <span class="w"> </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">25Gi</span>
</code></pre></div> </code></pre></div>
<h3 id="service"><a class="toclink" href="#service">Service</a></h3> </div>
<p>A <code>Service</code> is required for getting the traffic to the pod itself. The service is somewhat crucial. Its configuration determines whether the original IP from the sender will be kept. <a href="#exposing-your-mail-server-to-the-outside-world">More about this further down below</a>.</p> </div>
<p>The configuration you're seeing does keep the original IP, but you will not be able to scale this way. We have chosen to go this route in this case because we think most Kubernetes users will only want to have one instance.</p> <div class="tabbed-block">
<p>A <a href="https://kubernetes.io/docs/concepts/services-networking/service"><code>Service</code></a> is required for getting the traffic to the pod itself. It configures a load balancer with the ports you'll need.</p>
<p>The configuration for a <code>Service</code> affects if the original IP from a connecting client is preserved (<em>this is important</em>). <a href="#exposing-your-mail-server-to-the-outside-world">More about this further down below</a>.</p>
<div class="admonition example">
<p class="admonition-title">Example</p>
<div class="highlight"><pre><span></span><code><span class="nn">---</span> <div class="highlight"><pre><span></span><code><span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span> <span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Service</span> <span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Service</span>
@ -2481,29 +2257,71 @@
<span class="w"> </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver</span> <span class="w"> </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver</span>
<span class="w"> </span><span class="nt">ports</span><span class="p">:</span> <span class="w"> </span><span class="nt">ports</span><span class="p">:</span>
<span class="w"> </span><span class="c1"># Transfer</span> <span class="w"> </span><span class="c1"># smtp</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">transfer</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">smtp</span>
<span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">25</span> <span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">25</span>
<span class="w"> </span><span class="nt">targetPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">transfer</span> <span class="w"> </span><span class="nt">targetPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">smtp</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span> <span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="w"> </span><span class="c1"># ESMTP with implicit TLS</span> <span class="w"> </span><span class="c1"># submissions (ESMTP with implicit TLS)</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">esmtp-implicit</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">submission</span>
<span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">465</span> <span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">465</span>
<span class="w"> </span><span class="nt">targetPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">esmtp-implicit</span> <span class="w"> </span><span class="nt">targetPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">submissions</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span> <span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="w"> </span><span class="c1"># ESMTP with explicit TLS (STARTTLS)</span> <span class="w"> </span><span class="c1"># submission (ESMTP with explicit TLS)</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">esmtp-explicit</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">submission</span>
<span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">587</span> <span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">587</span>
<span class="w"> </span><span class="nt">targetPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">esmtp-explicit</span> <span class="w"> </span><span class="nt">targetPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">submission</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span> <span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="w"> </span><span class="c1"># IMAPS with implicit TLS</span> <span class="w"> </span><span class="c1"># imaps (implicit TLS)</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imap-implicit</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imaps</span>
<span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">993</span> <span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">993</span>
<span class="w"> </span><span class="nt">targetPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imap-implicit</span> <span class="w"> </span><span class="nt">targetPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imaps</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span> <span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
</code></pre></div> </code></pre></div>
<h3 id="deployments"><a class="toclink" href="#deployments">Deployments</a></h3> </div>
<p>Last but not least, the <code>Deployment</code> becomes the most complex component. It instructs Kubernetes how to run the DMS container and how to apply your <code>ConfigMaps</code>, persisted storage, etc. Additionally, we can set options to enforce runtime security here.</p> </div>
<div class="tabbed-block">
<div class="admonition example">
<p class="admonition-title">Using <a href="https://cert-manager.io/docs/"><code>cert-manager</code></a> to supply TLS certificates</p>
<div class="highlight"><pre><span></span><code><span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">cert-manager.io/v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Certificate</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mail-tls-certificate-rsa</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">secretName</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mail-tls-certificate-rsa</span>
<span class="w"> </span><span class="nt">isCA</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">false</span>
<span class="w"> </span><span class="nt">privateKey</span><span class="p">:</span>
<span class="w"> </span><span class="nt">algorithm</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">RSA</span>
<span class="w"> </span><span class="nt">encoding</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">PKCS1</span>
<span class="w"> </span><span class="nt">size</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2048</span>
<span class="w"> </span><span class="nt">dnsNames</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">[</span><span class="nv">mail.example.com</span><span class="p p-Indicator">]</span>
<span class="w"> </span><span class="nt">issuerRef</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mail-issuer</span>
<span class="w"> </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Issuer</span>
</code></pre></div>
<p>The <a href="../../security/ssl/">TLS docs page</a> provides guidance when it comes to certificates and transport layer security.</p>
</div>
<div class="admonition tip">
<p class="admonition-title">ECDSA + RSA (fallback)</p>
<p>You could supply RSA certificates as fallback certificates instead, with ECDSA as the primary. DMS supports dual certificates via the ENV <code>SSL_ALT_CERT_PATH</code> and <code>SSL_ALT_KEY_PATH</code>.</p>
</div>
<div class="admonition warning">
<p class="admonition-title">Always provide sensitive information via a <code>Secret</code></p>
<p>For storing OpenDKIM keys, TLS certificates, or any sort of sensitive data - you should be using <code>Secret</code>s.</p>
<p>A <code>Secret</code> is similar to <code>ConfigMap</code>, it can be used and mounted as a volume as demonstrated in the <a href="#deployment"><code>Deployment</code> manifest</a> tab.</p>
</div>
</div>
<div class="tabbed-block">
<p>The <a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-a-deployment"><code>Deployment</code></a> config is the most complex component.</p>
<ul>
<li>It instructs Kubernetes how to run the DMS container and how to apply your <code>ConfigMap</code>s, persisted storage, etc.</li>
<li>Additional options can be set to enforce runtime security.</li>
</ul>
<details class="example" open="open">
<summary>Example</summary>
<div class="highlight"><pre><span></span><code><span class="nn">---</span> <div class="highlight"><pre><span></span><code><span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">apps/v1</span> <span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">apps/v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Deployment</span> <span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Deployment</span>
@ -2517,8 +2335,7 @@
<span class="w"> </span><span class="nt">ignore-check.kube-linter.io/privileged-ports</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">&gt;-</span> <span class="w"> </span><span class="nt">ignore-check.kube-linter.io/privileged-ports</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">&gt;-</span>
<span class="w"> </span><span class="no">&#39;mailserver&#39; needs privileged ports</span> <span class="w"> </span><span class="no">&#39;mailserver&#39; needs privileged ports</span>
<span class="w"> </span><span class="nt">ignore-check.kube-linter.io/no-read-only-root-fs</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">&gt;-</span> <span class="w"> </span><span class="nt">ignore-check.kube-linter.io/no-read-only-root-fs</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">&gt;-</span>
<span class="w"> </span><span class="no">There are too many files written to make The</span> <span class="w"> </span><span class="no">There are too many files written to make the root FS read-only</span>
<span class="w"> </span><span class="no">root FS read-only</span>
<span class="nt">spec</span><span class="p">:</span> <span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">replicas</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span> <span class="w"> </span><span class="nt">replicas</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
@ -2542,8 +2359,8 @@
<span class="w"> </span><span class="nt">imagePullPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">IfNotPresent</span> <span class="w"> </span><span class="nt">imagePullPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">IfNotPresent</span>
<span class="w"> </span><span class="nt">securityContext</span><span class="p">:</span> <span class="w"> </span><span class="nt">securityContext</span><span class="p">:</span>
<span class="w"> </span><span class="c1"># Required to support SGID via `postdrop` executable</span> <span class="w"> </span><span class="c1"># `allowPrivilegeEscalation: true` is required to support SGID via the `postdrop`</span>
<span class="w"> </span><span class="c1"># in `/var/mail-state` for Postfix (maildrop + public dirs):</span> <span class="w"> </span><span class="c1"># executable in `/var/mail-state` for Postfix (maildrop + public dirs):</span>
<span class="w"> </span><span class="c1"># https://github.com/docker-mailserver/docker-mailserver/pull/3625</span> <span class="w"> </span><span class="c1"># https://github.com/docker-mailserver/docker-mailserver/pull/3625</span>
<span class="w"> </span><span class="nt">allowPrivilegeEscalation</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span> <span class="w"> </span><span class="nt">allowPrivilegeEscalation</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
<span class="w"> </span><span class="nt">readOnlyRootFilesystem</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">false</span> <span class="w"> </span><span class="nt">readOnlyRootFilesystem</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">false</span>
@ -2571,10 +2388,10 @@
<span class="w"> </span><span class="nt">seccompProfile</span><span class="p">:</span> <span class="w"> </span><span class="nt">seccompProfile</span><span class="p">:</span>
<span class="w"> </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">RuntimeDefault</span> <span class="w"> </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">RuntimeDefault</span>
<span class="w"> </span><span class="c1"># You want to tune this to your needs. If you disable ClamAV,</span> <span class="w"> </span><span class="c1"># Tune this to your needs.</span>
<span class="w"> </span><span class="c1"># you can use less RAM and CPU. This becomes important in</span> <span class="w"> </span><span class="c1"># If you disable ClamAV, you can use less RAM and CPU.</span>
<span class="w"> </span><span class="c1"># case you&#39;re low on resources and Kubernetes refuses to</span> <span class="w"> </span><span class="c1"># This becomes important in case you&#39;re low on resources</span>
<span class="w"> </span><span class="c1"># schedule new pods.</span> <span class="w"> </span><span class="c1"># and Kubernetes refuses to schedule new pods.</span>
<span class="w"> </span><span class="nt">resources</span><span class="p">:</span> <span class="w"> </span><span class="nt">resources</span><span class="p">:</span>
<span class="w"> </span><span class="nt">limits</span><span class="p">:</span> <span class="w"> </span><span class="nt">limits</span><span class="p">:</span>
<span class="w"> </span><span class="nt">memory</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">4Gi</span> <span class="w"> </span><span class="nt">memory</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">4Gi</span>
@ -2608,21 +2425,16 @@
<span class="w"> </span><span class="nt">mountPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/secrets/ssl/rsa/</span> <span class="w"> </span><span class="nt">mountPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/secrets/ssl/rsa/</span>
<span class="w"> </span><span class="nt">readOnly</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span> <span class="w"> </span><span class="nt">readOnly</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
<span class="w"> </span><span class="c1"># other</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">tmp-files</span>
<span class="w"> </span><span class="nt">mountPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/tmp</span>
<span class="w"> </span><span class="nt">readOnly</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">false</span>
<span class="w"> </span><span class="nt">ports</span><span class="p">:</span> <span class="w"> </span><span class="nt">ports</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">transfer</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">smtp</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">25</span> <span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">25</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span> <span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">esmtp-implicit</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">submissions</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">465</span> <span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">465</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span> <span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">esmtp-explicit</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">submission</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">587</span> <span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">587</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imap-implicit</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imaps</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">993</span> <span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">993</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span> <span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
@ -2652,47 +2464,44 @@
<span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">tls.key</span> <span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">tls.key</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">tls.crt</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">tls.crt</span>
<span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">tls.crt</span> <span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">tls.crt</span>
<span class="w"> </span><span class="c1"># other</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">tmp-files</span>
<span class="w"> </span><span class="nt">emptyDir</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">{}</span>
</code></pre></div> </code></pre></div>
<h3 id="certificates-an-example"><a class="toclink" href="#certificates-an-example">Certificates - An Example</a></h3> </details>
<p>In this example, we use <a href="https://cert-manager.io/docs/"><code>cert-manager</code></a> to supply RSA certificates. You can also supply RSA certificates as fallback certificates, which DMS supports out of the box with <code>SSL_ALT_CERT_PATH</code> and <code>SSL_ALT_KEY_PATH</code>, and provide ECDSA as the proper certificates.</p> </div>
<div class="highlight"><pre><span></span><code><span class="nn">---</span> </div>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">cert-manager.io/v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Certificate</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mail-tls-certificate-rsa</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">secretName</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mail-tls-certificate-rsa</span>
<span class="w"> </span><span class="nt">isCA</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">false</span>
<span class="w"> </span><span class="nt">privateKey</span><span class="p">:</span>
<span class="w"> </span><span class="nt">algorithm</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">RSA</span>
<span class="w"> </span><span class="nt">encoding</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">PKCS1</span>
<span class="w"> </span><span class="nt">size</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2048</span>
<span class="w"> </span><span class="nt">dnsNames</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">[</span><span class="nv">mail.example.com</span><span class="p p-Indicator">]</span>
<span class="w"> </span><span class="nt">issuerRef</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mail-issuer</span>
<span class="w"> </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Issuer</span>
</code></pre></div>
<div class="admonition attention">
<p class="admonition-title">Attention</p>
<p>You will need to have <a href="https://cert-manager.io/docs/"><code>cert-manager</code></a> configured. Especially the issue will need to be configured. Since we do not know how you want or need your certificates to be supplied, we do not provide more configuration here. The documentation for <a href="https://cert-manager.io/docs/"><code>cert-manager</code></a> is excellent.</p>
</div> </div>
<h3 id="sensitive-data"><a class="toclink" href="#sensitive-data">Sensitive Data</a></h3>
<div class="admonition attention">
<p class="admonition-title">Sensitive Data</p>
<p>For storing OpenDKIM keys, TLS certificates or any sort of sensitive data, you should be using <code>Secret</code>s. You can mount secrets like <code>ConfigMap</code>s and use them the same way.</p>
</div> </div>
<p>The <a href="../../security/ssl/">TLS docs page</a> provides guidance when it comes to certificates and transport layer security. Always provide sensitive information vai <code>Secrets</code>.</p>
<h2 id="exposing-your-mail-server-to-the-outside-world"><a class="toclink" href="#exposing-your-mail-server-to-the-outside-world">Exposing your Mail Server to the Outside World</a></h2> <h2 id="exposing-your-mail-server-to-the-outside-world"><a class="toclink" href="#exposing-your-mail-server-to-the-outside-world">Exposing your Mail Server to the Outside World</a></h2>
<p>The more difficult part with Kubernetes is to expose a deployed DMS to the outside world. Kubernetes provides multiple ways for doing that; each has downsides and complexity. The major problem with exposing DMS to outside world in Kubernetes is to <a href="https://kubernetes.io/docs/tutorials/services/source-ip">preserve the real client IP</a>. The real client IP is required by DMS for performing IP-based SPF checks and spam checks. If you do not require SPF checks for incoming mails, you may disable them in your <a href="../override-defaults/postfix/">Postfix configuration</a> by dropping the line that states: <code>check_policy_service unix:private/policyd-spf</code>.</p> <p>The more difficult part with Kubernetes is to expose a deployed DMS instance to the outside world.</p>
<p>The easiest approach was covered above, using <code class="highlight"><span class="nt">externalTrafficPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Local</span></code>, which disables the service proxy, but makes the service local as well (which does not scale). This approach only works when you are given the correct (that is, a public and routable) IP address by a load balancer (like MetalLB). In this sense, the approach above is similar to the next example below. We want to provide you with a few alternatives too. <strong>But</strong> we also want to communicate the idea of another simple method: you could use a load-balancer without an external IP and DNAT the network traffic to the mail server. After all, this does not interfere with SPF checks because it keeps the origin IP address. If no dedicated external IP address is available, you could try the latter approach, if one is available, use the former.</p> <p>The major problem with exposing DMS to the outside world in Kubernetes is to <a href="https://kubernetes.io/docs/tutorials/services/source-ip">preserve the real client IP</a>. The real client IP is required by DMS for performing IP-based DNS and spam checks.</p>
<h3 id="external-ips-service"><a class="toclink" href="#external-ips-service">External IPs Service</a></h3> <p>Kubernetes provides multiple ways to address this; each has its upsides and downsides.</p>
<p>The simplest way is to expose DMS as a <a href="https://kubernetes.io/docs/concepts/services-networking/service">Service</a> with <a href="https://kubernetes.io/docs/concepts/services-networking/service/#external-ips">external IPs</a>. This is very similar to the approach taken above. Here, an external IP is given to the service directly by you. With the approach above, you tell your load-balancer to do this.</p> <!-- This empty quote block is purely for a visual border -->
<div class="admonition quote">
<div class="tabbed-set tabbed-alternate" data-tabs="2:3"><input checked="checked" id="configure-ip-manually" name="__tabbed_2" type="radio" /><input id="host-network" name="__tabbed_2" type="radio" /><input id="using-the-proxy-protocol" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="configure-ip-manually">Configure IP Manually</label><label for="host-network">Host network</label><label for="using-the-proxy-protocol">Using the PROXY Protocol</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
<details class="abstract" open="open">
<summary>Advantages / Disadvantages</summary>
<ul class="task-list">
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled checked/><span class="task-list-indicator"></span></label> Simple</li>
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled/><span class="task-list-indicator"></span></label> Requires the node to have a dedicated, publicly routable IP address</li>
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled/><span class="task-list-indicator"></span></label> Limited to a single node (<em>associated to the dedicated IP address</em>)</li>
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled/><span class="task-list-indicator"></span></label> Your deployment requires an explicit IP in your configuration (<em>or an entire Load Balancer</em>).</li>
</ul>
</details>
<div class="admonition info">
<p class="admonition-title">Requirements</p>
<ol>
<li>You can dedicate a <strong>publicly routable IP</strong> address for the DMS configured <code>Service</code>.</li>
<li>A dedicated IP is required to allow your mail server to have matching <code>A</code> and <code>PTR</code> records (<em>which other mail servers will use to verify trust when they receive mail sent from your DMS instance</em>).</li>
</ol>
</div>
<div class="admonition example">
<p class="admonition-title">Example</p>
<p>Assign the DMS <code>Service</code> an external IP directly, or delegate an LB to assign the IP on your behalf.</p>
<div class="tabbed-set tabbed-alternate" data-tabs="3:2"><input checked="checked" id="external-ip-service" name="__tabbed_3" type="radio" /><input id="load-balancer" name="__tabbed_3" type="radio" /><div class="tabbed-labels"><label for="external-ip-service">External-IP Service</label><label for="load-balancer">Load-Balancer</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
<p>The DMS <code>Service</code> is configured with an "<a href="https://kubernetes.io/docs/concepts/services-networking/service/#external-ips">external IP</a>" manually. Append your externally reachable IP address to <code>spec.externalIPs</code>.</p>
<div class="highlight"><pre><span></span><code><span class="nn">---</span> <div class="highlight"><pre><span></span><code><span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span> <span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Service</span> <span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Service</span>
@ -2712,23 +2521,68 @@
<span class="w"> </span><span class="c1"># ...</span> <span class="w"> </span><span class="c1"># ...</span>
<span class="w"> </span><span class="nt">externalIPs</span><span class="p">:</span> <span class="w"> </span><span class="nt">externalIPs</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">80.11.12.10</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">10.20.30.40</span>
</code></pre></div> </code></pre></div>
<p>This approach</p> </div>
<ul> <div class="tabbed-block">
<li>does not preserve the real client IP, so SPF check of incoming mail will fail.</li> <p>The config differs depending on your choice of load balancer. This example uses <a href="https://metallb.universe.tf/">MetalLB</a>.</p>
<li>requires you to specify the exposed IPs explicitly.</li>
</ul>
<h3 id="proxy-port-to-service"><a class="toclink" href="#proxy-port-to-service">Proxy port to Service</a></h3>
<p>The <a href="https://github.com/kubernetes/contrib/tree/master/for-demos/proxy-to-service">proxy pod</a> helps to avoid the necessity of specifying external IPs explicitly. This comes at the cost of complexity; you must deploy a proxy pod on each <a href="https://kubernetes.io/docs/concepts/architecture/nodes">Node</a> you want to expose DMS on.</p>
<p>This approach</p>
<ul>
<li>does not preserve the real client IP, so SPF check of incoming mail will fail.</li>
</ul>
<h3 id="bind-to-concrete-node-and-use-host-network"><a class="toclink" href="#bind-to-concrete-node-and-use-host-network">Bind to concrete Node and use host network</a></h3>
<p>One way to preserve the real client IP is to use <code>hostPort</code> and <code>hostNetwork: true</code>. This comes at the cost of availability; you can reach DMS from the outside world only via IPs of <a href="https://kubernetes.io/docs/concepts/architecture/nodes">Node</a> where DMS is deployed.</p>
<div class="highlight"><pre><span></span><code><span class="nn">---</span> <div class="highlight"><pre><span></span><code><span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">extensions/v1beta1</span> <span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Service</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver</span>
<span class="w"> </span><span class="nt">labels</span><span class="p">:</span>
<span class="w"> </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver</span>
<span class="w"> </span><span class="nt">annotations</span><span class="p">:</span>
<span class="w"> </span><span class="nt">metallb.universe.tf/address-pool</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver</span>
<span class="c1"># ...</span>
<span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">metallb.io/v1beta1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">IPAddressPool</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mail</span>
<span class="w"> </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">metallb-system</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">addresses</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">[</span><span class="w"> </span><span class="nv">&lt;YOUR PUBLIC DEDICATED IP IN CIDR NOTATION&gt;</span><span class="w"> </span><span class="p p-Indicator">]</span>
<span class="w"> </span><span class="nt">autoAssign</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
<span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">metallb.io/v1beta1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">L2Advertisement</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mail</span>
<span class="w"> </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">metallb-system</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">ipAddressPools</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">[</span><span class="w"> </span><span class="nv">mailserver</span><span class="w"> </span><span class="p p-Indicator">]</span>
</code></pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="tabbed-block">
<details class="abstract" open="open">
<summary>Advantages / Disadvantages</summary>
<ul class="task-list">
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled checked/><span class="task-list-indicator"></span></label> Simple</li>
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled/><span class="task-list-indicator"></span></label> Requires the node to have a dedicated, publicly routable IP address</li>
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled/><span class="task-list-indicator"></span></label> Limited to a single node (<em>associated to the dedicated IP address</em>)</li>
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled/><span class="task-list-indicator"></span></label> It is not possible to access DMS via other cluster nodes, only via the node that DMS was deployed on</li>
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled/><span class="task-list-indicator"></span></label> Every port within the container is exposed on the host side</li>
</ul>
</details>
<div class="admonition example">
<p class="admonition-title">Example</p>
<p>Using <code>hostPort</code> and <code>hostNetwork: true</code> is a similar approach to <a href="https://docs.docker.com/compose/compose-file/compose-file-v3/#network_mode"><code>network_mode: host</code> with Docker Compose</a>.</p>
<div class="highlight"><pre><span></span><code><span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">apps/v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Deployment</span> <span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Deployment</span>
<span class="nt">metadata</span><span class="p">:</span> <span class="nt">metadata</span><span class="p">:</span>
@ -2737,7 +2591,6 @@
<span class="c1"># ...</span> <span class="c1"># ...</span>
<span class="w"> </span><span class="nt">spec</span><span class="p">:</span> <span class="w"> </span><span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">hostNetwork</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span> <span class="w"> </span><span class="nt">hostNetwork</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
<span class="w"> </span><span class="c1"># ...</span> <span class="w"> </span><span class="c1"># ...</span>
<span class="w"> </span><span class="nt">containers</span><span class="p">:</span> <span class="w"> </span><span class="nt">containers</span><span class="p">:</span>
<span class="w"> </span><span class="c1"># ...</span> <span class="w"> </span><span class="c1"># ...</span>
@ -2745,40 +2598,149 @@
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">smtp</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">smtp</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">25</span> <span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">25</span>
<span class="w"> </span><span class="nt">hostPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">25</span> <span class="w"> </span><span class="nt">hostPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">25</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">smtp-auth</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">submissions</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">465</span>
<span class="w"> </span><span class="nt">hostPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">465</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">submission</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">587</span> <span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">587</span>
<span class="w"> </span><span class="nt">hostPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">587</span> <span class="w"> </span><span class="nt">hostPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">587</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imap-secure</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imaps</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">993</span> <span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">993</span>
<span class="w"> </span><span class="nt">hostPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">993</span> <span class="w"> </span><span class="nt">hostPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">993</span>
<span class="w"> </span><span class="c1"># ...</span>
</code></pre></div> </code></pre></div>
<p>With this approach,</p> </div>
<ul> </div>
<li>it is not possible to access DMS via other cluster Nodes, only via the Node DMS was deployed at.</li> <div class="tabbed-block">
<li>every Port within the Container is exposed on the Host side.</li> <details class="abstract" open="open">
<summary>Advantages / Disadvantages</summary>
<ul class="task-list">
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled checked/><span class="task-list-indicator"></span></label> Preserves the origin IP address of clients (<em>which is crucial for DNS related checks</em>)</li>
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled checked/><span class="task-list-indicator"></span></label> Aligns with a best practice for Kubernetes by using a dedicated ingress, routing external traffic to the k8s cluster (<em>with the benefits of flexible routing rules</em>)</li>
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled checked/><span class="task-list-indicator"></span></label> Avoids the restraint of a single <a href="https://kubernetes.io/docs/concepts/architecture/nodes">node</a> (<em>as a workaround to preserve the original client IP</em>)</li>
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled/><span class="task-list-indicator"></span></label> Introduces complexity by requiring:<ul>
<li>A reverse-proxy / ingress controller (<em>potentially extra setup</em>)</li>
<li>Kubernetes manifest changes for the DMS configured <code>Service</code></li>
<li>DMS configuration changes for Postfix and Dovecot</li>
</ul> </ul>
<h3 id="proxy-port-to-service-via-proxy-protocol"><a class="toclink" href="#proxy-port-to-service-via-proxy-protocol">Proxy Port to Service via PROXY Protocol</a></h3> </li>
<p>This way is ideologically the same as <a href="#proxy-port-to-service">using a proxy pod</a>, but instead of a separate proxy pod, you configure your ingress to proxy TCP traffic to the DMS pod using the PROXY protocol, which preserves the real client IP.</p> <li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled/><span class="task-list-indicator"></span></label> To keep support for direct connections to DMS services internally within cluster, service ports must be "duplicated" to offer an alternative port for connections using PROXY protocol</li>
<h4 id="configure-your-ingress"><a class="toclink" href="#configure-your-ingress">Configure your Ingress</a></h4> </ul>
<p>With an <a href="https://kubernetes.github.io/ingress-nginx">NGINX ingress controller</a>, set <code>externalTrafficPolicy: Local</code> for its service, and add the following to the TCP services config map (as described <a href="https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services">here</a>):</p> </details>
<details class="question">
<summary>What is the PROXY protocol?</summary>
<p>PROXY protocol is a network protocol for preserving a clients IP address when the clients TCP connection passes through a proxy.</p>
<p>It is a common feature supported among reverse-proxy services (<em>NGINX, HAProxy, Traefik</em>), which you may already have handling ingress traffic for your cluster.</p>
<pre class="mermaid"><code>flowchart LR
A(External Mail Server) --&gt;|Incoming connection| B
subgraph cluster
B("Ingress Acting as a Proxy") --&gt;|PROXY protocol connection| C(DMS)
end</code></pre>
<p>For more information on the PROXY protocol, refer to <a href="../../../examples/tutorials/mailserver-behind-proxy/">our dedicated docs page</a> on the topic.</p>
</details>
<details class="example" open="open">
<summary>Configure the Ingress Controller</summary>
<div class="tabbed-set tabbed-alternate" data-tabs="4:2"><input checked="checked" id="traefik" name="__tabbed_4" type="radio" /><input id="nginx" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="traefik">Traefik</label><label for="nginx">NGINX</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
<p>On Traefik's side, the configuration is very simple.</p>
<ul>
<li>Create an entrypoint for each port that you want to expose (<em>probably 25, 465, 587 and 993</em>).</li>
<li>Each entrypoint should configure an <a href="https://doc.traefik.io/traefik/routing/providers/kubernetes-crd/#kind-ingressroutetcp"><code>IngressRouteTCP</code></a> that routes to the equivalent internal DMS <code>Service</code> port which supports PROXY protocol connections.</li>
</ul>
<p>The below snippet demonstrates an example for two entrypoints, <code>submissions</code> (port 465) and <code>imaps</code> (port 993).</p>
<div class="highlight"><pre><span></span><code><span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Service</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="c1"># This an optimization to get rid of additional routing steps.</span>
<span class="w"> </span><span class="c1"># Previously &quot;type: LoadBalancer&quot;</span>
<span class="w"> </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ClusterIP</span>
<span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">traefik.io/v1alpha1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">IngressRouteTCP</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">smtp</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">entryPoints</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">[</span><span class="w"> </span><span class="nv">submissions</span><span class="w"> </span><span class="p p-Indicator">]</span>
<span class="w"> </span><span class="nt">routes</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">match</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">HostSNI(`*`)</span>
<span class="w"> </span><span class="nt">services</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver</span>
<span class="w"> </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mail</span>
<span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">subs-proxy</span><span class="w"> </span><span class="c1"># note the 15 character limit here</span>
<span class="w"> </span><span class="nt">proxyProtocol</span><span class="p">:</span>
<span class="w"> </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2</span>
<span class="nn">---</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">traefik.io/v1alpha1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">IngressRouteTCP</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imaps</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">entryPoints</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">[</span><span class="w"> </span><span class="nv">imaps</span><span class="w"> </span><span class="p p-Indicator">]</span>
<span class="w"> </span><span class="nt">routes</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">match</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">HostSNI(`*`)</span>
<span class="w"> </span><span class="nt">services</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver</span>
<span class="w"> </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mail</span>
<span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imaps-proxy</span>
<span class="w"> </span><span class="nt">proxyProtocol</span><span class="p">:</span>
<span class="w"> </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2</span>
</code></pre></div>
<div class="admonition info">
<p class="admonition-title"><code>*-proxy</code> port name suffix</p>
<p>The <code>IngressRouteTCP</code> example configs above reference ports with a <code>*-proxy</code> suffix.</p>
<ul>
<li>These port variants will be defined in the <a href="#deployment"><code>Deployment</code> manifest</a>, and are scoped to the <code>mailserver</code> service (via <code>spec.routes.services.name</code>).</li>
<li>The suffix is used to distinguish that these ports are only compatible with connections using the PROXY protocol, which is what your ingress controller should be managing for you by adding the correct PROXY protocol headers to TCP connections it routes to DMS.</li>
</ul>
</div>
</div>
<div class="tabbed-block">
<p>With an <a href="https://kubernetes.github.io/ingress-nginx">NGINX ingress controller</a>, add the following to the TCP services config map (<em>as described <a href="https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services">here</a></em>):</p>
<div class="highlight"><pre><span></span><code><span class="nt">25</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;mailserver/mailserver:25::PROXY&quot;</span> <div class="highlight"><pre><span></span><code><span class="nt">25</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;mailserver/mailserver:25::PROXY&quot;</span>
<span class="nt">465</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;mailserver/mailserver:465::PROXY&quot;</span> <span class="nt">465</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;mailserver/mailserver:465::PROXY&quot;</span>
<span class="nt">587</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;mailserver/mailserver:587::PROXY&quot;</span> <span class="nt">587</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;mailserver/mailserver:587::PROXY&quot;</span>
<span class="nt">993</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;mailserver/mailserver:993::PROXY&quot;</span> <span class="nt">993</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;mailserver/mailserver:993::PROXY&quot;</span>
</code></pre></div> </code></pre></div>
<div class="admonition help">
<p class="admonition-title">HAProxy</p>
<p>With <a href="https://hub.docker.com/_/haproxy">HAProxy</a>, the configuration should look similar to the above. If you know what it actually looks like, add an example here. <img alt="😃" class="twemoji" src="https://cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f603.svg" title=":smiley:" /></p>
</div> </div>
<h4 id="configure-the-mailserver"><a class="toclink" href="#configure-the-mailserver">Configure the Mailserver</a></h4> </div>
<p>Then, configure both <a href="../override-defaults/postfix/">Postfix</a> and <a href="../override-defaults/dovecot/">Dovecot</a> to expect the PROXY protocol:</p> </div>
<details class="example"> </details>
<summary>HAProxy Example</summary> <details class="example" open="open">
<summary>Adjust DMS config for Dovecot + Postfix</summary>
<details class="warning">
<summary>Only ingress should connect to DMS with PROXY protocol</summary>
<p>While Dovecot will restrict connections via PROXY protocol to only clients trusted configured via <code>haproxy_trusted_networks</code>, Postfix does not have an equivalent setting. Public clients should always route through ingress to establish a PROXY protocol connection.</p>
<p>You are responsible for properly managing traffic inside your cluster and to <strong>ensure that only trustworthy entities</strong> can connect to the designated PROXY protocol ports.</p>
<p>With Kubernetes, this is usually the task of the CNI (<em>container network interface</em>).</p>
</details>
<div class="admonition tip">
<p class="admonition-title">Advised approach</p>
<p>The <em>"Separate PROXY protocol ports"</em> tab below introduces a little more complexity, but provides better compatibility for internal connections to DMS.</p>
</div>
<div class="tabbed-set tabbed-alternate" data-tabs="5:2"><input checked="checked" id="only-accept-connections-with-proxy-protocol" name="__tabbed_5" type="radio" /><input id="separate-proxy-protocol-ports-for-ingress" name="__tabbed_5" type="radio" /><div class="tabbed-labels"><label for="only-accept-connections-with-proxy-protocol">Only accept connections with PROXY protocol</label><label for="separate-proxy-protocol-ports-for-ingress">Separate PROXY protocol ports for ingress</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
<div class="admonition warning">
<p class="admonition-title">Connections to DMS within the internal cluster will be rejected</p>
<p>The services for these ports can only enable PROXY protocol support by mandating the protocol on all connections for these ports.</p>
<p>This can be problematic when you also need to support internal cluster traffic directly to DMS (<em>instead of routing indirectly through the ingress controller</em>).</p>
</div>
<p>Here is an example configuration for <a href="../override-defaults/postfix/">Postfix</a>, <a href="../override-defaults/dovecot/">Dovecot</a>, and the required adjustments for the <a href="#deployment"><code>Deployment</code> manifest</a>. The port names are adjusted here only to convey the additional context described earlier.</p>
<div class="highlight"><pre><span></span><code><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ConfigMap</span> <div class="highlight"><pre><span></span><code><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ConfigMap</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span> <span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span>
<span class="nt">metadata</span><span class="p">:</span> <span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver.config</span> <span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver-extra-config</span>
<span class="w"> </span><span class="nt">labels</span><span class="p">:</span> <span class="w"> </span><span class="nt">labels</span><span class="p">:</span>
<span class="w"> </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver</span> <span class="w"> </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver</span>
<span class="nt">data</span><span class="p">:</span> <span class="nt">data</span><span class="p">:</span>
@ -2789,8 +2751,7 @@
<span class="w"> </span><span class="no">submission/inet/smtpd_upstream_proxy_protocol=haproxy</span> <span class="w"> </span><span class="no">submission/inet/smtpd_upstream_proxy_protocol=haproxy</span>
<span class="w"> </span><span class="no">submissions/inet/smtpd_upstream_proxy_protocol=haproxy</span> <span class="w"> </span><span class="no">submissions/inet/smtpd_upstream_proxy_protocol=haproxy</span>
<span class="w"> </span><span class="nt">dovecot.cf</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span> <span class="w"> </span><span class="nt">dovecot.cf</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span>
<span class="w"> </span><span class="no"># Assuming your ingress controller is bound to 10.0.0.0/8</span> <span class="w"> </span><span class="no">haproxy_trusted_networks = &lt;YOUR POD CIDR&gt;</span>
<span class="w"> </span><span class="no">haproxy_trusted_networks = 10.0.0.0/8, 127.0.0.0/8</span>
<span class="w"> </span><span class="no">service imap-login {</span> <span class="w"> </span><span class="no">service imap-login {</span>
<span class="w"> </span><span class="no">inet_listener imap {</span> <span class="w"> </span><span class="no">inet_listener imap {</span>
<span class="w"> </span><span class="no">haproxy = yes</span> <span class="w"> </span><span class="no">haproxy = yes</span>
@ -2800,10 +2761,10 @@
<span class="w"> </span><span class="no">}</span> <span class="w"> </span><span class="no">}</span>
<span class="w"> </span><span class="no">}</span> <span class="w"> </span><span class="no">}</span>
<span class="c1"># ...</span> <span class="c1"># ...</span>
<span class="nn">---</span>
<span class="nn">---</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Deployment</span> <span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Deployment</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">extensions/v1beta1</span> <span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">apps/v1</span>
<span class="nt">metadata</span><span class="p">:</span> <span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver</span> <span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mailserver</span>
<span class="nt">spec</span><span class="p">:</span> <span class="nt">spec</span><span class="p">:</span>
@ -2811,6 +2772,24 @@
<span class="w"> </span><span class="nt">spec</span><span class="p">:</span> <span class="w"> </span><span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">containers</span><span class="p">:</span> <span class="w"> </span><span class="nt">containers</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">docker-mailserver</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">docker-mailserver</span>
<span class="w"> </span><span class="c1"># ...</span>
<span class="w"> </span><span class="nt">ports</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">smtp-proxy</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">25</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imap-proxy</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">143</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">subs-proxy</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">465</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">sub-proxy</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">587</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imaps-proxy</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">993</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="w"> </span><span class="c1"># ...</span>
<span class="w"> </span><span class="nt">volumeMounts</span><span class="p">:</span> <span class="w"> </span><span class="nt">volumeMounts</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">config</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">config</span>
<span class="w"> </span><span class="nt">subPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">postfix-main.cf</span> <span class="w"> </span><span class="nt">subPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">postfix-main.cf</span>
@ -2825,11 +2804,78 @@
<span class="w"> </span><span class="nt">mountPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/tmp/docker-mailserver/dovecot.cf</span> <span class="w"> </span><span class="nt">mountPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/tmp/docker-mailserver/dovecot.cf</span>
<span class="w"> </span><span class="nt">readOnly</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span> <span class="w"> </span><span class="nt">readOnly</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
</code></pre></div> </code></pre></div>
</details> </div>
<p>With this approach,</p> <div class="tabbed-block">
<div class="admonition info">
<p class="admonition-title">Info</p>
<p>Supporting internal cluster connections to DMS without using PROXY protocol requires both Postfix and Dovecot to be configured with alternative ports for each service port (<em>which only differ by enforcing PROXY protocol connections</em>).</p>
<ul> <ul>
<li>it is not possible to access DMS via cluster-DNS, as the PROXY protocol is required for incoming connections.</li> <li>The ingress controller will route public connections to the internal alternative ports for DMS (<code>*-proxy</code> variants).</li>
<li>Internal cluster connections will instead use the original ports configured for the DMS container directly (<em>which are private to the cluster network</em>).</li>
</ul> </ul>
</div>
<p>In this example we'll create a copy of the original service ports with PROXY protocol enabled, and increment the port number assigned by <code>10000</code>.</p>
<p>Create a <code>user-patches.sh</code> file to apply these config changes during container startup:</p>
<div class="highlight"><pre><span></span><code><span class="ch">#!/bin/bash</span>
<span class="c1"># Duplicate the config for the submission(s) service ports (587 / 465) with adjustments for the PROXY ports (10587 / 10465) and `syslog_name` setting:</span>
postconf<span class="w"> </span>-Mf<span class="w"> </span>submission/inet<span class="w"> </span><span class="p">|</span><span class="w"> </span>sed<span class="w"> </span>-e<span class="w"> </span>s/^submission/10587/<span class="w"> </span>-e<span class="w"> </span><span class="s1">&#39;s/submission/submission-proxyprotocol/&#39;</span><span class="w"> </span>&gt;&gt;<span class="w"> </span>/etc/postfix/master.cf
postconf<span class="w"> </span>-Mf<span class="w"> </span>submissions/inet<span class="w"> </span><span class="p">|</span><span class="w"> </span>sed<span class="w"> </span>-e<span class="w"> </span>s/^submissions/10465/<span class="w"> </span>-e<span class="w"> </span><span class="s1">&#39;s/submissions/submissions-proxyprotocol/&#39;</span><span class="w"> </span>&gt;&gt;<span class="w"> </span>/etc/postfix/master.cf
<span class="c1"># Enable PROXY Protocol support for these new service variants:</span>
postconf<span class="w"> </span>-P<span class="w"> </span><span class="m">10587</span>/inet/smtpd_upstream_proxy_protocol<span class="o">=</span>haproxy
postconf<span class="w"> </span>-P<span class="w"> </span><span class="m">10465</span>/inet/smtpd_upstream_proxy_protocol<span class="o">=</span>haproxy
<span class="c1"># Create a variant for port 25 too (NOTE: Port 10025 is already assigned in DMS to Amavis):</span>
postconf<span class="w"> </span>-Mf<span class="w"> </span>smtp/inet<span class="w"> </span><span class="p">|</span><span class="w"> </span>sed<span class="w"> </span>-e<span class="w"> </span>s/^smtp/12525/<span class="w"> </span>&gt;&gt;<span class="w"> </span>/etc/postfix/master.cf
<span class="c1"># Enable PROXY Protocol support (different setting as port 25 is handled via postscreen), optionally configure a `syslog_name` to distinguish in logs:</span>
postconf<span class="w"> </span>-P<span class="w"> </span><span class="m">12525</span>/inet/postscreen_upstream_proxy_protocol<span class="o">=</span>haproxy<span class="w"> </span><span class="m">12525</span>/inet/syslog_name<span class="o">=</span>smtp-proxyprotocol
</code></pre></div>
<p>For Dovecot, you can configure <a href="../override-defaults/dovecot/"><code>dovecot.cf</code></a> to look like this:</p>
<div class="highlight"><pre><span></span><code><span class="na">haproxy_trusted_networks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&lt;YOUR POD CIDR&gt;</span>
<span class="na">service imap-login {</span>
<span class="w"> </span><span class="na">inet_listener imap-proxied {</span>
<span class="w"> </span><span class="na">haproxy</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">yes</span>
<span class="w"> </span><span class="na">port</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">10143</span>
<span class="w"> </span><span class="na">}</span>
<span class="w"> </span><span class="na">inet_listener imaps-proxied {</span>
<span class="w"> </span><span class="na">haproxy</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">yes</span>
<span class="w"> </span><span class="na">port</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">10993</span>
<span class="w"> </span><span class="na">ssl</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">yes</span>
<span class="w"> </span><span class="na">}</span>
<span class="na">}</span>
</code></pre></div>
<p>Update the <a href="#deployment"><code>Deployment</code> manifest</a> <code>ports</code> section by appending these new ports:</p>
<div class="highlight"><pre><span></span><code><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">smtp-proxy</span>
<span class="w"> </span><span class="c1"># not 10025 in this example due to a possible clash with Amavis</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">12525</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imap-proxy</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">10143</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">subs-proxy</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">10465</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">sub-proxy</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">10587</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">imaps-proxy</span>
<span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">10993</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
</code></pre></div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If you use other Dovecot ports (110, 995, 4190), you may want to configure those similar to above. The <code>dovecot.cf</code> config for these ports is <a href="../../../examples/tutorials/mailserver-behind-proxy/">documented here</a> (<em>in the equivalent section of that page</em>).</p>
</div>
</div>
</div>
</div>
</details>
</div>
</div>
</div>
</div>

View File

@ -2323,7 +2323,7 @@ setup<span class="w"> </span>config<span class="w"> </span>dkim<span class="w">
</div> </div>
</details> </details>
<p>DKIM is currently supported by either OpenDKIM or Rspamd:</p> <p>DKIM is currently supported by either OpenDKIM or Rspamd:</p>
<div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">OpenDKIM</label><label for="__tabbed_1_2">Rspamd</label></div> <div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="opendkim" name="__tabbed_1" type="radio" /><input id="rspamd" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="opendkim">OpenDKIM</label><label for="rspamd">Rspamd</label></div>
<div class="tabbed-content"> <div class="tabbed-content">
<div class="tabbed-block"> <div class="tabbed-block">
<p>OpenDKIM is currently <a href="../../environment/#enable_opendkim">enabled by default</a>.</p> <p>OpenDKIM is currently <a href="../../environment/#enable_opendkim">enabled by default</a>.</p>
@ -2431,7 +2431,7 @@ setup<span class="w"> </span>config<span class="w"> </span>dkim<span class="w">
<div class="admonition example"> <div class="admonition example">
<p class="admonition-title">Configuring DNS - DKIM record</p> <p class="admonition-title">Configuring DNS - DKIM record</p>
<p>When you generated your key in the previous step, the DNS data was saved into a file <code>&lt;selector&gt;.txt</code> (default: <code>mail.txt</code>). Use this content to update your <a href="https://www.vultr.com/docs/introduction-to-vultr-dns/">DNS via Web Interface</a> or directly edit your <a href="https://en.wikipedia.org/wiki/Zone_file">DNS Zone file</a>:</p> <p>When you generated your key in the previous step, the DNS data was saved into a file <code>&lt;selector&gt;.txt</code> (default: <code>mail.txt</code>). Use this content to update your <a href="https://www.vultr.com/docs/introduction-to-vultr-dns/">DNS via Web Interface</a> or directly edit your <a href="https://en.wikipedia.org/wiki/Zone_file">DNS Zone file</a>:</p>
<div class="tabbed-set tabbed-alternate" data-tabs="2:2"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">Web Interface</label><label for="__tabbed_2_2">DNS Zone file</label></div> <div class="tabbed-set tabbed-alternate" data-tabs="2:2"><input checked="checked" id="web-interface" name="__tabbed_2" type="radio" /><input id="dns-zone-file" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="web-interface">Web Interface</label><label for="dns-zone-file">DNS Zone file</label></div>
<div class="tabbed-content"> <div class="tabbed-content">
<div class="tabbed-block"> <div class="tabbed-block">
<p>Create a new record:</p> <p>Create a new record:</p>

View File

@ -2270,7 +2270,7 @@
<h2 id="running-inside-a-rootless-container"><a class="toclink" href="#running-inside-a-rootless-container">Running Inside A Rootless Container</a></h2> <h2 id="running-inside-a-rootless-container"><a class="toclink" href="#running-inside-a-rootless-container">Running Inside A Rootless Container</a></h2>
<p><a href="https://github.com/rootless-containers/rootlesskit"><code>RootlessKit</code></a> is the <em>fakeroot</em> implementation for supporting <em>rootless mode</em> in Docker and Podman. By default, RootlessKit uses the <a href="https://github.com/rootless-containers/rootlesskit/blob/v0.14.5/docs/port.md#port-drivers"><code>builtin</code> port forwarding driver</a>, which does not propagate source IP addresses.</p> <p><a href="https://github.com/rootless-containers/rootlesskit"><code>RootlessKit</code></a> is the <em>fakeroot</em> implementation for supporting <em>rootless mode</em> in Docker and Podman. By default, RootlessKit uses the <a href="https://github.com/rootless-containers/rootlesskit/blob/v0.14.5/docs/port.md#port-drivers"><code>builtin</code> port forwarding driver</a>, which does not propagate source IP addresses.</p>
<p>It is necessary for F2B to have access to the real source IP addresses in order to correctly identify clients. This is achieved by changing the port forwarding driver to <a href="https://github.com/rootless-containers/slirp4netns"><code>slirp4netns</code></a>, which is slower than the builtin driver but does preserve the real source IPs.</p> <p>It is necessary for F2B to have access to the real source IP addresses in order to correctly identify clients. This is achieved by changing the port forwarding driver to <a href="https://github.com/rootless-containers/slirp4netns"><code>slirp4netns</code></a>, which is slower than the builtin driver but does preserve the real source IPs.</p>
<div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Docker</label><label for="__tabbed_1_2">Podman</label></div> <div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="docker" name="__tabbed_1" type="radio" /><input id="podman" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="docker">Docker</label><label for="podman">Podman</label></div>
<div class="tabbed-content"> <div class="tabbed-content">
<div class="tabbed-block"> <div class="tabbed-block">
<p>For <a href="https://docs.docker.com/engine/security/rootless">rootless mode</a> in Docker, create <code>~/.config/systemd/user/docker.service.d/override.conf</code> with the following content:</p> <p>For <a href="https://docs.docker.com/engine/security/rootless">rootless mode</a> in Docker, create <code>~/.config/systemd/user/docker.service.d/override.conf</code> with the following content:</p>

View File

@ -2271,6 +2271,7 @@
</ul> </ul>
<p>This reduces many of the benefits for why you might use a reverse proxy, but they can still be useful.</p> <p>This reduces many of the benefits for why you might use a reverse proxy, but they can still be useful.</p>
<p>Some deployments may require a service to route traffic (kubernetes) when deploying, in which case the below advice is important to understand well.</p> <p>Some deployments may require a service to route traffic (kubernetes) when deploying, in which case the below advice is important to understand well.</p>
<p>The guide here has also been adapted for <a href="../../../config/advanced/kubernetes/#using-the-proxy-protocol">our Kubernetes docs</a>.</p>
<h2 id="what-can-go-wrong"><a class="toclink" href="#what-can-go-wrong">What can go wrong?</a></h2> <h2 id="what-can-go-wrong"><a class="toclink" href="#what-can-go-wrong">What can go wrong?</a></h2>
<p>Without a reverse proxy involved, a service is typically aware of the client IP for a connection.</p> <p>Without a reverse proxy involved, a service is typically aware of the client IP for a connection.</p>
<p>However when a reverse proxy routes the connection this information can be lost, and the proxied service mistakenly treats the client IP as the reverse proxy handling the connection.</p> <p>However when a reverse proxy routes the connection this information can be lost, and the proxied service mistakenly treats the client IP as the reverse proxy handling the connection.</p>

View File

@ -2055,7 +2055,7 @@
to the respective IP-address on the server you want to use.</p> to the respective IP-address on the server you want to use.</p>
<div class="admonition example"> <div class="admonition example">
<p class="admonition-title">Example</p> <p class="admonition-title">Example</p>
<div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Contributed solution</label><label for="__tabbed_1_2">Alternative (unverified)</label></div> <div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="contributed-solution" name="__tabbed_1" type="radio" /><input id="alternative-unverified" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="contributed-solution">Contributed solution</label><label for="alternative-unverified">Alternative (unverified)</label></div>
<div class="tabbed-content"> <div class="tabbed-content">
<div class="tabbed-block"> <div class="tabbed-block">
<div class="highlight"><span class="filename">postfix-main.cf</span><pre><span></span><code>smtp_bind_address = 198.51.100.42 <div class="highlight"><span class="filename">postfix-main.cf</span><pre><span></span><code>smtp_bind_address = 198.51.100.42

File diff suppressed because one or more lines are too long

View File

@ -2,237 +2,237 @@
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/faq/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/faq/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/introduction/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/introduction/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/usage/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/usage/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/debugging/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/debugging/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/environment/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/environment/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/pop3/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/pop3/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/setup.sh/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/setup.sh/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/user-management/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/user-management/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/auth-ldap/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/auth-ldap/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/auth-oauth2/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/auth-oauth2/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/dovecot-master-accounts/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/dovecot-master-accounts/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/full-text-search/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/full-text-search/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/ipv6/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/ipv6/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/kubernetes/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/kubernetes/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/mail-fetchmail/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/mail-fetchmail/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/mail-getmail/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/mail-getmail/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/mail-sieve/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/mail-sieve/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/optional-config/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/optional-config/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/podman/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/podman/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/mail-forwarding/aws-ses/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/mail-forwarding/aws-ses/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/mail-forwarding/relay-hosts/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/mail-forwarding/relay-hosts/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/maintenance/update-and-cleanup/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/maintenance/update-and-cleanup/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/override-defaults/dovecot/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/override-defaults/dovecot/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/override-defaults/postfix/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/override-defaults/postfix/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/override-defaults/user-patches/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/advanced/override-defaults/user-patches/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/best-practices/autodiscover/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/best-practices/autodiscover/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/best-practices/dkim_dmarc_spf/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/best-practices/dkim_dmarc_spf/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/best-practices/mta-sts/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/best-practices/mta-sts/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/security/fail2ban/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/security/fail2ban/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/security/mail_crypt/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/security/mail_crypt/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/security/rspamd/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/security/rspamd/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/security/ssl/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/security/ssl/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/security/understanding-the-ports/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/config/security/understanding-the-ports/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/contributing/general/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/contributing/general/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/contributing/issues-and-pull-requests/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/contributing/issues-and-pull-requests/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/contributing/tests/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/contributing/tests/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/tutorials/basic-installation/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/tutorials/basic-installation/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/tutorials/blog-posts/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/tutorials/blog-posts/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/tutorials/crowdsec/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/tutorials/crowdsec/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/tutorials/docker-build/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/tutorials/docker-build/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/tutorials/mailserver-behind-proxy/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/tutorials/mailserver-behind-proxy/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/use-cases/auth-lua/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/use-cases/auth-lua/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/use-cases/bind-smtp-network-interface/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/use-cases/bind-smtp-network-interface/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/use-cases/forward-only-mailserver-with-ldap-authentication/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/use-cases/forward-only-mailserver-with-ldap-authentication/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/use-cases/imap-folders/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/use-cases/imap-folders/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
<url> <url>
<loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/use-cases/ios-mail-push-support/</loc> <loc>https://docker-mailserver.github.io/docker-mailserver/edge/examples/use-cases/ios-mail-push-support/</loc>
<lastmod>2024-03-06</lastmod> <lastmod>2024-03-12</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
</url> </url>
</urlset> </urlset>