{"record":{"id":"48cc196ac75f8e11","repo":"Billionmail/BillionMail","slug":"failed-to-write-postfix-config-v","errorCode":null,"errorMessage":"failed to write postfix config: %v","messagePattern":"failed to write postfix config: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/mail_service/certificate.go","lineNumber":253,"sourceCode":"\t// Write certificate and key to files\n\tcertPath := public.AbsPath(filepath.Join(consts.SSL_PATH, \"postfix.crt\"))\n\tkeyPath := public.AbsPath(filepath.Join(consts.SSL_PATH, \"postfix.key\"))\n\n\tif err := os.WriteFile(certPath, []byte(csrPem), 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to write certificate file: %v\", err)\n\t}\n\n\tif err := os.WriteFile(keyPath, []byte(keyPem), 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to write key file: %v\", err)\n\t}\n\n\t// Update SSL certificate configuration\n\tconfig := string(content)\n\tconfig = c.updateConfigLine(config, \"smtpd_tls_key_file\", keyPath)\n\tconfig = c.updateConfigLine(config, \"smtpd_tls_cert_file\", certPath)\n\n\tif err := os.WriteFile(mainCf, []byte(config), 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to write postfix config: %v\", err)\n\t}\n\n\treturn nil\n}\n\n// SetPostfixVMailCert configures SSL certificate for Postfix virtual mail\nfunc (c *Certificate) SetPostfixVMailCert(domain, csrPem, keyPem string) error {\n\t// Validate certificate data\n\tif err := c.verifyCertificate(csrPem, keyPem); err != nil {\n\t\treturn err\n\t}\n\n\t// Update Postfix Master configuration\n\tif err := c.SetPostfixMasterSSL(); err != nil {\n\t\treturn err\n\t}\n\n\t// Update Postfix virtual mail configuration","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/mail_service/certificate.go#L235-L271","documentation":"After updating the smtpd_tls_key_file / smtpd_tls_cert_file lines, updatePostfixConfig fails to persist main.cf via os.WriteFile and wraps the OS error. The certificate files may already be written, leaving main.cf pointing at old cert paths until retried.","triggerScenarios":"SetSSL or SetPostfixSSL runs while the Postfix main.cf path is missing, read-only, permission-denied, or the disk is full — typically a container mount or ownership problem.","commonSituations":"Postfix conf volume mounted read-only; main.cf owned by root while service runs unprivileged; container filesystem in read-only mode; out-of-space host.","solutions":["Check that the resolved main.cf path exists and is writable by the service user (chown/chmod or fix the volume).","Confirm the Postfix configuration volume is not mounted read-only in Docker Compose.","Free disk space if ENOSPC is the wrapped error.","Read the embedded %v error to pinpoint the errno before changing anything.","Retry SetSSL; then reload/restart Postfix so main.cf changes take effect."],"exampleFix":"// before\nif err := os.WriteFile(mainCf, []byte(config), 0755); err != nil {\n    return fmt.Errorf(\"failed to write postfix config: %v\", err)\n}\n// after\nif err := os.WriteFile(mainCf, []byte(config), 0644); err != nil {\n    return fmt.Errorf(\"failed to write postfix config %s: %w\", mainCf, err)\n}","handlingStrategy":"validation","validationCode":"mainCf := public.AbsPath(filepath.Join(consts.POSTFIX_CONF_PATH, \"main.cf\"))\nif _, err := os.Stat(mainCf); err != nil {\n    return fmt.Errorf(\"main.cf missing: %v\", err)\n}\nif err := unix.Access(mainCf, unix.W_OK); err != nil {\n    return fmt.Errorf(\"main.cf not writable: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"err := svc.SetPostfixSSL(ctx, domain)\nif err != nil && strings.Contains(err.Error(), \"failed to write postfix config\") {\n    log.Printf(\"postfix main.cf unwritable — check volume mounts and ownership: %v\", err)\n}","preventionTips":["Mount Postfix config dir as writable volume in compose (no :ro).","Back up main.cf before SSL updates so a partial write can be rolled back.","Keep main.cf owned by the service user or grant group write.","Watch for host-level read-only remounts after filesystem errors."],"tags":["filesystem","postfix","configuration","file-write"],"backgroundTag":"file-write-permission-denied","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}