Documentation
¶
Overview ¶
Package config loads the server configuration: one YAML file, decoded strictly, plus MYOWNPKI_* environment overrides (go-conventions.md "Configuration", PLAN §14).
Rules:
- Unknown keys, a second YAML document and files over MaxFileSize are errors.
- Unknown MYOWNPKI_* variables are errors too: a typo must not be ignored.
- Dev mode is a command-line flag (serve --dev), never a config key.
- No secrets: the unseal passphrase is never read from a file or variable.
Load returns a validated Config or an error that names every problem.
Index ¶
- Constants
- Variables
- func ACMEBaseURL(s string) (string, error)
- func ACMEHost(base string) string
- func ACMEResolver(s string) (string, error)
- func AgentBaseURL(s string) (string, error)
- func AgentHost(base string) string
- func DefaultPath(goos string, getenv func(string) string) string
- func EnvNames() []string
- func Load(path string, environ []string) (Config, Source, error)
- func ParseNetworks(s string) ([]netip.Prefix, error)
- func ParseTLSNames(s string) ([]string, []netip.Addr, error)
- func PasskeyRPID(origin string) (string, error)
- type ACME
- type Admin
- type Agent
- type Auth
- type Config
- type Log
- type Public
- type Source
Constants ¶
const EnvConfigFile = EnvPrefix + "CONFIG"
EnvConfigFile names the config file when --config is not given.
const EnvPrefix = "MYOWNPKI_"
EnvPrefix starts every environment variable this package reads.
const MaxFileSize = 64 << 10
MaxFileSize limits the config file; a real one is a few hundred bytes.
Variables ¶
var ( LogLevels = []string{"debug", "info", "warn", "error"} LogFormats = []string{"json", "text"} )
Allowed values.
var ErrInvalid = errors.New("invalid configuration")
ErrInvalid is wrapped by every error about a malformed or inconsistent configuration.
Functions ¶
func ACMEBaseURL ¶ added in v0.2.0
ACMEBaseURL checks acme.base_url and returns it without a trailing slash: https only (the proxy terminates TLS; RFC 8555 §6.1), a host, no user, query or fragment.
func ACMEHost ¶ added in v0.2.2
ACMEHost is the host of acme.base_url in lower case: the name (or IP) in the certificate of the ACME listener with acme.tls_issuer.
func ACMEResolver ¶ added in v0.2.0
ACMEResolver checks acme.resolver: empty, an IP (port 53) or IP:port.
func AgentBaseURL ¶ added in v0.3.0
AgentBaseURL checks agent.base_url: https://host[:port], no path.
func AgentHost ¶ added in v0.3.0
AgentHost is the host of agent.base_url in lower case: the name (or IP) in the agent listener's certificate.
func DefaultPath ¶
DefaultPath is the config file used when neither --config nor MYOWNPKI_CONFIG is given: %ProgramData%\MyOwnPKI\config.yaml on Windows, /etc/myownpki/config.yaml elsewhere. getenv is os.Getenv in production.
func ParseNetworks ¶
ParseNetworks parses a comma-separated list of IPs and CIDRs (trusted proxies, the admin allowlist). A single IP becomes a /32 or /128. Zones and host bits in a CIDR are refused – a typo like 10.0.0.1/8 must not silently trust a whole network.
func ParseTLSNames ¶
ParseTLSNames splits admin.tls_names into DNS names and IPs. DNS names are LDH labels in lower case (a wildcard is not allowed: the bootstrap certificate names exactly the hosts admins use).
func PasskeyRPID ¶
PasskeyRPID checks auth.passkey_origin and returns its host name, the WebAuthn RP ID ("" when passkeys are off). Browsers allow WebAuthn only in a secure context: https, or http on localhost.
Types ¶
type ACME ¶ added in v0.2.0
type ACME struct {
// Listen is IP:port of the ACME listener – never the public CRL port, so
// nobody talks ACME in clear text. Without TLSIssuer it is for the reverse
// proxy only; with it, for the clients (e.g. :443).
Listen string `yaml:"listen"`
// BaseURL is what clients use (the proxy's https URL, e.g.
// https://pki.homelab.lan/acme); every URL the server hands out is built
// from it. Empty: ACME is off.
BaseURL string `yaml:"base_url"`
// TrustedProxies may connect to Listen (others get 403), and only their
// X-Forwarded-For is believed (IPs or CIDRs, comma-separated). Ignored
// with TLSIssuer: then every client connects directly and the peer is
// the client address.
TrustedProxies string `yaml:"trusted_proxies"`
// Resolver is the DNS server (IP or IP:port) for dns-01 and for resolving
// http-01 names. Empty: the system resolver.
Resolver string `yaml:"resolver"`
// TLSIssuer names a CA of this instance: ACME runs with TLS on Listen,
// with a certificate for the host of BaseURL that the server issues from
// this CA itself. Empty: plain HTTP behind a reverse proxy.
TLSIssuer string `yaml:"tls_issuer"`
}
ACME is the ACME server (PHASE2): by default plain HTTP on its own listener, only behind a reverse proxy that terminates TLS (owner Q1 2026-10-22); with TLSIssuer it speaks TLS itself (v0.2.2, owner 2026-10-24).
type Admin ¶
type Admin struct {
// Listen is IP:port; an empty IP means all interfaces.
Listen string `yaml:"listen"`
// TLSCertFile and TLSKeyFile name an operator-provided certificate. Both
// empty: a self-signed bootstrap certificate is created (PLAN §5).
TLSCertFile string `yaml:"tls_cert_file"`
TLSKeyFile string `yaml:"tls_key_file"`
// TLSNames are further DNS names or IPs (comma-separated) for the
// bootstrap certificate, besides the host name, the listen IP and
// loopback – the names admins type into the browser. With TLSIssuer they
// are exactly the names of the issued certificate.
TLSNames string `yaml:"tls_names"`
// TLSIssuer names a CA of this instance (v0.2.2): the server issues the
// listener's certificate from it itself, while unsealed, and renews it.
// Empty: the operator certificate or the bootstrap certificate.
TLSIssuer string `yaml:"tls_issuer"`
// AllowedNetworks limits who may connect (IPs or CIDRs, comma-separated);
// empty: everybody. Checked against the direct peer before TLS (ADR-08).
AllowedNetworks string `yaml:"allowed_networks"`
}
Admin is the admin listener: web UI and REST API (ADR-08).
type Agent ¶ added in v0.3.0
type Agent struct {
// BaseURL is what agents connect to, e.g. https://pki.homelab.lan:8444;
// its host is the name in the listener certificate. Empty: no agents.
BaseURL string `yaml:"base_url"`
// Listen is IP:port of the agent listener – its own port, never the
// admin, ACME or public one.
Listen string `yaml:"listen"`
// TLSIssuer names the CA that issues the listener certificate, as for
// admin.tls_issuer: an intermediate, issued while unsealed.
TLSIssuer string `yaml:"tls_issuer"`
// CA names the agent CA: an intermediate with the EKU limit clientAuth
// only. It signs the agents' 7-day certificates, and only certificates
// from it pass the listener's client authentication.
CA string `yaml:"ca"`
// PackageDir is the immutable release-artifact directory exposed by the
// agent listener. The host installer stages it; the container uses /opt.
PackageDir string `yaml:"package_dir"`
}
Agent is the agent listener (ADR-08, docs/PHASE3.md §1.4): Connect-RPC over mTLS for myownpki-agent. Off while BaseURL is empty.
type Auth ¶
type Auth struct {
// KeyFile holds the key that encrypts the TOTP secrets and keys the
// recovery code hashes. Empty: <data_dir>/auth.key. It may live outside
// the data directory (Docker secret, systemd credential): then a copy of
// the databases alone holds no usable TOTP secret.
KeyFile string `yaml:"key_file"`
// TrustedProxies lists reverse proxies (IPs or CIDRs, comma-separated)
// whose X-Forwarded-For header is believed. Empty: the direct peer is
// the client – the safe default.
TrustedProxies string `yaml:"trusted_proxies"`
// PasskeyOrigin is the address users open the admin UI with, e.g.
// https://pki.homelab.lan:9443 (PHASE1 step 17). Passkeys are bound to its
// host name (the WebAuthn RP ID). Empty: no passkeys, TOTP only.
PasskeyOrigin string `yaml:"passkey_origin"`
}
Auth configures sign-in (PHASE1 step 10).
type Config ¶
type Config struct {
// DataDir holds system.db and the tenant directories. Absolute path.
DataDir string `yaml:"data_dir"`
Log Log `yaml:"log"`
Admin Admin `yaml:"admin"`
Public Public `yaml:"public"`
Auth Auth `yaml:"auth"`
ACME ACME `yaml:"acme"`
Agent Agent `yaml:"agent"`
}
Config is the server configuration. Field order is the order of the example file.
func Default ¶
func Default() Config
Default returns the configuration used for every key the file leaves out. The admin listener binds to loopback only: remote administration is a deliberate decision of the operator.
func (*Config) ApplyEnv ¶
ApplyEnv applies MYOWNPKI_* overrides from environ (os.Environ format) and returns the names it applied, sorted. An unknown MYOWNPKI_* variable is an error: a typo would otherwise be ignored silently. An empty value is applied as well, so MYOWNPKI_PUBLIC_LISTEN= disables the public listener.
func (Config) AuthKeyFile ¶
AuthKeyFile returns the path of the auth key: auth.key_file or <data_dir>/auth.key.
type Log ¶
type Log struct {
Level string `yaml:"level"` // debug, info, warn, error
Format string `yaml:"format"` // json (production) or text
}
Log configures the process log (not the audit log).