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
- Change sshd.listen to a non-22 port, e.g. "0.0.0.0:2222".
- Update deployment templates/Ansible vars that pin the port to 22.
- 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
- Reserve a nonstandard default (2222) in templates and docs.
- Add the port-22 check to your CI config lint step.
- If external clients need port 22, front the server with a TCP forwarder instead.
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
- sshd.listen must be provided
- invalid sshd.listen address: %s
- sshd.host_key must be provided
- error while loading sshd.host_key file: %s
- error while adding sshd.host_key: %s
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/d673d8d09e96c638.
Report an issue: GitHub.