Documentation
¶
Index ¶
- Constants
- func ParseLogLevel(s string) slog.Level
- func ResolveSecrets(ctx context.Context, cfg *Config, resolver SecretResolver) error
- type AuditConfig
- type Config
- type DataMountSource
- type DatabaseConfig
- type DockerConfig
- type Duration
- type OidcConfig
- type OpenbaoConfigdeprecated
- type ProcessConfig
- type ProxyConfig
- type RedisConfig
- type Secret
- func (s Secret) Expose() (string, error)
- func (s Secret) GoString() string
- func (s Secret) IsEmpty() bool
- func (s Secret) IsVaultRef() bool
- func (s Secret) MarshalJSON() ([]byte, error)
- func (s Secret) MarshalText() ([]byte, error)
- func (s Secret) MustExpose() string
- func (s *Secret) Resolve(ctx context.Context, r SecretResolver) error
- func (s *Secret) SetValue(v string)
- func (s Secret) String() string
- func (s *Secret) UnmarshalText(text []byte) error
- type SecretResolver
- type ServerConfig
- type ServiceConfig
- type SessionStoreMode
- type StorageConfig
- type TelemetryConfig
- type UpdateConfig
- type VaultConfig
Constants ¶
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
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:"-"`
}
type DataMountSource ¶ added in v0.0.3
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 ¶
Duration wraps time.Duration for TOML deserialization from strings like "30s", "5m", "1h".
func (*Duration) UnmarshalText ¶
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 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 (Secret) Expose ¶ added in v0.0.2
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) IsVaultRef ¶ added in v0.0.2
IsVaultRef reports whether the secret value is a vault reference (starts with "vault:").
func (Secret) MarshalJSON ¶ added in v0.0.2
MarshalJSON implements json.Marshaler to prevent secret leakage.
func (Secret) MarshalText ¶ added in v0.0.2
MarshalText implements encoding.TextMarshaler to prevent secret leakage.
func (Secret) MustExpose ¶ added in v0.0.2
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
SetValue replaces the secret's internal value. Used for auto-generated secrets (e.g. session_secret).
func (*Secret) UnmarshalText ¶ added in v0.0.2
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
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"`
}