{"record":{"id":"84fcf7aebe866e8e","repo":"Billionmail/BillionMail","slug":"failed-to-change-dkim-private-key-permissions-v","errorCode":null,"errorMessage":"Failed to change DKIM private key permissions: %v","messagePattern":"Failed to change DKIM private key permissions: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/domains/domains.go","lineNumber":571,"sourceCode":"\t\tvar res *v2.ExecResult\n\t\tres, 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\")\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"Failed to generate DKIM key pair: %v\", err)\n\t\t\treturn\n\t\t}\n\n\t\tif res != nil {\n\t\t\t_, err = public.WriteFile(dkimPubPath, res.Output)\n\t\t\tif err != nil {\n\t\t\t\terr = fmt.Errorf(\"Failed to write DKIM public key: %v\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// update dkim private key file permission to 0644\n\t\terr = os.Chmod(dkimPriPath, 0644)\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"Failed to change DKIM private key permissions: %v\", err)\n\t\t\treturn\n\t\t}\n\n\t\t// Skip DKIM signing config for relay-mapped domains — relay provider signs\n\t\trelayDomains, relayErr := GetRelayDomains(context.Background())\n\t\tif relayErr != nil {\n\t\t\tg.Log().Warning(context.Background(), \"Failed to check relay domains for DKIM signing:\", relayErr)\n\t\t\trelayDomains = make(map[string]bool)\n\t\t}\n\n\t\tif !relayDomains[domain] {\n\t\t\t// build DKIM Sign config\n\t\t\tsignConf := fmt.Sprintf(`\n#%s_DKIM_BEGIN\n%s {\n   selectors [\n    {\n      path: \"/var/lib/rspamd/dkim/%s/default.private\";","sourceCodeStart":553,"sourceCodeEnd":589,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/domains/domains.go#L553-L589","documentation":"After generating keys, getDKIMRecordWithKeySize runs os.Chmod(dkimPriPath, 0644) so Rspamd can read the private key. This error wraps a chmod failure. Without readable permissions, DKIM signing will fail later even though the keys exist.","triggerScenarios":"getDKIMRecordWithKeySize when os.Chmod on the freshly generated private key fails — file owned by another uid (rspamd container user vs host process), read-only mount, or the private path doesn't exist because generation silently failed earlier.","commonSituations":"Host process runs as non-root while key files are root-owned; DKIM volume mounted with restrictive options; AppArmor/SELinux denials; race where keygen wrote to a container-internal path not mapped to dkimPriPath.","solutions":["Check the wrapped error for EPERM/EACCES and run the process with rights over the dkim directory, or chown the files to the service user","Confirm dkimPriPath exists (a prior generation failure would surface here) and points at the rspamd volume mount","Verify the rspamd container user can read 0644 files on that volume","Retry GetDKIMRecord after fixing mount/permission issues"],"exampleFix":"// before\nerr = os.Chmod(dkimPriPath, 0644)\nif err != nil { err = fmt.Errorf(\"Failed to change DKIM private key permissions: %v\", err); return }\n// after\nif _, statErr := os.Stat(dkimPriPath); statErr != nil {\n    err = fmt.Errorf(\"DKIM private key missing before chmod: %v\", statErr)\n    return\n}\nif err = os.Chmod(dkimPriPath, 0644); err != nil {\n    err = fmt.Errorf(\"Failed to chmod DKIM private key %s (check volume ownership): %v\", dkimPriPath, err)\n    return\n}","handlingStrategy":"validation","validationCode":"info, err := os.Stat(dkimPriPath)\nif err != nil { return fmt.Errorf(\"private key missing: %v\", err) }\nif info.Mode().Perm() == 0644 { return nil } // already correct","typeGuard":null,"tryCatchPattern":"if err := os.Chmod(dkimPriPath, 0644); err != nil {\n    if errors.Is(err, os.ErrPermission) {\n        logger.Warnf(ctx, \"cannot chmod %s (not owner); signing may fail\", dkimPriPath)\n    }\n    return fmt.Errorf(\"Failed to change DKIM private key permissions: %v\", err)\n}","preventionTips":["Run the management process with the same uid/gid that owns the DKIM volume","Set umask/creation mode correctly at key write time so chmod is a no-op safety net","Audit volume mount options (no read-only, no noexec interference)","Verify rspamd can read the key after generation with a test exec (cat the .private file)"],"tags":["filesystem","permissions","dkim","chmod"],"backgroundTag":"file-permission-denied","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}