Documentation
¶
Overview ¶
Package config loads and validates /etc/mooring/config.yaml — the root of trust (plan §5.1). Everything here is fail-closed: any precondition violation returns an error and the binary refuses to boot. No web route ever reads or writes this file; it is edited only over SSH.
Index ¶
- Constants
- func DecodeKey(s string) ([]byte, error)
- type AdminConfig
- type AlertingConfig
- type AuthConfig
- type Config
- func (c *Config) Allowlist() []netip.Prefix
- func (c *Config) EdgeCAByName(name string) (EdgeCA, bool)
- func (c *Config) HasEdgeCA(name string) bool
- func (c *Config) IsProtectedProject(project string) bool
- func (c Config) String() string
- func (c *Config) TrustedProxyPrefixes() []netip.Prefix
- func (c *Config) Validate() error
- type CookieConfig
- type DockerConfig
- type Duration
- type EdgeCA
- type EdgeConfig
- type EdgeMode
- type EditorBlock
- type EditorMode
- type GitConfig
- type GitHubConfig
- type MonitorConfig
- type RetentionConfig
- type ServerConfig
- type ServerFileRoot
- type SessionConfig
- type SetupConfig
Constants ¶
const DefaultPath = "/etc/mooring/config.yaml"
DefaultPath is where the root-of-trust config lives in production.
const DevInsecurePermsEnv = "MOORING_DEV_INSECURE_PERMS"
DevInsecurePermsEnv, when set to a truthy value, relaxes the config-file ownership/permission enforcement for LOCAL DEVELOPMENT only. It is read from the environment (never from the config file itself) so the file can never disable its own root-of-trust checks (review #6).
Variables ¶
This section is empty.
Functions ¶
Types ¶
type AdminConfig ¶
AdminConfig optionally fronts the admin UI through the edge and points at the Caddy admin endpoint (plan §6.1 SBD-1/SBD-2).
type AlertingConfig ¶
type AlertingConfig struct {
Enabled bool `yaml:"enabled"`
EvalInterval Duration `yaml:"eval_interval"` // evaluator tick
NotifyMinInterval Duration `yaml:"notify_min_interval"` // global rate limit between sends
QuietStartHour int `yaml:"quiet_start_hour"` // [0..23], -1 disables (suppresses WARNING; CRITICAL always pages)
QuietEndHour int `yaml:"quiet_end_hour"`
DeadMansURL string `yaml:"dead_mans_url"` // outbound heartbeat to an external cron-monitor
DeadMansInterval Duration `yaml:"dead_mans_interval"`
}
AlertingConfig is the Tier-1 tuning for the read-and-notify alert engine (plan §8). Channels + rules are operator-managed in the DB; this only tunes the engine. Off by default (no engine goroutines run unless enabled).
type AuthConfig ¶
type AuthConfig struct {
Username string `yaml:"username"`
PasswordHash string `yaml:"password_hash"`
TOTPSecret string `yaml:"totp_secret"`
}
AuthConfig holds the single operator's credentials.
type Config ¶
type Config struct {
BindAddr string `yaml:"bind_addr"`
EncryptionKey string `yaml:"encryption_key"`
EncryptionKeyPrevious string `yaml:"encryption_key_previous"`
IPAllowlist []string `yaml:"ip_allowlist"`
TrustProxy bool `yaml:"trust_proxy"`
TrustedProxies []string `yaml:"trusted_proxies"`
Auth AuthConfig `yaml:"auth"`
Edge EdgeConfig `yaml:"edge"`
Admin AdminConfig `yaml:"admin"`
Session SessionConfig `yaml:"session"`
Cookie CookieConfig `yaml:"cookie"`
Docker DockerConfig `yaml:"docker"`
Monitor MonitorConfig `yaml:"monitor"`
Git GitConfig `yaml:"git"`
GitHub GitHubConfig `yaml:"github"`
CaddyEditor EditorBlock `yaml:"caddy_editor"`
ComposeValidation EditorBlock `yaml:"compose_validation"`
Setup SetupConfig `yaml:"setup"`
Retention RetentionConfig `yaml:"retention"`
Alerting AlertingConfig `yaml:"alerting"`
Server ServerConfig `yaml:"server"`
DataDir string `yaml:"data_dir"`
// ProtectedProjects are Compose projects Mooring must never start/stop/
// redeploy (the socket-proxy, and later the edge) — plan §3 protected set.
ProtectedProjects []string `yaml:"protected_projects"`
// contains filtered or unexported fields
}
Config is the typed root-of-trust document. Secret-bearing fields are kept as plain strings here (the file itself is 0600 root:root) but are never echoed: String() is overridden to redact them.
func Load ¶
Load reads, parses, and fully validates the config at path. It is the only entry point; a returned error means refuse-to-boot.
func Parse ¶
Parse decodes and validates config bytes (used by Load and by tests). Unknown keys are a hard error so a typo or smuggled key cannot slip through.
func (*Config) EdgeCAByName ¶
EdgeCAByName returns the configured CA with the given name.
func (*Config) IsProtectedProject ¶
IsProtectedProject reports whether a compose project is in the protected set.
func (Config) String ¶
String redacts the secret-bearing fields so a Config can never be logged in the clear (plan §5.5 / §15 lint).
func (*Config) TrustedProxyPrefixes ¶
TrustedProxyPrefixes returns the parsed trusted-proxy prefixes.
type CookieConfig ¶
type CookieConfig struct {
Prefix string `yaml:"prefix"` // "__Host-" (default) or "__Secure-"
BasePath string `yaml:"base_path"` // required iff prefix is __Secure-
}
CookieConfig selects the session cookie prefix model (plan §5.3). __Host- mandates Path=/ and no base path; __Secure- pairs with a base_path.
type DockerConfig ¶
type DockerConfig struct {
ProxyAddr string `yaml:"proxy_addr"`
ExternalProxy bool `yaml:"external_proxy"`
}
DockerConfig points at the read-only docker-socket-proxy (plan §3). Mooring NEVER talks to the raw socket; ProxyAddr must be a loopback endpoint.
By default Mooring MANAGES this proxy itself: at boot it brings up the embedded, Mooring-owned read-only proxy compose so the operator never runs a docker command (they only ever write mooring.yaml). Set external_proxy: true if you run your own proxy/endpoint at proxy_addr and want Mooring to leave it alone.
type EdgeCA ¶
type EdgeCA struct {
Name string `yaml:"name"` // [a-z][a-z0-9-]{0,30}; referenced as `ca: <name>`
DirectoryURL string `yaml:"directory_url"` // the ACME directory URL (https)
Email string `yaml:"email"` // optional ACME contact; falls back to acme_email
TrustedRoot string `yaml:"trusted_root"` // optional PEM file Caddy trusts for the CA's OWN https
}
EdgeCA is an additional ACME issuer — a private/internal CA (e.g. step-ca). A mooring.yaml edge route or cert binding opts into it by Name; everything else keeps using the default edge.acme_ca. Defined ONLY here in the root-of-trust config (an app repo must never be able to introduce a trusted CA).
type EdgeConfig ¶
type EdgeConfig struct {
Mode EdgeMode `yaml:"mode"`
ACMEEmail string `yaml:"acme_email"`
ACMECA string `yaml:"acme_ca"`
CAs []EdgeCA `yaml:"cas"` // extra named issuers (private CAs) routes/cert-bindings can opt into by name
ApplyProbeWindow Duration `yaml:"apply_probe_window"`
L4Enabled bool `yaml:"l4_enabled"` // own a managed L4 (TCP/UDP) load balancer (nginx-stream)
L4NginxDigest string `yaml:"l4_nginx_digest"` // pinned SHA-256 of the nginx binary (optional)
}
EdgeConfig configures the managed edge (plan §3.1, §6).
type EdgeMode ¶
type EdgeMode string
EdgeMode is the managed/external switch (plan §3.1). Default managed.
type EditorBlock ¶
type EditorBlock struct {
Mode EditorMode `yaml:"mode"`
}
EditorBlock is the strict|review knob shared by the Caddy editor and the compose importer.
type EditorMode ¶
type EditorMode string
EditorMode gates how far the Caddy editor / compose importer may soften lints.
const ( EditorStrict EditorMode = "strict" EditorReview EditorMode = "review" )
type GitConfig ¶
type GitConfig struct {
PollInterval *Duration `yaml:"poll_interval"`
}
GitConfig tunes the connected-repo auto-fetch poller. So a repo connected in the dashboard "just works" with no webhook setup, Mooring fetches every connected repo on this cadence — READ-PLANE ONLY: the poller never deploys, it just surfaces an "update available" the operator then deploys with a click. (Push-to-deploy stays an explicit opt-in via the webhook + auto_deploy, never the background poller.)
PollInterval is a pointer so an omitted key (nil → the 2 min default) is distinguishable from an explicit "poll_interval: 0" (disables polling). A negative value also disables.
func (GitConfig) PollIntervalD ¶
PollIntervalD returns the effective poll interval (0 when disabled / unset).
type GitHubConfig ¶
type GitHubConfig struct {
ClientID string `yaml:"client_id"`
ClientSecret string `yaml:"client_secret"`
}
GitHubConfig holds the optional "Connect with GitHub" OAuth App credentials. The operator registers an OAuth App once in their GitHub settings and pastes the id + secret here (install-time, SSH — never a browser). When both are set, the dashboard offers one-click repo connect (pick a repo; Mooring installs a read-only deploy key for it — no key pasting). Empty = the feature is simply off.
func (GitHubConfig) Enabled ¶
func (g GitHubConfig) Enabled() bool
Enabled reports whether GitHub connect is configured.
type MonitorConfig ¶
type MonitorConfig struct {
PollInterval Duration `yaml:"poll_interval"`
MetricsRetention Duration `yaml:"metrics_retention"`
}
MonitorConfig tunes the read-plane poller (plan §4 read plane).
type RetentionConfig ¶
type RetentionConfig struct {
Interval Duration `yaml:"interval"` // how often the retention pass runs
EventsMaxAge Duration `yaml:"events_max_age"` // audit rows older than this are prunable
EventsMaxRows int `yaml:"events_max_rows"` // hard cap on audit rows (oldest trimmed)
ArchiveMaxMB int `yaml:"archive_max_mb"` // rotate the security-archive NDJSON past this
}
RetentionConfig is the Tier-1 (SSH-only, SIGHUP-reloadable) audit-retention block (plan §16.1). It bounds the events/audit table so it can never become the disk-wedge that kills the write plane — while NEVER silently dropping a security row (those are archived to NDJSON first, fail-closed).
type ServerConfig ¶
type ServerConfig struct {
// FileRoots are directories the operator may browse READ-ONLY in the Server
// tab (e.g. an app's log dir). Each needs a stable name (used in the URL).
FileRoots []ServerFileRoot `yaml:"file_roots"`
// DebCacheDir is the directory the operator downloads Mooring .deb packages
// into; the Server tab can delete OLD ones there (never the running version),
// behind password+TOTP re-auth. Must be absolute. It also must be within the
// service's writable paths for the delete to succeed (see docs).
DebCacheDir string `yaml:"deb_cache_dir"`
}
ServerConfig configures the read-only "Server" tab (host inspection + cleanup). Both knobs are OPT-IN and default to off/empty: with no file_roots the file view is disabled entirely (fail-closed), and with no deb_cache_dir the old-.deb cleanup is unavailable. The host monitor (CPU/memory/disk/processes) needs no config. Secret/state paths (the data dir, config, keys, DB) are ALWAYS denied to the file view regardless of what's listed here — see internal/web.
type ServerFileRoot ¶
type ServerFileRoot struct {
Name string `yaml:"name"` // [a-z0-9][a-z0-9-]{0,30}; used in the URL/UI
Path string `yaml:"path"` // absolute directory path
}
ServerFileRoot is one named, browsable directory.
type SessionConfig ¶
type SessionConfig struct {
IdleTimeout Duration `yaml:"idle_timeout"`
AbsoluteTimeout Duration `yaml:"absolute_timeout"`
}
SessionConfig holds idle/absolute timeouts (plan §5.3).
type SetupConfig ¶
type SetupConfig struct {
Enabled bool `yaml:"enabled"`
// Image is the digest-pinned jail base image (the throwaway container backend).
Image string `yaml:"image"`
// Resource limits — counted against the global one-docker-child semaphore.
WallClock Duration `yaml:"wall_clock"` // hard wall-clock timeout
CPUs string `yaml:"cpus"` // docker --cpus value, e.g. "1.0"
MemoryMB int `yaml:"memory_mb"` // hard memory cap (MemorySwapMax=0)
PidsLimit int `yaml:"pids_limit"` // max processes
ScratchMB int `yaml:"scratch_mb"` // writable scratch quota
OutputCapKB int `yaml:"output_cap_kb"` // captured stdout/stderr cap
}
SetupConfig gates the Mode-3 setup-script sandbox (plan §7/§9, OFF by default, hard-gated). When enabled, scripts run in a throwaway jail with the limits below; the binary refuses to boot if the host can't provide a working sandbox (plan §5.1), and a live self-test runs before EVERY execution.