Help us shape the future of Go! Take the 2026 Go Developer Survey

config

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package config reads host definitions from OpenSSH client config files.

The parser follows OpenSSH semantics rather than a simplified approximation: parameters are resolved first-value-wins across matching Host blocks, file scope directives act as defaults for every host, Include is honoured the way ssh honours it — read where the line is, and only where the block around it matches the host being resolved — and only concrete (non-wildcard) aliases are surfaced as connectable hosts.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddHost

func AddHost(path string, h NewHost) error

AddHost appends h to the config file at path, creating the file and the directory above it when they are missing. Nothing already in the file is touched: what is added sits alongside it.

func DefaultHostsPath

func DefaultHostsPath() (string, error)

DefaultHostsPath is the file hosts added through ohmyssh are written to.

func DefaultSSHConfigPath

func DefaultSSHConfigPath() (string, error)

DefaultSSHConfigPath returns ~/.ssh/config.

func ExpandPath

func ExpandPath(path string) string

ExpandPath resolves a leading "~" and makes the path absolute. Relative paths are resolved against ~/.ssh, matching how OpenSSH treats IdentityFile and Include values.

func JoinHostPort

func JoinHostPort(host, port string) string

JoinHostPort builds the host:port form an address is dialled and looked up in known_hosts under. An empty port means 22, as it does everywhere else a host is described.

net.JoinHostPort is not used because it would bracket a literal that already carries brackets — ssh config allows both spellings of an IPv6 address, and both have to reach the same place.

func RemoveHost

func RemoveHost(path, alias string) error

RemoveHost deletes the blocks naming alias from the config file at path.

The file is edited by line rather than written back from what was parsed out of it, so everything the user put there by hand — comments, spacing, the order of the directives — is still there afterwards. A block takes its "# Tags:" comment with it: left behind, that comment would label whichever block follows, which is a host nobody tagged. A path that cannot be read, or that holds no block naming alias, is an error rather than a quiet success.

Types

type NewHost

type NewHost struct {
	Alias string
	Host  string
	User  string
	Port  string
	Tags  []string
}

NewHost is a host the user typed into the browser's add form: the fields of a Host block, before any of them has been written down.

Only the alias is required. A field left empty is left out of the block, which is how a Host block is read anyway — an omitted HostName means the alias is the address, an omitted User means the login of whoever is running this, an omitted Port means 22.

func (NewHost) Block

func (h NewHost) Block() string

Block renders the host the way it is written to a config file, in the format ssh's own files use down to the four-space indent, so that the file ohmyssh keeps can be read, edited and version controlled like any other.

func (NewHost) Validate

func (h NewHost) Validate() error

Validate reports whether these fields can be written down as a Host block and read back as the host the user meant.

The line-break check is the one that matters: a value carrying a break does not stay a value, it starts a directive of its own on the next line, and the file is read back as configuration. The rest is about what an alias may be, since a glob or a negation there would change how *other* blocks match rather than merely failing to match this one.

type SSHHost

type SSHHost struct {
	Name          string   // the alias used to select this host
	Hostname      string   // HostName, or Name when the block omits it
	User          string   // User, empty means "fall back to $USER"
	Port          string   // Port, empty means 22
	Identity      string   // IdentityFile
	IdentityAgent string   // IdentityAgent
	ProxyJump     string   // ProxyJump
	ProxyCommand  string   // ProxyCommand
	Tags          []string // from a "# Tags: a, b" comment above the Host line
	SourceFile    string   // config file this alias came from
	LineNumber    int      // 1-based line of the Host directive
	IsWildcard    bool     // block patterns contained glob characters
}

SSHHost is a single connectable host with every matching directive resolved.

func ParseSSHConfig

func ParseSSHConfig() ([]SSHHost, error)

ParseSSHConfig reads the default config path and returns resolved hosts.

func ParseSSHConfigFile

func ParseSSHConfigFile(path string) ([]SSHHost, error)

ParseSSHConfigFile parses path and returns one resolved entry per concrete alias. A missing file is not an error; it yields no hosts.

func ParseSSHConfigFiles

func ParseSSHConfigFiles(paths ...string) ([]SSHHost, error)

ParseSSHConfigFiles parses paths in order into one resolved list, as if each later file were Included at the end of the first.

Reading them together rather than separately is what makes the arrangement worth having: a file-scope directive in the first file — a default User, a default IdentityFile — applies to hosts declared in the second, exactly as it would to a host in an included file. And because the first obtained value wins across the lot, a host defined in both files resolves to the one in the first, so a file ohmyssh writes can never shadow the user's own config.

func ResolveName

func ResolveName(target string, paths ...string) (SSHHost, bool, error)

ResolveName resolves target the way ssh does when no literal alias names it, which is the case a wildcard block covers.

Only a block with something specific in its pattern counts. A bare `Host *` is not a definition: its directives are the defaults every host already receives, and letting it match would make every mistyped alias resolve to a host that does not exist — the mistake Find's suggestions exist to report. A pattern that names something — `*.corp.example.com` — defines a machine as squarely as an alias does, and refusing it sends the user hunting for a host that is right there in the file they are reading.

It reads the files itself because a caller that has resolved the hosts no longer holds the blocks, and the names it resolves are not among them: a wildcard block is not offered as a browsable host. The cost is one parse on the path where nothing matched, which is once per invocation.

func (SSHHost) Addr

func (h SSHHost) Addr() string

Addr returns the host:port dial target.

func (SSHHost) DisplayUser

func (h SSHHost) DisplayUser() string

DisplayUser returns the user that will be used for authentication.

func (SSHHost) String

func (h SSHHost) String() string

String renders a compact "user@host:port" description for listings.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL