slackhq/nebula · error

sshd.listen can not use port 22

Error message

sshd.listen can not use port 22

What it means

The SSH server refuses to bind to port 22 because the host's real sshd already owns it; configSSH rejects any sshd.listen whose port string equals "22". This forces operators to choose an alternate port so the built-in SSH server doesn't collide with the system one.

Source

Thrown at ssh.go:92

	})
}

// configSSH reads the ssh info out of the passed-in Config and
// updates the passed-in SSHServer. On success, it returns a function
// that callers may invoke to run the configured ssh server. On
// failure, it returns nil, error.
func configSSH(l *slog.Logger, ssh *sshd.SSHServer, c *config.C) (func(), error) {
	listen := c.GetString("sshd.listen", "")
	if listen == "" {
		return nil, fmt.Errorf("sshd.listen must be provided")
	}

	_, port, err := net.SplitHostPort(listen)
	if err != nil {
		return nil, fmt.Errorf("invalid sshd.listen address: %s", err)
	}
	if port == "22" {
		return nil, fmt.Errorf("sshd.listen can not use port 22")
	}

	hostKeyPathOrKey := c.GetString("sshd.host_key", "")
	if hostKeyPathOrKey == "" {
		return nil, fmt.Errorf("sshd.host_key must be provided")
	}

	var hostKeyBytes []byte
	if strings.Contains(hostKeyPathOrKey, "-----BEGIN") {
		hostKeyBytes = []byte(hostKeyPathOrKey)
	} else {
		hostKeyBytes, err = os.ReadFile(hostKeyPathOrKey)
		if err != nil {
			return nil, fmt.Errorf("error while loading sshd.host_key file: %s", err)
		}
	}

	err = ssh.SetHostKey(hostKeyBytes)

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Change sshd.listen to a non-22 port, e.g. "0.0.0.0:2222".
  2. Update deployment templates/Ansible vars that pin the port to 22.
  3. Port-forward from 22 externally if clients require the standard port.

Example fix

// before
sshd.listen = "0.0.0.0:22"
// after
sshd.listen = "0.0.0.0:2222"
Defensive patterns

Strategy: validation

Validate before calling

raw := cfg.GetString("sshd.listen", "")
if _, port, err := net.SplitHostPort(raw); err == nil && port == "22" {
    return errors.New("sshd.listen cannot use port 22; choose e.g. 2222")
}

Try / catch

run, err := configSSH(logger, srv, c)
if err != nil {
    if strings.Contains(err.Error(), "can not use port 22") {
        logger.Error("sshd.listen uses reserved port 22; pick an alternate port")
        os.Exit(78)
    }
    return err
}

Prevention

When it happens

Trigger: Setting sshd.listen = "0.0.0.0:22" or ":22"; the literal port comparison `port == "22"` in ssh.go's configSSH fires after a successful SplitHostPort.

Common situations: Operators keeping the default SSH port out of habit; templated configs that substitute the standard port; misreading the docs that this SSH server is supplementary and must use a non-22 port.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/d673d8d09e96c638. Report an issue: GitHub.