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

  1. Check Rspamd container is up: docker ps and docker logs <rspamd>
  2. 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
  3. Ensure /var/lib/rspamd/dkim is a writable mounted volume
  4. 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

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


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/9a3d7c7b6a9ee1cc. Report an issue: GitHub.