Documentation
¶
Overview ¶
Package config loads, defaults, validates, and resolves MachineProxy configuration. It receives TOML, JSON or YAML files plus CLI overrides from cmd/machineproxy, and feeds runtime wiring for backends, namespace setup, FUSE mounts, environment filtering, and component discovery.
Index ¶
- Constants
- Variables
- func ExpandLocalHome(p string) (string, error)
- func ExpandRemoteHome(p, remoteHome string) (string, error)
- func LocalCacheDir() (string, error)
- func LookupGroupGID(name string) (uint32, error)
- func LookupUID(name string) (uint32, error)
- func MatchLocalCommand(entry, pathname string) bool
- func ResolveAgentBinaryPath(configPath, goos, goarch string) (string, error)
- func ResolveInterposerPath(configPath string) (string, error)
- func ResolveShimPath(configPath string) (string, error)
- func ResolveTracerPath(configPath string) (string, error)
- type Config
- type Format
- type IDLookup
- type IDMapEntry
- type LocalCommandRule
- type Mount
Constants ¶
const ( // UIDGIDModeTransparent forwards the remote UID/GID through unchanged. UIDGIDModeTransparent = "transparent" // UIDGIDModeOverride rewrites reads to the local user's UID/GID and // silently drops chown attempts that would otherwise propagate the // local user's view of ownership onto the remote. UIDGIDModeOverride = "override" )
Recognized values for Container.UIDMode and Container.GIDMode.
Variables ¶
var ( // DefaultCacheDir overrides the local-side cache parent directory // used to derive the PATH-stub bind target (and any future cache // locations). A leading "~" is expanded against the local user's // home directory at use time. When empty (the default), local // callers resolve $XDG_CACHE_HOME/machineproxy, falling back to // ~/.cache/machineproxy when XDG_CACHE_HOME is unset or relative. DefaultCacheDir = "" // DefaultAgentRemotePath is the upload destination for mproxy-agent // on the remote host. A leading "~" is expanded against the remote // user's home directory at SFTP-use time. This stays independent // of DefaultCacheDir because remote-side env vars aren't visible at // config-load time. DefaultAgentRemotePath = "~/.cache/machineproxy/mproxy-agent" // DefaultPathStubFallbackDir is the absolute path used in place of // the resolved local cache dir when home-directory lookup fails. DefaultPathStubFallbackDir = "/tmp/machineproxy/pathstub" )
Packager-overridable path defaults. These are var (not const) so a downstream packager can repoint them at build time via, e.g.:
go build -ldflags "-X github.com/jamesits/machineproxy/pkg/config.LibDir=/opt/machineproxy/lib"
LibDir's default is OS-specific and lives in paths_<goos>.go.
var ( Version = "0.0.0" Commit = "" Date = "" )
Build-time metadata, populated via ldflags.
var LibDir = "/usr/lib/machineproxy"
LibDir is the install location for machineproxy support binaries (mproxy-shim, mproxy-tracer, and the per-OS/arch agent layout under <LibDir>/agent/<goos>/<goarch>/). Override at link time via -ldflags "-X github.com/jamesits/machineproxy/pkg/config.LibDir=..." for downstream packagers.
Functions ¶
func ExpandLocalHome ¶ added in v1.1.0
ExpandLocalHome resolves a leading "~" or "~/" against the local user's home directory. Other paths are returned unchanged. Returns an error only if "~" is used but the home dir cannot be looked up.
func ExpandRemoteHome ¶ added in v1.1.0
ExpandRemoteHome resolves a leading "~" or "~/" against remoteHome (typically the SFTP server's default working directory). Other paths are returned unchanged. SFTP servers do not expand "~" themselves and session.Start single-quotes its argument, so this rewrite must happen client-side before any remote use.
func LocalCacheDir ¶ added in v1.3.2
LocalCacheDir resolves the local-side cache parent directory:
- DefaultCacheDir (with "~" expanded) when non-empty
- $XDG_CACHE_HOME/machineproxy when XDG_CACHE_HOME is an absolute path
- ~/.cache/machineproxy otherwise
Returns an error only when "~" expansion is required and the local home directory cannot be determined.
func LookupGroupGID ¶ added in v1.3.0
LookupGroupGID resolves a local group name to its GID.
func MatchLocalCommand ¶
MatchLocalCommand is a convenience that compiles entry and matches in one step. Returns false for malformed entries.
func ResolveAgentBinaryPath ¶
ResolveAgentBinaryPath finds the mproxy-agent binary. It checks the MPROXY_AGENT_BIN env var first, then the config value, adjacent binary, and well-known install paths. The goos and goarch parameters select the correct platform-specific binary for the remote host.
func ResolveInterposerPath ¶ added in v1.3.0
ResolveInterposerPath finds the libmproxy_interposer.dylib bundle for the local darwin host. It looks adjacent to the running machineproxy binary first (development layout), then under <LibDir>/agent/darwin/ <goarch>/ (install layout, mirroring ResolveAgentBinaryPath). On non-darwin hosts the dylib is not used; callers should branch on runtime.GOOS before invoking this.
func ResolveShimPath ¶
ResolveShimPath finds the mproxy-shim binary using the config value, then falling back to adjacent binary and well-known install paths.
func ResolveTracerPath ¶
ResolveTracerPath finds the mproxy-tracer binary using the config value, then falling back to adjacent binary and well-known install paths.
Types ¶
type Config ¶
type Config struct {
LogLevel string `yaml:"log_level" toml:"log_level" json:"log_level"` // trace, debug, info, warn, error
LogFile string `yaml:"log_file" toml:"log_file" json:"log_file"` // empty = stderr
Remote struct {
// Type selects the backend implementation: "ssh" (default) or
// "docker". The CLI --backend flag overrides this when set.
Type string `yaml:"type" toml:"type" json:"type"`
// SSH is resolved via the user's ssh_config (see ssh_config(5)).
// Host accepts either a literal hostname/IP or a Host alias defined
// in ~/.ssh/config; User and Port, when set, override the resolved
// values from ssh_config.
SSH struct {
Host string `yaml:"host" toml:"host" json:"host"`
User string `yaml:"user" toml:"user" json:"user"`
Port int `yaml:"port" toml:"port" json:"port"`
} `yaml:"ssh" toml:"ssh" json:"ssh"`
// Docker selects a running container by name or ID. Host (when
// set) overrides the DOCKER_HOST env var for this invocation.
Docker struct {
Container string `yaml:"container" toml:"container" json:"container"`
Host string `yaml:"host" toml:"host" json:"host"`
} `yaml:"docker" toml:"docker" json:"docker"`
// Compose selects a running container by Docker Compose project and
// service name. Project "." resolves from the working directory.
// Sequence (1-based) picks a specific replica of a scaled service;
// 0 means auto (errors if more than one container matches).
// Host, when set, overrides the DOCKER_HOST env var.
Compose struct {
Project string `yaml:"project" toml:"project" json:"project"`
Service string `yaml:"service" toml:"service" json:"service"`
Sequence int `yaml:"sequence" toml:"sequence" json:"sequence"`
Host string `yaml:"host" toml:"host" json:"host"`
} `yaml:"compose" toml:"compose" json:"compose"`
// OS selects the remote-side agent binary's GOOS. When empty,
// the runtime first asks the backend to detect it and only
// falls back to the local runtime.GOOS if detection fails.
OS string `yaml:"os" toml:"os" json:"os"`
// Arch selects the remote-side agent binary's GOARCH. Empty
// triggers the same detection/fallback chain as OS.
Arch string `yaml:"arch" toml:"arch" json:"arch"`
} `yaml:"remote" toml:"remote" json:"remote"`
Container struct {
LocalCommands []string `yaml:"local_commands" toml:"local_commands" json:"local_commands"`
Mounts []string `yaml:"mounts" toml:"mounts" json:"mounts"` // docker-compose style: [local:]remote
WorkingDir string `yaml:"working_dir" toml:"working_dir" json:"working_dir"` // override container working directory; defaults to first mount's local path
EnvRemove []string `yaml:"env_remove" toml:"env_remove" json:"env_remove"` // glob/regex patterns for env vars to strip from the container process
// PathProxy controls the FUSE-backed PATH-stub directory that
// surfaces remote-side executables inside the container.
// "prepend" — stubs win over locally-installed binaries (default)
// "append" — local binaries win; stubs only fill gaps
// "disabled" — skip enumeration entirely
PathProxy string `yaml:"path_proxy" toml:"path_proxy" json:"path_proxy"`
// PathStubDir is the in-container directory where the stub FUSE
// is bind-mounted. Defaults to $HOME/.cache/machineproxy/pathstub
// so bwrap (which lacks privilege to mkdir parents under /var)
// can create the bind target. A leading "~" is expanded against
// the local user's home; the resulting path must be absolute.
PathStubDir string `yaml:"path_stub_dir" toml:"path_stub_dir" json:"path_stub_dir"`
// ForceResolveInitialCommandLocally controls whether the
// resolved entrypoint command, its shebang interpreter, and
// any env-target are auto-appended to LocalCommands. The
// initial exec is always resolved against the local PATH
// (the path-stub directory is skipped) because the path-stub
// serves remote binaries that the local kernel may not load;
// whitelisting the resolved chain prevents the exec
// interception layer from later routing those same paths to
// the remote when they are re-execed (for instance by the
// kernel's binfmt_script interpreter). Defaults to true; set
// false to opt out.
ForceResolveInitialCommandLocally *bool `` /* 134-byte string literal not displayed */
// UIDMode controls how the workspace FUSE mount reports file
// owner UIDs and how chown(uid, _) calls are forwarded:
// "transparent" — pass the remote UID through unchanged
// "override" — always report the local user's UID for
// reads, and silently no-op uid changes on
// write. This is the default because the
// remote often runs as a different user
// (e.g. root) than the local process, and
// transparent ownership reporting trips
// default_permissions in the kernel.
UIDMode string `yaml:"uid_mode" toml:"uid_mode" json:"uid_mode"`
// GIDMode is the GID counterpart to UIDMode; same semantics.
GIDMode string `yaml:"gid_mode" toml:"gid_mode" json:"gid_mode"`
// UIDMap is a list of /etc/subuid-like entries that translate
// remote-reported UIDs to the local view (and back, on chown).
// Each entry has one of these shapes:
// "uid:mapped_uid"
// "username:mapped_uid" (username resolved via getpwnam)
// "uid:mapped_uid:count"
// "username:mapped_uid:count"
// A UID covered by any entry takes the mapped value regardless
// of UIDMode; UIDs not covered fall back to UIDMode behaviour.
// See CompileIDMapEntry for the full grammar.
UIDMap []string `yaml:"uid_map" toml:"uid_map" json:"uid_map"`
// GIDMap is the GID counterpart to UIDMap. Names in the first
// field are resolved via getgrnam instead of getpwnam.
GIDMap []string `yaml:"gid_map" toml:"gid_map" json:"gid_map"`
} `yaml:"container" toml:"container" json:"container"`
Agent struct {
EnvKeep []string `yaml:"env_keep" toml:"env_keep" json:"env_keep"` // glob/regex patterns for inherited env vars to forward to remote
EnvRemove []string `yaml:"env_remove" toml:"env_remove" json:"env_remove"` // glob/regex patterns for env vars to always strip from remote
} `yaml:"agent" toml:"agent" json:"agent"`
Components struct {
ShimPath string `yaml:"shim_path" toml:"shim_path" json:"shim_path"`
TracerPath string `yaml:"tracer_path" toml:"tracer_path" json:"tracer_path"`
InterposerPath string `yaml:"interposer_path" toml:"interposer_path" json:"interposer_path"`
AgentLocalPath string `yaml:"agent_local_path" toml:"agent_local_path" json:"agent_local_path"`
AgentRemotePath string `yaml:"agent_remote_path" toml:"agent_remote_path" json:"agent_remote_path"`
} `yaml:"components" toml:"components" json:"components"`
Recording struct {
Path string `yaml:"path" toml:"path" json:"path"` // empty disables recording
} `yaml:"recording" toml:"recording" json:"recording"`
}
Config describes machineproxy runtime behavior.
func Load ¶
Load reads from r, auto-detecting YAML vs TOML by sniffing the bytes, and applies defaults plus validation. Use LoadFile when you have a path so the extension hint applies first.
func LoadFile ¶
LoadFile reads and decodes the config at path, applies defaults, and validates. Format is detected by file extension first (.yaml/.yml/.json → YAML, .toml → TOML); if the extension is unrecognized, the contents are sniffed (see detectFormat).
func LoadFileRaw ¶ added in v1.1.0
LoadFileRaw reads and decodes the config at path without applying defaults or validating. Callers that need to mutate the result before use (for instance, applying CLI overrides) should call Finalize after their mutations. Format detection matches LoadFile.
type IDLookup ¶ added in v1.3.0
IDLookup resolves a name to a numeric ID. LookupUID and LookupGroupGID are the production implementations used by Validate; tests can pass an in-memory stub.
type IDMapEntry ¶ added in v1.3.0
IDMapEntry is a parsed uid_map/gid_map line. A single entry maps a contiguous range of [Count] remote IDs starting at RemoteID to local IDs starting at LocalID.
func CompileIDMapEntry ¶ added in v1.3.0
func CompileIDMapEntry(s string, lookup IDLookup) (IDMapEntry, error)
CompileIDMapEntry parses a single uid_map / gid_map entry in /etc/subuid-like format. Supported forms:
uid:mapped_uid username:mapped_uid uid:mapped_uid:count username:mapped_uid:count
The first column identifies the remote-side ID (either as a numeric ID or as a name resolved via lookup); the second column is the local ID to surface for that range; count (default 1) extends the range. lookup may be nil when every entry uses a numeric first column.
type LocalCommandRule ¶
type LocalCommandRule struct {
// contains filtered or unexported fields
}
LocalCommandRule is a compiled local_commands entry that can match against executable pathnames. Supported forms:
- "/absolute/path" — exact full path match
- "/regex/" — regex matched against the full pathname
- "basename" — matched against the last segment of the path
func CompileLocalCommand ¶
func CompileLocalCommand(s string) (*LocalCommandRule, error)
CompileLocalCommand parses and validates a local_commands entry, returning a rule that can match pathnames.
func (*LocalCommandRule) Match ¶
func (r *LocalCommandRule) Match(pathname string) bool
Match reports whether pathname matches this rule.
type Mount ¶
type Mount struct {
// RemotePath is the path on the remote machine (FUSE source).
RemotePath string
// ContainerPath is the path inside the container (bind target).
// Equals RemotePath when no explicit local path is given.
ContainerPath string
}
Mount represents a parsed container mount entry in docker-compose style. Format: [local_path:]remote_path
func ParseMount ¶
ParseMount parses a docker-compose style mount string.
Either side may start with "~" or "~/"; the local side is expanded against the local user's home immediately so the resulting ContainerPath is always absolute. The remote side is returned in its raw form (still possibly "~/..."), to be expanded against the remote user's home at SFTP-use time — see ExpandRemoteHome.