Billionmail/BillionMail · error

failed to read postfix config: %v

Error message

failed to read postfix config: %v

What it means

updatePostfixConfig reads Postfix main.cf (consts.POSTFIX_MAIN_CONF) with os.ReadFile before rewriting the smtpd_tls_cert_file/key_file lines. This error wraps the read failure and is raised by SetSSL and SetPostfixSSL when main.cf is missing or unreadable.

Source

Thrown at core/internal/service/mail_service/certificate.go:232

		return fmt.Errorf("private key data is empty")
	}

	// Validate certificate
	cInfo := acme.GetCertInfo(csrPem)

	if cInfo.Endtime == 0 {
		return fmt.Errorf("certificate is invalid")
	}

	return nil
}

// updatePostfixConfig updates Postfix configuration with new certificate
func (c *Certificate) updatePostfixConfig(csrPem, keyPem string) error {
	mainCf := public.AbsPath(consts.POSTFIX_MAIN_CONF)
	content, err := os.ReadFile(mainCf)
	if err != nil {
		return fmt.Errorf("failed to read postfix config: %v", err)
	}

	// Write certificate and key to files
	certPath := public.AbsPath(filepath.Join(consts.SSL_PATH, "postfix.crt"))
	keyPath := public.AbsPath(filepath.Join(consts.SSL_PATH, "postfix.key"))

	if err := os.WriteFile(certPath, []byte(csrPem), 0755); err != nil {
		return fmt.Errorf("failed to write certificate file: %v", err)
	}

	if err := os.WriteFile(keyPath, []byte(keyPem), 0755); err != nil {
		return fmt.Errorf("failed to write key file: %v", err)
	}

	// Update SSL certificate configuration
	config := string(content)
	config = c.updateConfigLine(config, "smtpd_tls_key_file", keyPath)
	config = c.updateConfigLine(config, "smtpd_tls_cert_file", certPath)

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Verify the main.cf path (postconf -h config_directory) and correct consts.POSTFIX_MAIN_CONF or the deployment mount
  2. Install postfix / initialize the mail server before applying certificates
  3. Grant the process read access to main.cf
  4. Log the wrapped error to identify whether it is ENOENT or EACCES
Defensive patterns

Strategy: validation

Validate before calling

mainCf := public.AbsPath(consts.POSTFIX_MAIN_CONF)
if _, err := os.Stat(mainCf); err != nil {
    return fmt.Errorf("postfix main.cf missing at %s — install/initialize postfix first: %w", mainCf, err)
}

Try / catch

if err := certService.SetSSL(csrPem, keyPem); err != nil {
    if strings.Contains(err.Error(), "failed to read postfix config") {
        log.Errorf("main.cf unreadable: %s", err)
        return ErrPostfixNotInstalled
    }
    return err
}

Prevention

When it happens

Trigger: Calling SetSSL or SetPostfixSSL on a machine where AbsPath(consts.POSTFIX_MAIN_CONF) does not exist or cannot be read by the process user.

Common situations: Postfix not installed (fresh container/mail-server not initialized); custom postfix chroot/config directory; permission mismatch between the app user and /etc/postfix/main.cf.

Understand the failure class

Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.

Related errors


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