Knowledge base

domain-key

<virtual-mta>criticalset by the Hub

The same signing key, but declared inside a sending stream
in the configuration this is a linedomain-keyinside the block <virtual-mta>
The same name 3:<domain-key-list>Global<virtual-mta><virtual-mta-pool>— some of them are other settings, some are the same one
A key that applies only in this stream

The same line as at the node level — selector, domain, key — but declared inside <virtual-mta>. The selection mechanism is described on the general page; what matters here is something else: what declaring it in this particular place changes.

It changes two things. The key becomes available only to this stream’s messages — whatever leaves through other streams will not see it. And it is stronger than the general ones: if matching declarations exist both at the node level and here, the ones here win.

Hence the usual use: different senders sign with different keys, and they are separated by stream.

The main trap is mail not reaching the right stream. The manual warns separately: having declared a key inside a stream, you must make sure that messages from this sending domain actually get into it — usually with a selection rule on MAIL FROM. Otherwise the key exists, signing is on, yet messages leave through another stream that has no key and stay unsigned.
What the Hub does. It distributes keys across nodes and streams itself: each sending address has its own stream, and the key goes into it. The Hub writes the selection rule as well — mail gets into the stream the key was created for.
Recommended values

An asterisk inside a stream is safer than at the node level. Here it intercepts only this stream’s messages, not all mail. The manual’s example is exactly that.

Check the route before the value. A key in a stream makes sense only together with a rule that routes the right mail there.

The general declarations do not disappear. They remain a fallback for messages that the ones here did not fit.

The remark about the asterisk being safe inside a stream is ours. From the manual here are the example with this value, the priority of stream keys and the warning about the route.
Example configuration
# the key applies only to this stream's messages
<virtual-mta mta1>
    domain-key s1, *, /etc/pmta/key.pem</virtual-mta>

# and the rule that routes the right mail here
<pattern-list L>
    mail-from /[@\.]example\.com$/ virtual-mta=mta1
</pattern-list>
The second block matters no less than the first: without the selection rule, messages leave through another stream that has no key and stay unsigned.
yellow — — directive names, blue — blocks. They are highlighted the same way in the text of the card.
▲

Common mistakes and problems

what people get wrong and how it ends2 mistakes▶

Declaring a key in a stream without routing mail into it

§ 10.3.2

What it costsThe key exists, signing is on, messages leave through another stream. The node does not sign them — silently, with no log entry.
How to spot itSigning is on, messages have no header, and the stream is empty.
How to do it rightAdd a selection rule on MAIL FROM or move the declaration to the node level.

Duplicating the general key in every stream

our experience

What it costsRotation turns into edits in many places, and sooner or later one stream is left with the old key. And that stream has priority — so it is precisely the outdated declaration that wins.
How to spot itAfter rotation some messages are signed with the old selector.
How to do it rightKeep the general key at the node level; in streams declare only what really belongs to them alone.
Compatibility
PowerMTA 6.0
described in the manual of this version · platform: any
The vendor does not state the first version for every directive — there is no note here. The name also appears in the 5.0 edition of the manual.
Reference data
Syntax
domain-key <see-global>
Values
three comma-separated values — a selector, a domain or an asterisk, a file path or a reference to a secrets vault
Applying
reload, no restart needed
Queue
will not touch what is already queued
Where to write it
<virtual-mta>
How many times
may be repeated
Everything here comes from the manual, with the section.
Inheritance
The declaration applies inside its <virtual-mta> and overrides same-named node-level declarations. The general ones do not disappear: they remain a fallback for messages that the ones here did not fit. It is picked up by pmta reload.
How to check on the node
Which key a message was signed with shows in the signature header; which stream it left through — in the list of queues:
grep -i 'DKIM-Signature' /var/log/pmta/pmta.log | tail -5
pmta show queues | grep -i mta1
An empty second output with the key set means mail does not get into this stream — the selection rule did not fire. The Hub distributes keys across streams itself.
In the Hub
Managed at
DNS → Signing keys
Value
The Hub picks it itself — pace, warm-up stage, metrics
Cost of a mistake
reversible: harms only while it is set
Scenarios
Sending address rotation
Priority
critical