config

package
v0.0.4 Latest Latest
Warning

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

Go to latest
Published: Apr 26, 2026 License: GPL-3.0 Imports: 13 Imported by: 0

Documentation

Index

Constants

View Source
const LevelTrace = slog.Level(-8)

LevelTrace is a custom log level below Debug for fine-grained diagnostic output (protocol details, per-message flow, algorithm steps).

Variables

This section is empty.

Functions

func ParseLogLevel added in v0.0.2

func ParseLogLevel(s string) slog.Level

ParseLogLevel converts a log level name (trace, debug, info, warn, error) to an slog.Level. Returns slog.LevelInfo for empty or unrecognized values.

func ResolveSecrets added in v0.0.2

func ResolveSecrets(ctx context.Context, cfg *Config, resolver SecretResolver) error

ResolveSecrets walks all Secret and *Secret fields in cfg and resolves any vault references (values starting with "vault:"). Uses the same struct-walking pattern as applyEnvToStruct.

Types

type AuditConfig added in v0.0.2

type AuditConfig struct {
	Path string `toml:"path"` // e.g. /data/audit/blockyard.jsonl
}

type Config

type Config struct {
	Server    ServerConfig     `toml:"server"`
	Docker    DockerConfig     `toml:"docker"`
	Storage   StorageConfig    `toml:"storage"`
	Database  DatabaseConfig   `toml:"database"`
	Proxy     ProxyConfig      `toml:"proxy"`
	Process   *ProcessConfig   `toml:"process"`   // nil when backend != "process"
	Redis     *RedisConfig     `toml:"redis"`     // nil when not configured
	OIDC      *OidcConfig      `toml:"oidc"`      // nil when not configured
	Vault     *VaultConfig     `toml:"vault"`     // nil when not configured
	Audit     *AuditConfig     `toml:"audit"`     // nil when not configured
	Telemetry *TelemetryConfig `toml:"telemetry"` // nil when not configured
	Update    *UpdateConfig    `toml:"update"`    // nil when not configured

	// Openbao is the deprecated name for Vault. Present only to let
	// existing configs keep loading; migrateDeprecatedFields copies it
	// into Vault at load time and emits a warning. Remove in a future
	// release.
	Openbao *VaultConfig `toml:"openbao"`

	// ConfigPath is the filesystem path to the config file this
	// Config was loaded from. Populated by main.go after Load so the
	// process orchestrator can re-exec the new blockyard with the
	// same --config flag. Not a TOML field — no struct tag.
	ConfigPath string `toml:"-"`
}

func Load

func Load(path string) (*Config, error)

type DataMountSource added in v0.0.3

type DataMountSource struct {
	Name string `toml:"name"`
	Path string `toml:"path"`
}

DataMountSource defines an admin-approved mount source. The Name is referenced by apps; the Path is the host-side location.

type DatabaseConfig

type DatabaseConfig struct {
	Driver string `toml:"driver"` // "sqlite" (default) or "postgres"
	Path   string `toml:"path"`   // used when driver = "sqlite"
	URL    string `toml:"url"`    // PostgreSQL connection string; used when driver = "postgres"

	// Vault DB secrets engine integration (postgres only).
	//
	// VaultMount names the secrets engine mount path. Shared between
	// admin credential issuance (#238) and per-user board-storage
	// credentials (#283, #284). Default "database".
	//
	// VaultRole, when set, routes the admin connection through vault:
	// blockyard reads `{VaultMount}/static-creds/{VaultRole}` at
	// startup instead of using a static Database.URL password.
	// Requires [vault].
	//
	// VaultDBConnection names the vault database-engine connection
	// blockyard targets when registering per-user static roles
	// (#284) — the `{name}` from `{VaultMount}/config/{name}` the
	// operator created at deploy time. Required when BoardStorage
	// is true. Passed verbatim as the `db_name` field of
	// `POST {mount}/static-roles/{name}`.
	//
	// VaultRotationPeriod is passed as the `rotation_period` field
	// when registering per-user static roles. Vault auto-rotates
	// each user's PG password on this cadence. No vault-native
	// operator knob exists for this — it's a per-static-role setting
	// passed at creation time, which is blockyard's job. Applies
	// only when BoardStorage = true; ignored otherwise. Default 24h.
	//
	// BoardStorage enables the board-storage feature: adds a PG16+
	// preflight at startup and (in #284) drives per-user role
	// provisioning. Requires driver = "postgres" and [vault].
	VaultMount          string   `toml:"vault_mount"`
	VaultRole           string   `toml:"vault_role"`
	VaultDBConnection   string   `toml:"vault_db_connection"`
	VaultRotationPeriod Duration `toml:"vault_rotation_period"`
	BoardStorage        bool     `toml:"board_storage"`
}

type DockerConfig

type DockerConfig struct {
	Socket          string            `toml:"socket"`
	Image           string            `toml:"image"`
	ShinyPort       int               `toml:"shiny_port"`
	PakVersion      string            `toml:"pak_version"`      // "stable" (default), or pinned version
	ServiceNetwork  string            `toml:"service_network"`  // Docker network whose containers are made reachable from workers
	Runtime         string            `toml:"runtime"`          // OCI runtime; empty = Docker daemon default
	RuntimeDefaults map[string]string `toml:"runtime_defaults"` // per-access-type defaults (e.g. public=kata-runtime)

	// Deprecated; copied into the new locations by migrateDeprecatedFields
	// and removed in the next release.
	DeprecatedDefaultMemoryLimit string   `toml:"default_memory_limit"`
	DeprecatedDefaultCPULimit    float64  `toml:"default_cpu_limit"`
	DeprecatedStoreRetention     Duration `toml:"store_retention"`
}

type Duration

type Duration struct {
	time.Duration
}

Duration wraps time.Duration for TOML deserialization from strings like "30s", "5m", "1h".

func (*Duration) UnmarshalText

func (d *Duration) UnmarshalText(text []byte) error

type OidcConfig added in v0.0.2

type OidcConfig struct {
	IssuerURL          string   `toml:"issuer_url"`
	IssuerDiscoveryURL string   `toml:"issuer_discovery_url"` // optional: use a different URL for OIDC discovery (e.g. Docker-internal DNS)
	ClientID           string   `toml:"client_id"`
	ClientSecret       Secret   `toml:"client_secret"`
	CookieMaxAge       Duration `toml:"cookie_max_age"`
	InitialAdmin       string   `toml:"initial_admin"`
	DefaultRole        string   `toml:"default_role"` // role assigned on first login: "viewer" (default) or "publisher"
}

type OpenbaoConfig deprecated added in v0.0.2

type OpenbaoConfig = VaultConfig

OpenbaoConfig is the deprecated type alias kept so external callers that still reference OpenbaoConfig continue to compile. Remove together with the deprecated Openbao field on Config.

Deprecated: use VaultConfig.

type ProcessConfig added in v0.0.3

type ProcessConfig struct {
	BwrapPath      string `toml:"bwrap_path"`             // path to bubblewrap binary
	RPath          string `toml:"r_path"`                 // path to R binary
	SeccompProfile string `toml:"seccomp_profile"`        // path to compiled BPF seccomp profile; empty = no seccomp
	PortRangeStart int    `toml:"port_range_start"`       // first port for workers (inclusive)
	PortRangeEnd   int    `toml:"port_range_end"`         // last port for workers (inclusive)
	WorkerUIDStart int    `toml:"worker_uid_range_start"` // first host UID for workers (inclusive)
	WorkerUIDEnd   int    `toml:"worker_uid_range_end"`   // last host UID for workers (inclusive)
	WorkerGID      int    `toml:"worker_gid"`             // shared host GID for all workers (used by egress firewall rules)

	// SkipMetadataCheck suppresses the cloud-metadata reachability
	// preflight check. Default false: the check is meant to flag the
	// "workers can reach 169.254.169.254 and steal IAM creds" footgun
	// on VMs with an attached instance role. Set true only when
	// blockyard itself legitimately needs metadata access (e.g.
	// IRSA-style auth against S3); operators who opt in also accept
	// the worker-compromise implication.
	SkipMetadataCheck bool `toml:"skip_metadata_check"`
}

ProcessConfig configures the process (bubblewrap) backend.

type ProxyConfig

type ProxyConfig struct {
	WsCacheTTL         Duration `toml:"ws_cache_ttl"`
	HealthInterval     Duration `toml:"health_interval"`
	WorkerStartTimeout Duration `toml:"worker_start_timeout"`
	MaxWorkers         int      `toml:"max_workers"`
	LogRetention       Duration `toml:"log_retention"`
	SessionIdleTTL     Duration `toml:"session_idle_ttl"`
	IdleWorkerTimeout  Duration `toml:"idle_worker_timeout"`
	HTTPForwardTimeout Duration `toml:"http_forward_timeout"`
	MaxCPULimit        *float64 `toml:"max_cpu_limit"`
	TransferTimeout    Duration `toml:"transfer_timeout"`     // default 60s when unset
	SessionMaxLifetime Duration `toml:"session_max_lifetime"` // 0 = unlimited (default); hard cap on session duration
	// AuthRateLimitPerMinute caps the per-IP request rate on the
	// /login, /callback, and /logout endpoints. Default 10/min —
	// tight enough to slow password guessing, loose enough for
	// normal interactive use. Bump in e2e stacks where multiple
	// Playwright tests each drive a full OIDC round-trip.
	AuthRateLimitPerMinute int `toml:"auth_rate_limit_per_minute"`
	// SessionStore selects the sticky-session backend. Empty = "auto":
	// "layered" when both [redis] and database.driver=postgres are set,
	// "redis" when only [redis] is set, "postgres" when only postgres
	// is configured, "memory" otherwise.
	SessionStore SessionStoreMode `toml:"session_store"`
}

type RedisConfig added in v0.0.3

type RedisConfig struct {
	URL       string `toml:"url"`        // redis://[:password@]host:port[/db]
	KeyPrefix string `toml:"key_prefix"` // default: "blockyard:"
}

type Secret added in v0.0.2

type Secret struct {
	// contains filtered or unexported fields
}

Secret wraps a secret string. Its String() and GoString() methods return "[REDACTED]" to prevent accidental logging. Use Expose() to retrieve the actual value.

func NewSecret added in v0.0.2

func NewSecret(s string) Secret

func (Secret) Expose added in v0.0.2

func (s Secret) Expose() (string, error)

Expose returns the secret value. It returns an error if the value is an unresolved vault reference (starts with "vault:"), preventing accidental use of the raw reference string as a secret.

func (Secret) GoString added in v0.0.2

func (s Secret) GoString() string

GoString implements fmt.GoStringer for %#v formatting.

func (Secret) IsEmpty added in v0.0.2

func (s Secret) IsEmpty() bool

func (Secret) IsVaultRef added in v0.0.2

func (s Secret) IsVaultRef() bool

IsVaultRef reports whether the secret value is a vault reference (starts with "vault:").

func (Secret) MarshalJSON added in v0.0.2

func (s Secret) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler to prevent secret leakage.

func (Secret) MarshalText added in v0.0.2

func (s Secret) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler to prevent secret leakage.

func (Secret) MustExpose added in v0.0.2

func (s Secret) MustExpose() string

MustExpose returns the secret value, panicking if the value is an unresolved vault reference. Use in tests and contexts where the value is known to be resolved.

func (*Secret) Resolve added in v0.0.2

func (s *Secret) Resolve(ctx context.Context, r SecretResolver) error

Resolve resolves a vault reference. If the value starts with "vault:", it parses the format "vault:{kv_path}#{key}", reads the secret from vault, and replaces the internal value. Non-vault values are left unchanged.

func (*Secret) SetValue added in v0.0.2

func (s *Secret) SetValue(v string)

SetValue replaces the secret's internal value. Used for auto-generated secrets (e.g. session_secret).

func (Secret) String added in v0.0.2

func (s Secret) String() string

func (*Secret) UnmarshalText added in v0.0.2

func (s *Secret) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler so TOML decoding writes the raw string into the Secret wrapper.

type SecretResolver added in v0.0.2

type SecretResolver interface {
	KVRead(ctx context.Context, path string, token string) (map[string]any, error)
	AdminToken() string
}

SecretResolver reads secrets from a vault-compatible KV v2 store. Implemented by integration.Client.

type ServerConfig

type ServerConfig struct {
	Bind               string            `toml:"bind"`
	ManagementBind     string            `toml:"management_bind"` // optional: separate listener for /healthz, /readyz, /metrics
	SessionSecret      *Secret           `toml:"session_secret"`  // required when [oidc] is set
	ExternalURL        string            `toml:"external_url"`
	ShutdownTimeout    Duration          `toml:"shutdown_timeout"`
	DrainTimeout       Duration          `toml:"drain_timeout"`
	LogLevel           string            `toml:"log_level"`            // debug, info, warn, error (default: info)
	TrustedProxies     []string          `toml:"trusted_proxies"`      // CIDRs whose X-Forwarded-For to trust (e.g. ["10.0.0.0/8"])
	Backend            string            `toml:"backend"`              // "docker" (default) or "process"
	SkipPreflight      bool              `toml:"skip_preflight"`       // skip backend-specific preflight checks at startup
	DefaultMemoryLimit string            `toml:"default_memory_limit"` // fallback memory limit for workers (e.g. "2g")
	DefaultCPULimit    float64           `toml:"default_cpu_limit"`    // fallback CPU limit for workers (fractional vCPUs)
	BootstrapToken     string            `toml:"bootstrap_token"`      // dev only: one-time token exchanged for a real PAT via POST /api/v1/bootstrap
	WorkerEnv          map[string]string `toml:"worker_env"`           // extra env vars injected into every worker (e.g. OTEL_EXPORTER_OTLP_ENDPOINT)

	// Deprecated; copied into SkipPreflight by migrateDeprecatedFields and
	// removed in the next release.
	DeprecatedSkipDockerPreflight bool `toml:"skip_docker_preflight"`
}

type ServiceConfig added in v0.0.2

type ServiceConfig struct {
	ID    string `toml:"id"`
	Label string `toml:"label"`
}

ServiceConfig describes a third-party service whose API key users can enroll via the vault (e.g. OpenAI, Posit Connect).

Credentials are stored at: secret/data/users/{sub}/apikeys/{id}

type SessionStoreMode added in v0.0.4

type SessionStoreMode string

SessionStoreMode is the selector for proxy.session_store. Despite the "Session" name, the same value also drives the worker registry, worker map, and process-backend port/UID allocators (see #286, #287, #288, parent #262) — operators rarely want asymmetric durability across these stores, so the resolver below picks one mode for all of them.

const (
	SessionStoreAuto     SessionStoreMode = ""
	SessionStoreMemory   SessionStoreMode = "memory"
	SessionStoreRedis    SessionStoreMode = "redis"
	SessionStorePostgres SessionStoreMode = "postgres"
	SessionStoreLayered  SessionStoreMode = "layered"
)

func ResolveSessionStoreMode added in v0.0.4

func ResolveSessionStoreMode(cfg *Config) SessionStoreMode

ResolveSessionStoreMode picks the shared-state backend. Honours an explicit cfg.Proxy.SessionStore value; otherwise defaults to the "best" available mode given which backends are configured.

  • [redis] + postgres → layered (PG primary, Redis cache)
  • [redis] only → redis
  • postgres only → postgres
  • neither → memory (single-process only)

Lives in the config package so both cmd/blockyard/main.go and the process backend's allocator selection can reach it without importing each other.

type StorageConfig

type StorageConfig struct {
	BundleServerPath    string            `toml:"bundle_server_path"`
	BundleWorkerPath    string            `toml:"bundle_worker_path"`
	BundleRetention     int               `toml:"bundle_retention"`
	MaxBundleSize       int64             `toml:"max_bundle_size"`
	SoftDeleteRetention Duration          `toml:"soft_delete_retention"`
	StoreRetention      Duration          `toml:"store_retention"` // R library cache eviction; 0 = disabled
	DataMounts          []DataMountSource `toml:"data_mounts"`
}

type TelemetryConfig added in v0.0.2

type TelemetryConfig struct {
	MetricsEnabled bool   `toml:"metrics_enabled"` // default: false
	OTLPEndpoint   string `toml:"otlp_endpoint"`   // e.g. http://otel-collector:4317
}

type UpdateConfig added in v0.0.3

type UpdateConfig struct {
	Schedule    string   `toml:"schedule"`     // cron expression; empty = disabled
	Channel     string   `toml:"channel"`      // "stable" (default) or "main"
	WatchPeriod Duration `toml:"watch_period"` // health monitoring after update completes

	// Repo is the GitHub owner/repo to query for releases and the
	// origin/main HEAD comparison (e.g. "cynkra/blockyard"). Empty
	// keeps the upstream default. Operators of forks override this
	// to point the update check at their own repo.
	Repo string `toml:"repo"`

	// AltBindRange is the port range the process orchestrator picks
	// an alternate bind from when spawning the new server during a
	// rolling update. Operator-configured, separate from
	// [process] port_range (worker pool). Default: "8090-8099".
	// Ignored by the Docker variant.
	AltBindRange string `toml:"alt_bind_range"`

	// DrainIdleWait is the maximum time Finish will wait for the
	// local server's session count to reach zero before tearing
	// down. Used by the process orchestrator to let active sessions
	// finish naturally during a rolling-update drain. Default: 5m.
	// Ignored by the Docker variant, which cuts over hard and
	// relies on the reverse proxy to drain in-flight requests.
	DrainIdleWait Duration `toml:"drain_idle_wait"`
}

type VaultConfig added in v0.0.4

type VaultConfig struct {
	Address              string          `toml:"address"`
	AdminToken           Secret          `toml:"admin_token"`       // deprecated: use role_id with AppRole auth
	RoleID               string          `toml:"role_id"`           // AppRole role identifier
	TokenTTL             Duration        `toml:"token_ttl"`         // default: 1h
	JWTAuthPath          string          `toml:"jwt_auth_path"`     // default: "jwt"
	SecretIDFile         string          `toml:"secret_id_file"`    // opt-in: read secret_id from this path at every AppRole login, enabling rotation without restart
	SecretIDWrapped      bool            `toml:"secret_id_wrapped"` // opt-in: treat secret_id_file contents as a response-wrap token to unwrap at login time
	CACert               string          `toml:"ca_cert"`           // path to PEM file; when set, replaces system CA trust for vault HTTP calls
	SkipPolicyScopeCheck bool            `toml:"skip_policy_scope_check"`
	Services             []ServiceConfig `toml:"services"`
}

Jump to

Keyboard shortcuts

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