Billionmail/BillionMail · error
Failed to generate DKIM key pair: %v
Error message
Failed to generate DKIM key pair: %v
What it means
When DKIM keys don't exist on disk, getDKIMRecordWithKeySize execs `rspamadm dkim_keygen` in the Rspamd container to generate a key pair of the requested size for the domain. This error wraps the Docker exec failure. Note the mutex is held (defer Unlock), so callers fail cleanly but generation must be retried.
Source
Thrown at core/internal/service/domains/domains.go:556
var dk *docker.DockerAPI
dk, err = docker.NewDockerAPI()
if err != nil {
err = fmt.Errorf("Failed to connect to Docker API: %v", err)
return
}
defer dk.Close()
// Generate new keys if they don't exist
if !public.FileExists(dkimPriPath) || !public.FileExists(dkimPubPath) {
mutex.Lock()
defer mutex.Unlock()
var res *v2.ExecResult
res, err = dk.ExecCommandByName(context.Background(), consts.SERVICES.Rspamd, []string{"rspamadm", "dkim_keygen", "-s", selector, "-b", fmt.Sprintf("%d", keySize), "-d", domain, "-k", fmt.Sprintf("/var/lib/rspamd/dkim/%s/%s.private", domain, selector)}, "root")
if err != nil {
err = fmt.Errorf("Failed to generate DKIM key pair: %v", err)
return
}
if res != nil {
_, err = public.WriteFile(dkimPubPath, res.Output)
if err != nil {
err = fmt.Errorf("Failed to write DKIM public key: %v", err)
return
}
}
// update dkim private key file permission to 0644
err = os.Chmod(dkimPriPath, 0644)
if err != nil {
err = fmt.Errorf("Failed to change DKIM private key permissions: %v", err)
return
}
View on GitHub (pinned to fc36c76c05)
Solutions
- Check Rspamd container is up: docker ps and docker logs <rspamd>
- Exec manually to see the real error: docker exec <rspamd> rspamadm dkim_keygen -s <selector> -b 2048 -d <domain> -k /var/lib/rspamd/dkim/<domain>/<selector>.private
- Ensure /var/lib/rspamd/dkim is a writable mounted volume
- Retry GetDKIMRecord after the container is healthy — key generation is idempotent when keys are missing
Example fix
// before
res, err = dk.ExecCommandByName(context.Background(), consts.SERVICES.Rspamd, []string{"rspamadm","dkim_keygen","-s",selector,"-b",fmt.Sprintf("%d",keySize),...}, "root")
if err != nil { err = fmt.Errorf("Failed to generate DKIM key pair: %v", err); return }
// after
res, err = dk.ExecCommandByName(context.Background(), consts.SERVICES.Rspamd, keygenArgs, "root")
if err != nil { err = fmt.Errorf("Failed to generate DKIM key pair (is %s running and rspamadm available?): %v", consts.SERVICES.Rspamd, err); return }
if res != nil && res.ExitCode != 0 { err = fmt.Errorf("rspamadm dkim_keygen exited %d: %s", res.ExitCode, res.Output); return } Defensive patterns
Strategy: retry
Validate before calling
running, err := dk.IsContainerRunning(ctx, consts.SERVICES.Rspamd)
if err != nil || !running { return errors.New("rspamd container must be running for DKIM keygen") }
_, err = dk.ExecCommandByName(ctx, consts.SERVICES.Rspamd, []string{"which", "rspamadm"}, "root")
if err != nil { return errors.New("rspamadm not available in rspamd image") } Try / catch
err := retry.Do(3, 3*time.Second, func() error {
res, err := dk.ExecCommandByName(ctx, consts.SERVICES.Rspamd, keygenArgs, "root")
if err != nil { return err }
if res == nil || res.Output == "" { return errors.New("empty keygen output") }
return nil
})
if err != nil { return fmt.Errorf("Failed to generate DKIM key pair: %v", err) } Prevention
- Keep rspamd container healthy and supervised (restart: always)
- Validate keySize is 1024 or 2048 before exec
- Ensure /var/lib/rspamd/dkim is a writable persistent volume
- Unlock the mutex path quickly so failed keygen doesn't stall other domains
When it happens
Trigger: GetDKIMRecord / GetDKIMShortRecord / RepairDKIMSigningConfig for a domain with no existing key files, when ExecCommandByName(ctx, Rspamd, [rspamadm dkim_keygen ...]) fails — Rspamd container not running, rspamadm binary missing, bad keySize argument, or exec exits non-zero (e.g. unwritable /var/lib/rspamd/dkim).
Common situations: Rspamd container stopped or OOM-killed; DKIM directory volume not mounted so keygen cannot write; invalid keySize passed (not 1024/2048); container image updated without rspamadm on PATH.
Related errors
- rspamdadm not found
- failed to update BILLIONMAIL_HOSTNAME in postfix container:
- Failed to connect to Docker API: %v
- Failed to write DKIM public key: %v
- Failed to read DKIM sign config: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/9a3d7c7b6a9ee1cc.
Report an issue: GitHub.