Billionmail/BillionMail · error

failed to restart postfix container: %v

Error message

failed to restart postfix container: %v

What it means

restartPostfix asks the Docker API client to restart the Postfix container (consts.SERVICES.Postfix) so new SSL settings take effect. Any Docker-level restart failure is wrapped as 'failed to restart postfix container: %v'. Thrown by SetSSL, SetSNI, SetPostfixSSL and SetPostfixVMailCert — i.e. the cert files and configs were updated but the service was not reloaded.

Source

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

// updateConfigLine updates a configuration line in config file
func (c *Certificate) updateConfigLine(config, key, value string) string {
	lines := strings.Split(config, "\n")
	for i, line := range lines {
		line = strings.TrimSpace(line)
		if strings.HasPrefix(line, key) && strings.Contains(line, "=") {
			lines[i] = key + " = " + value
			return strings.Join(lines, "\n")
		}
	}
	return config + "\n" + key + " = " + value
}

// restartPostfix restarts Postfix service
func (c *Certificate) restartPostfix() error {
	// Restart Postfix container
	if err := c.dockerApiClient().RestartContainerByName(context.Background(), consts.SERVICES.Postfix); err != nil {
		return fmt.Errorf("failed to restart postfix container: %v", err)
	}

	return nil
}

// restartDovecot restarts Dovecot service
func (c *Certificate) restartDovecot() error {
	// Restart Dovecot container
	if err := c.dockerApiClient().RestartContainerByName(context.Background(), consts.SERVICES.Dovecot); err != nil {
		return fmt.Errorf("failed to restart dovecot container: %v", err)
	}

	return nil
}

// GetSSLStatus checks SSL certificate status
func (c *Certificate) GetSSLStatus(domain string) (bool, error) {
	// Check Postfix certificate

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Verify the Postfix container exists and matches consts.SERVICES.Postfix (docker ps) and rename/recreate it if needed
  2. Ensure the Docker socket is mounted and accessible (docker.sock volume, root or docker group)
  3. Start the Postfix container if it is stopped (docker compose up -d postfix)
  4. Manually restart postfix (docker restart <postfix>) to apply the new certs, then retry the API call

Example fix

// before
if err := c.dockerApiClient().RestartContainerByName(context.Background(), consts.SERVICES.Postfix); err != nil {
    return fmt.Errorf("failed to restart postfix container: %v", err)
}
// after
if err := c.dockerApiClient().RestartContainerByName(context.Background(), consts.SERVICES.Postfix); err != nil {
    // config files are already updated; surface actionable guidance
    return fmt.Errorf("failed to restart postfix container %s (is it running? is docker.sock mounted?): %w", consts.SERVICES.Postfix, err)
}
Defensive patterns

Strategy: retry

Validate before calling

cli, err := c.dockerApiClient().ContainerList(ctx, types.ContainerListOptions{All: true})
if err != nil {
    return fmt.Errorf("docker unreachable: %w", err)
}
running := false
for _, ct := range cli {
    if strings.Contains(strings.Join(ct.Names, ","), consts.SERVICES.Postfix) {
        running = true
    }
}
if !running {
    return fmt.Errorf("postfix container %s not running", consts.SERVICES.Postfix)
}

Try / catch

if err := certSvc.SetSSL(ctx, domain); err != nil {
    if strings.Contains(err.Error(), "failed to restart postfix container") {
        // check docker.sock mount, container name, then retry or restart manually
    }
    return err
}

Prevention

When it happens

Trigger: Any of SetSSL/SetSNI/SetPostfixSSL/SetPostfixVMailCert called when the Postfix container is not running, has a different name than consts.SERVICES.Postfix, or the Docker socket/daemon is unreachable.

Common situations: Docker socket not mounted (/var/run/docker.sock missing or permission denied); Postfix runs on the host instead of a container; container renamed after a compose refactor; Docker daemon restarting or out of memory.

Related errors


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