Stalwart: Difference between revisions

Onny (talk | contribs)
Add mail alias configuration
Onny (talk | contribs)
Sending from subaddresses: Add note on planned feature
 
(5 intermediate revisions by the same user not shown)
Line 248: Line 248:
== Tips and tricks ==
== Tips and tricks ==


=== Auto update TLSA records ===
Stalwart [https://github.com/stalwartlabs/stalwart/issues/1664 does not yet] automatically update the TLSA record if your ACME certificate changes.
Following script is a possible workaounrd. It extracts the ACME cert every five minute, calculates the TLSA hash and compares it with the upstream record. If it doesn't match, it uses [https://github.com/Stenstromen/gotlsaflare gotlsaflare] to update the TLSA record on Cloudflare.
<syntaxhighlight lang="nixos">
systemd.services.tlsa-cloudflare-update = {
  description = "Check and update TLSA/DANE record for mx1 from Stalwart ACME Cert";
 
  after = [
    "network-online.target"
    "stalwart-mail.service"
  ];
  wants = [
    "network-online.target"
    "stalwart-mail.service"
  ];
 
  serviceConfig = {
    Type = "oneshot";
    User = "stalwart-mail";
    Group = "stalwart-mail";
    EnvironmentFile = config.age.secrets.gotlsaflare-cloudflare-token.path;
    RuntimeDirectory = "stalwart-tlsa";
  };
  environment = {
    DOMAIN = "example.org";
    SUBDOMAIN = "mail";
    PORT = "25";
    ACME_PROVIDER_ID = "cloudflare";
  };
  path = with pkgs; [
    bash
    coreutils
    openssl
    dnsutils
    gotlsaflare
    rocksdb.tools
    gawk
  ];
  script = ''
    set -eu
    TLSA_RECORD="_$PORT._tcp.$SUBDOMAIN.$DOMAIN"
    DB_PATH="/var/lib/stalwart-mail/db"
    TEMP_RAW="/run/stalwart-tlsa/cert.bundle"
    TEMP_CRT="/run/stalwart-tlsa/cert.crt"
    echo "Starting TLSA update process for $DOMAIN"
    ldb --db="$DB_PATH" --column_family=s get "acme.$ACME_PROVIDER_ID.cert" | base64 -d > "$TEMP_RAW"
    if [ ! -s "$TEMP_RAW" ]; then
      echo "ERROR: ACME certificate extraction failed"
      exit 1
    fi
    openssl x509 -in "$TEMP_RAW" -out "$TEMP_CRT"
    LOCAL_HASH=$(openssl x509 -in "$TEMP_CRT" -pubkey -noout | openssl pkey -pubin -outform DER | openssl sha256 | awk '{print tolower($2)}')
    echo "Local hash: $LOCAL_HASH"
    UPSTREAM_HASH=$(dig +nosplit +short TLSA "$TLSA_RECORD" | awk '{print tolower($4)}' | head -n1)
    echo "Upstream hash: $UPSTREAM_HASH"
    if [ "$LOCAL_HASH" = "$UPSTREAM_HASH" ]; then
      echo "Hashes match. DNS is up to date."
      exit 0
    fi
    echo "Hashes differ! Updating Cloudflare..."
    gotlsaflare update \
      --url "$DOMAIN" \
      --subdomain "$SUBDOMAIN" \
      --tcp"$PORT" \
      --cert "$TEMP_CRT"
    echo "TLSA update completed successfully."
  '';
};
systemd.timers.tlsa-cloudflare-update = {
  description = "Run TLSA check and update every 5 minutes";
  wantedBy = [ "timers.target" ];
  timerConfig = {
    OnBootSec = "2m";
    OnUnitActiveSec = "5m";
    Unit = "tlsa-cloudflare-update.service";
  };
};
</syntaxhighlight>
Adapt the variables <code>DOMAIN</code>, <code>SUBDOMAIN</code>, and <code>PORT</code> according to your needs. The variable <code>ACME_PROVIDER_ID</code> corresponds to the ACME profile name you've setup in the Stalwart webadmin interface. <code>EnvironmentFile</code> points to a file containing the secret Cloudflare api token in the format: TOKEN=12345678[...].
=== Sending from subaddresses ===
Receiving mails to subaddresses like <code>john+secondary@example.org</code> is enabled by default. Sending from subaddresses will fail with "You are not allowed to send from this address" as long as they are not an configured alias address. You can disable this check but it will allow any authenticated user to send from any other address.
{{file|/etc/nixos/configuration.nix|nix|3=services.stalwart-mail = {
  settings = {
    [...]
    session.auth.must-match-sender = false;
  };
};}}
A configuration option to customize the pattern of authorized sender addresses is a [https://github.com/stalwartlabs/stalwart/issues/394#issuecomment-3705990056 planned feature].
=== Test mail server ===
=== Test mail server ===
You can use several online tools to test your mail server configuration:
You can use several online tools to test your mail server configuration: