Documentation
¶
Overview ¶
Package config loads configuration from YAML, environment, and flags (R-271).
Index ¶
Constants ¶
const ( OTLPHTTP = "http/protobuf" OTLPGRPC = "grpc" )
Metrics protocols.
const DefaultMetricsInterval = time.Minute
DefaultMetricsInterval is Metrics.Interval's default, and the OpenTelemetry SDKs' own.
const LetsEncryptDirectory = "https://acme-v02.api.letsencrypt.org/directory"
LetsEncryptDirectory is ACME.DirectoryURL's default.
const PolicyEnvPrefix = "PANDO_POLICY_"
PolicyEnvPrefix is how a host policy field is set from the environment: PANDO_POLICY_MIN_SECURITY_SCORE sets min_security_score.
const RegistryAdapterID = "image_registry"
RegistryAdapterID is the ID of the image registry adapter PANDO_REGISTRY_* declares.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ACME ¶
type ACME struct {
// DirectoryURL is the CA's ACME directory. Let's Encrypt's production
// directory by default; an organization's own ACME CA, or a test CA such
// as Pebble, otherwise.
DirectoryURL string `` /* 150-byte string literal not displayed */
// CAFile is a PEM bundle of certificates trusted, beside the system's,
// when connecting to the directory: for a private ACME server whose own
// TLS certificate no public root signs. Empty trusts the system roots.
CAFile string `` /* 185-byte string literal not displayed */
}
ACME is the certificate authority the edge's certificates are ordered from when Pando issues them itself — the Kubernetes edge (O-49, R-169).
type AdapterDecl ¶
type AdapterDecl struct {
ID string `json:"id"`
Category string `json:"category"`
Kind string `json:"kind"`
Name string `json:"name"`
Default bool `json:"is_default"`
Enabled bool `json:"enabled"`
// Config is the adapter's own settings, as it would be stored in
// adapter_configs.config. Never a credential.
Config map[string]any `json:"-"`
// Credentials name where each credential is read from at startup. The
// value itself is never in the file (R-190).
Credentials map[string]CredentialRef `json:"-"`
// Functions are the AI functions this adapter handles, for an AI adapter.
Functions []FunctionDecl `json:"functions,omitempty"`
Source Source `json:"source"`
}
AdapterDecl is one adapter declared in the config file.
type Apps ¶
type Apps struct {
CPUMillis int `` /* 139-byte string literal not displayed */
MemoryBytes int64 `mapstructure:"memory_bytes" desc:"The memory each new app may use, in bytes. An app can override its own. 0 means 512 MiB."`
DiskBytes int64 `mapstructure:"disk_bytes" desc:"The disk each new app may use, in bytes. An app can override its own. 0 means 10 GiB."`
// DockerCredentials pulls a private image with the Docker login on the
// Pando server — `docker login`, the config.json it writes and any
// credential helper it names, found through DOCKER_CONFIG or
// ~/.docker — when the app has no registry credential of its own (issue
// #41). Off by default: it lends every app on the install whatever the
// server's login can read, so it is an operator's decision, made where
// only an operator can make it.
DockerCredentials bool `` /* 235-byte string literal not displayed */
}
Apps holds the resource limits every new app inherits (R-240).
R-240 says these are set at the host. They were constants: one CPU, 512 MiB and 10 GiB for every app, with nothing that could change them, so a 12-CPU host refused its thirteenth app however idle the first twelve were (issue #55). Zero means the shipped default (spec.StandardDefaults); an app still overrides its own with app.resources.override (R-241).
type Bootstrap ¶
type Bootstrap struct {
// AdminPassword is the first administrator's initial password, empty to
// have the first person to reach the console set the administrator up
// there (R-046).
//
// The one credential in this struct, and the reason nothing logs a Config
// wholesale. It exists because the generated password is shown once, in a
// log line, and a server container recreated before anyone read it leaves
// an account nobody can sign in to.
//
// Ignored once the install has any account. It is a bootstrap input, not a
// way to set a password: the account must still change it at first sign-in,
// because an environment variable is in the Compose file, in
// `docker inspect`, and inherited by every child process.
AdminPassword string `` /* 268-byte string literal not displayed */
}
Bootstrap is what first run needs, and is read on no other run.
type Config ¶
type Config struct {
Server Server `mapstructure:"server"`
Bootstrap Bootstrap `mapstructure:"bootstrap"`
Database Database `mapstructure:"database"`
Log Log `mapstructure:"log"`
Reconciler Reconciler `mapstructure:"reconciler"`
Apps Apps `mapstructure:"apps"`
Work Work `mapstructure:"work"`
Retention Retention `mapstructure:"retention"`
Registry Registry `mapstructure:"registry"`
ACME ACME `mapstructure:"acme"`
Metrics Metrics `mapstructure:"metrics"`
// File is the config file read at startup, or empty when there was none.
File string `mapstructure:"-"`
// Settings is every non-secret setting with its effective value and where
// it came from, for GET /config. Policy is the host policy fields set at
// startup, which override the stored policy (see sources.go).
Settings []Setting `mapstructure:"-"`
Policy []PolicySetting `mapstructure:"-"`
// Adapters are the adapters declared in the config file, with the AI
// functions each handles (adapters.go).
Adapters []AdapterDecl `mapstructure:"-"`
}
Config is Pando's configuration, from YAML, environment, and flags (R-271).
Adapters usually live in the database (adapter_configs), so they can be changed through the API. An install kept as code may declare them in the file instead (Adapters, see adapters.go), and those are read-only elsewhere while declared.
type CredentialRef ¶
CredentialRef is where a declared credential is read from: an environment variable, or a file such as a mounted Docker or Kubernetes secret.
type Database ¶
type Database struct {
// URL is the connection string. The bundled Compose file supplies it; an
// operator pointing Pando at an existing Postgres sets PANDO_DATABASE_URL.
//
// Whatever it names, the account must be able to manage Pando's restricted
// application role — see design 00 §1.1. Pando verifies this at startup and
// refuses to run if the audit log would be rewritable.
URL string `` /* 192-byte string literal not displayed */
ConnectTimeout time.Duration `mapstructure:"connect_timeout" desc:"How long Pando keeps trying to reach Postgres at startup before giving up."`
// PasswordFile names a file holding the password for URL's user, which
// URL then leaves out (issue #130). The bundled Compose file generates
// one on first start rather than defaulting to a known password, and
// hands it to Postgres and Pando as a file, so it is in neither the
// Compose file nor `docker inspect`. Load writes it into URL.
PasswordFile string `` /* 178-byte string literal not displayed */
// MaxConns caps this replica's pool of connections as the application
// role. pgx's own default is the CPU count, at least four, which a
// reconciler holding a connection per app it is converging, plus the
// leader's held lock, could use up on a small host and then wait on
// forever (issue #72). Postgres's max_connections must allow MaxConns
// for every replica, plus a few for each one's bootstrap.
MaxConns int32 `` /* 172-byte string literal not displayed */
}
type FunctionDecl ¶
type FunctionDecl struct {
Function string `json:"function"`
Model string `json:"model,omitempty"`
Source Source `json:"source"`
}
FunctionDecl is one AI function a declared adapter handles.
type Metrics ¶
type Metrics struct {
// OTLPEndpoint is the collector: http://otel-collector:4318 for OTLP over
// HTTP, or http://otel-collector:4317 for gRPC. http:// sends in the
// clear, https:// over TLS. Over HTTP, a URL with no path has
// /v1/metrics added, as the OpenTelemetry SDKs do.
OTLPEndpoint string `` /* 182-byte string literal not displayed */
// OTLPProtocol is http/protobuf (the default) or grpc.
OTLPProtocol string `mapstructure:"otlp_protocol" desc:"The OTLP protocol: http/protobuf or grpc."`
// OTLPHeaders are sent with every export, written as
// OTEL_EXPORTER_OTLP_HEADERS writes them: key=value pairs separated by
// commas, values URL-encoded. Usually an API key, so never reported
// (sources.go) or logged (R-194).
OTLPHeaders string `` /* 192-byte string literal not displayed */
// Interval is how often metrics are pushed. Default: a minute.
Interval time.Duration `mapstructure:"interval" desc:"How often metrics are pushed."`
}
Metrics is where Pando pushes metrics about itself, over OTLP (R-399, issue #126). Empty OTLPEndpoint: nothing is exported.
type PolicySetting ¶
type PolicySetting struct {
Key string `json:"key"`
Value any `json:"value"`
Source Source `json:"source"`
}
PolicySetting is a host policy field set at startup (a `policy:` section in the config file, or PANDO_POLICY_<FIELD>). It overrides the stored policy and cannot be changed from the console, the API or the CLI while it is set. The value is as given — a string from the environment, a typed value from the file — and is checked against the policy document by the policy package.
type Reconciler ¶
type Reconciler struct {
// Backoff is the retry schedule, indexed by consecutive failures, as a
// comma-separated list of durations: "0s,5s,15s,60s,5m".
Backoff string `` /* 262-byte string literal not displayed */
// FailureThreshold is how many failures inside FailureWindow before an app
// is given up on and left failed (R-150).
FailureThreshold int `` /* 137-byte string literal not displayed */
// FailureWindow is measured from the last failure, so a slow crash loop
// still reaches the threshold rather than resetting forever.
FailureWindow time.Duration `mapstructure:"failure_window" desc:"The window failures are counted in, measured from the last failure. 0 means 30 minutes."`
// GCInterval is how often garbage collection runs. Zero means the shipped
// hour. Short intervals are wasteful rather than dangerous — nothing the
// collector does is urgent — so unlike the backoff this gets no warning.
GCInterval time.Duration `mapstructure:"gc_interval" desc:"How often garbage collection runs. 0 means an hour."`
}
Reconciler tunes R-149's retry backoff and R-150's give-up rule.
Present because the acceptance test for R-151 has to wait out the real schedule, and at the shipped numbers that is forty minutes. Leave these unset in production: the defaults are the requirement, and Pando says so at startup if they are set faster.
func (Reconciler) BackoffSchedule ¶
func (r Reconciler) BackoffSchedule() ([]time.Duration, error)
BackoffSchedule parses Backoff, returning nil when it is unset.
type Registry ¶
type Registry struct {
// URL is the registry and an optional path prefix:
// https://registry.internal:5000, or the organization's registry such as
// 123456789012.dkr.ecr.us-east-1.amazonaws.com/pando.
URL string `` /* 307-byte string literal not displayed */
// Username and Password are the one credential Pando pushes and pulls
// with (O-36). The password may be given as a file instead
// (PasswordFile), so it need not be in the environment.
Username string `mapstructure:"username" desc:"The registry username. With kind ecr, the AWS access key ID."`
Password string `` /* 171-byte string literal not displayed */
PasswordFile string `mapstructure:"password_file" desc:"A file holding the registry password, in place of password."`
// Kind is basic (the default) or ecr, where Username and Password are an
// AWS access key ID and its secret.
Kind string `mapstructure:"kind" desc:"How Pando signs in to the registry: basic (a username and password) or ecr (an AWS access key)."`
// Layout is per_app (the default) or single.
Layout string `` /* 176-byte string literal not displayed */
// Insecure permits plain HTTP (O-35). Off by default.
Insecure bool `mapstructure:"insecure" desc:"Allow plain HTTP to the registry."`
// Always sends every build through the registry, even for a runtime that
// can import it. Off by default.
Always bool `mapstructure:"always" desc:"Send every build through the registry, even when the runtime could import it directly."`
}
Registry is the startup shorthand for declaring the install's image registry adapter (R-252, issue #153): PANDO_REGISTRY_URL and the variables beside it, or registry: in the config file. It becomes the adapter declaration image_registry (registry.go), read-only while it is set (R-271), as one written under adapters: would be. Empty URL: no registry, which single-host Docker does not need (O-34).
type Retention ¶
type Retention struct {
DeploymentsPerApp int `mapstructure:"deployments_per_app" desc:"How many deployments are kept for each app. 0 means 50."`
Scans time.Duration `mapstructure:"scans" desc:"How long security scans are kept. 0 means 90 days."`
Sessions time.Duration `mapstructure:"sessions" desc:"How long expired or revoked sessions are kept. 0 means 30 days."`
IdempotencyKeys time.Duration `mapstructure:"idempotency_keys" desc:"How long idempotency keys are kept. 0 means a day."`
SSOFlows time.Duration `mapstructure:"sso_flows" desc:"How long expired sign-in flows are kept. 0 means a day."`
Events time.Duration `mapstructure:"events" desc:"How long the event outbox is kept. 0 means 30 days."`
DeletedApps time.Duration `mapstructure:"deleted_apps" desc:"How long a deleted app's detection and backup records are kept. 0 means 30 days."`
}
Retention is how long the retention job keeps each kind of row it removes (issue #72, R-224). Zero means the shipped default for each, listed in retention.Settings: 50 deploys per app, scans 90 days, expired or revoked sessions 30 days, idempotency keys a day, expired sign-in flows a day, the event outbox 30 days, a deleted app's detection and backup record 30 days.
type Server ¶
type Server struct {
Addr string `` /* 139-byte string literal not displayed */
ShutdownTimeout time.Duration `mapstructure:"shutdown_timeout" desc:"How long Pando waits for requests in flight to finish when it is stopped."`
// ProxyUpstream is the address routing adapters are told to send traffic
// to (R-023). It must be reachable from wherever an adapter's data plane
// runs, which is not necessarily where Pando runs.
ProxyUpstream string `` /* 227-byte string literal not displayed */
// Issuer is the `iss` claim in every assertion, and identifies this
// install to the apps it fronts.
Issuer string `` /* 140-byte string literal not displayed */
// ExternalURL is how a browser reaches this installation, and exists
// because Pando usually does not terminate its own TLS (O-19).
//
// Behind a TLS-terminating reverse proxy — the topology SECURITY.md
// describes — every request arrives over plain HTTP, so `r.TLS` is nil and
// Pando cannot tell an encrypted browser connection from an unencrypted
// one. Session cookies then go out without `Secure`, and a single plaintext
// request to the hostname puts one on the wire.
//
// The operator states the scheme rather than Pando guessing it from a
// header. `X-Forwarded-Proto` is the usual answer and is rejected here for
// the same reason R-053 strips inbound `X-Pando-*`: any client that can
// reach Pando directly can also set it, so trusting it without a
// trusted-proxy list trades one hole for another, and with one it becomes a
// second thing to get wrong.
//
// Empty is correct for the two topologies where the request already tells
// the truth: Pando serving TLS itself, and the plain-HTTP localhost install
// the README documents.
ExternalURL string `` /* 275-byte string literal not displayed */
// TrustedProxies are the proxies whose X-Forwarded-For names the client
// in the audit log (R-380, design 12 §3.2): addresses and CIDRs, separated
// by commas. Empty, the default, records the connecting peer. It decides
// the audited address and nothing else — not Secure, which ExternalURL
// decides, and not rate limits (O-19).
TrustedProxies string `` /* 217-byte string literal not displayed */
// RoutingMode is how apps are addressed — "subdomain" or "path" (design 03
// §4.1). Neither is a global setting in the spec sense; this is the
// install's default shape, and each app's spec still names its own mode.
RoutingMode spec.RoutingMode `` /* 199-byte string literal not displayed */
// BaseDomain is what a per-app subdomain is carved out of, so an app
// called "notes" is reached at notes.example.com. Only used in subdomain
// mode; empty is correct for an install addressing apps by path, which is
// the default and needs no DNS at all (R-002 — setup cost is paid once).
BaseDomain string `` /* 172-byte string literal not displayed */
// PortRangeStart and PortRangeEnd bound the ports handed to apps in
// port-mode routing — the loopback adapter's only mode, and so the laptop
// default. [P]: the requirements do not specify a range (O-15).
PortRangeStart int `mapstructure:"port_range_start" desc:"The first host port given to an app when apps are reached by port."`
PortRangeEnd int `mapstructure:"port_range_end" desc:"The last host port given to an app when apps are reached by port."`
// WorkDir is where a DR bundle is assembled before it is encrypted and
// streamed out (R-212). It needs room for a database dump plus every app
// volume, which is why it is configurable and does not default to the
// system temporary directory — that is often a small tmpfs, and running out
// of space partway through a backup is how an install discovers it has no
// backups.
WorkDir string `` /* 165-byte string literal not displayed */
// AuditArchiveDir is where Pando keeps audit archives itself, when host
// policy's audit_archive is keep, the default (R-347). Beside the rest
// of Pando's data, on the same volume, so the archives are on the disk
// R-224 is about rather than somewhere nobody counts.
AuditArchiveDir string `` /* 126-byte string literal not displayed */
// TokenKeyPath is the file holding the key API tokens are stored under,
// as HMAC-SHA-256 (R-063). Generated on first start. Outside the database
// so a dump alone cannot test a guess at a token; every replica must read
// the same file, which is why it defaults to the shared /var/lib/pando
// beside the secrets key, and a DR bundle carries it (R-212).
TokenKeyPath string `` /* 193-byte string literal not displayed */
// AdvertiseURL is where the other Pando replicas reach this one, for the
// one request that has to go to a particular replica: a deploy's live log
// (issue #72). Empty means http://<hostname><port of addr>, which is right
// on a Compose network; in Kubernetes, set it to the pod's address, such
// as http://$(POD_IP):8080. With one replica nothing reads it.
AdvertiseURL string `` /* 257-byte string literal not displayed */
}
type Setting ¶
type Setting struct {
Key string `json:"key"`
Value any `json:"value"`
Source Source `json:"source"`
// Env is the variable that sets it, whether or not it is set — so a
// setting still at its default can say how to change it.
Env string `json:"env"`
}
Setting is one startup setting, its effective value and where it came from.
type SettingDoc ¶
type SettingDoc struct {
Env string `json:"env"`
Key string `json:"key"`
Type string `json:"type"`
Default string `json:"default"`
Description string `json:"description"`
Group string `json:"group"`
Secret bool `json:"secret"`
}
SettingDoc is one startup setting as docs/config.json publishes it: the variable and key that set it, its type and default, and what it does.
Read from Config itself — the mapstructure key, the desc tag beside it, the default Load starts from and the variable Load binds — so the reference cannot name a setting Pando does not read, or miss one it does (R-271).
type Source ¶
type Source struct {
// Kind is "env", "file" or "default".
Kind string `json:"kind"`
// Name is the environment variable, or the config file's path.
Name string `json:"name,omitempty"`
// Key is the key inside the config file.
Key string `json:"key,omitempty"`
}
Source is where a value came from.
type Work ¶
type Work struct {
// Deploys is the older name for host policy's max_concurrent_deploys
// (issue #93). Set, it fixes that policy field unless the policy key is
// set too (policyOf); nothing reads it from here.
Deploys int `` /* 159-byte string literal not displayed */
// Detections is how many detections this replica runs at once. Default:
// one per CPU, at least two.
Detections int `mapstructure:"detections" desc:"How many detections this replica runs at once. 0 means one per CPU, and at least two."`
// Backups is how many rolling backups the leader takes at once.
// Default: two.
Backups int `mapstructure:"backups" desc:"How many rolling backups the leader takes at once. 0 means two."`
// AutoDeploy is how many apps the leader checks for new commits at
// once. Default: eight.
AutoDeploy int `mapstructure:"auto_deploy" desc:"How many apps the leader checks for new commits at once. 0 means eight."`
}
Work bounds the background work one replica does at once (issue #72). Zero means the shipped default for each.