Configuration
gbb-server -config PATH and gbb build --local --config PATH load YAML; their default is configs/config.yaml. Supported GBB_ environment overrides take precedence over file values. The server's -addr flag overrides its configured listen address.
The example configuration (configs/config.example.yaml in the repo) documents the baseline settings. The exact environment mapping is in internal/config/config.go (internal/config/config.go in the repo); names are explicitly mapped, so do not infer them mechanically from YAML nesting.
Essential settings
| Setting | Purpose |
|---|---|
addr / GBB_ADDR |
API listen address, normally :8080 |
data_dir / GBB_DATA_DIR |
Persistent workspaces, caches, logs, and filesystem artifacts |
database.dsn / GBB_DATABASE_DSN |
PostgreSQL catalog, jobs, and operational state; or describe it in parts (see below) |
redis.url / GBB_HUMAN_REDIS_URL |
Anonymous verification and shared abuse counters; only used in public mode |
godot_repo |
Default engine repository; catalog rows can select a fork |
build.image_prefix / GBB_IMAGE_PREFIX |
Prefix matching the toolchain image tags; registry-qualified to pull them |
build.image_tag / GBB_IMAGE_TAG |
Tag those images carry, latest locally or the vX.Y.Z a release published |
build.registry.server / GBB_BUILD_REGISTRY_SERVER |
Registry the pull credential is for |
build.registry.username / GBB_BUILD_REGISTRY_USERNAME |
Account for that pull; empty pulls anonymously |
build.registry.password / GBB_BUILD_REGISTRY_PASSWORD |
Token for it; prefer password_file |
build.registry.password_file / GBB_BUILD_REGISTRY_PASSWORD_FILE |
Path to a mounted token, which wins over the inline value |
build.workspace_mount / GBB_WORKSPACE_MOUNT |
Workspace mount strategy; use bind with shared absolute paths |
artifacts.backend / GBB_ARTIFACT_BACKEND |
fs for local storage, s3 for object storage |
auth.cookie_secure / GBB_COOKIE_SECURE |
Secure attribute for legacy browser sessions |
docker.host / DOCKER_HOST |
Docker-compatible endpoint; an explicit configured host wins |
Toolchain images
build.image_prefix is concatenated with linux:<tag>, windows:<tag> or
macos:<tag>, so it ends in the separator: gbb/ names the images a local
make images builds, and git.picklemustard.dev/studioteal/gbb- names the ones
a release publishes.
build.image_tag is worth pinning rather than leaving on latest. An image is
pulled only when it is not already present, so a tag that never changes is
fetched once and then kept indefinitely -- a floating latest means a deployed
sidecar keeps whichever toolchain it happened to see first. scripts/release.sh
rewrites this in deploy/k8s/configmap.yaml on every release.
build.registry is how the Docker daemon authenticates that pull. It is not the
cluster's imagePullSecret: that one covers the kubelet fetching the pod's own
containers, while this covers a pull the daemon makes on the server's behalf,
which travels as a header on the Engine API request. dockerd reads no
config.json of its own, so a private registry needs this and is otherwise
unreachable from a build. Leave it empty for locally built images or a public
registry.
Capacity and leases
build.workers controls concurrent builds. build.jobs controls SCons parallelism per build; zero uses all available cores. build.memory and build.cpus constrain each compiler container. Start with one worker and size memory for linking as well as compilation.
build.timeout bounds a build. build.queue_capacity bounds waiting work in the legacy queue. Anonymous admission has its own durable queue and per-IP limits.
build.lease, heartbeat_interval, poll_interval, and max_attempts control worker ownership and retry after a lost lease. Heartbeats must be shorter than the lease. A lease measures worker liveness, not the maximum compilation duration.
build.ccache_volume names the compiler cache. A Docker named workspace volume does not automatically receive files assembled on the API filesystem. For the deployed dind arrangement, both containers must share /data, with bind mode configured.
Precedence
Four layers, lowest first, applied uniformly to every setting:
built-in defaults < the YAML file < GBB_ environment < a *_file field
The environment sits above the file because it is the last thing a deployment
can change without editing a ConfigMap. A *_file field sits above the
environment because the path is normally written in the YAML while the contents
come from a volume the YAML cannot see: a mounted secret that lost to an inline
value would be pointless. The two are different keys, so there is no circularity
— GBB_DATABASE_PASSWORD_FILE sets the path, and the file's contents then win
over GBB_DATABASE_PASSWORD.
Unknown keys are rejected. A misspelled setting fails at startup rather than being silently ignored.
Connections: one string, or parts
database and redis each accept either a whole connection string (dsn,
url) or discrete fields (host, port, user, name/db, password,
sslmode). Setting both forms is refused rather than silently resolved, because
a connection string is used whole and its parts cannot be overridden
individually.
Prefer the discrete form when a password contains @ / ? # : or %. Those are
percent-escaped for you, where a hand-written string quietly parses as a
different host. database.params carries any libpq keyword the schema does not
name, so nothing is lost by not writing the string yourself.
A composed database connection defaults to port 5432 and sslmode: require. A
local instance with no certificate needs sslmode: disable, or connecting fails
with an error about TLS rather than about the setting.
Secrets from files
Every credential has a *_file sibling that reads it from a mounted path:
database.dsn_file, database.password_file, redis.url_file,
redis.password_file, and access_key_id_file / secret_access_key_file /
session_token_file under the S3 blocks. Trailing newlines are trimmed, so both
echo secret > file and a projected Kubernetes Secret work. A file that cannot
be read is fatal at startup: continuing with an empty credential produces an
authentication failure against the right host with the wrong secret, which is
the least diagnosable outcome available.
Inline password: values in the file are accepted for development. The deployed
config is a ConfigMap, so do not use them there.
Storage and credentials
For S3, configure endpoint, bucket, region, prefix, and path-style addressing as required by your store. Create the bucket before starting the server. Supply GBB_S3_ACCESS_KEY_ID and GBB_S3_SECRET_ACCESS_KEY through the environment or deployment secrets, or mount them and set secret_access_key_file.
Temporary credentials add session_token. A deployment that already mounts ~/.aws can set profile (with credentials_files / config_files to override the search paths) instead of static keys; static keys win where both are given, so setting both is refused. signing_region signs as a region other than the bucket's own, for a store that demands a particular one. A store on a private certificate authority sets tls.ca_bundle_path, which is added to the system roots rather than replacing them; tls.cert_file and tls.key_file supply a client certificate for mTLS.
Legacy delivery can redirect to presigned URLs or proxy through the API. Anonymous delivery streams privately; the separate gateway uses its own read-only S3 credential and database role. See gateway configuration; it accepts the same database, redis, and s3 blocks through its own -config file, and still reads its historical environment variables.
Private module cloning uses modules.ssh_key_path and modules.known_hosts_path. Keep the private key readable only by the intended identity and verify host keys. Compiler containers do not perform repository authentication themselves.
Public service settings
Anonymous mode requires GBB_HUMAN_ENABLED=true, GBB_PUBLIC_ORIGIN, GBB_TURNSTILE_SITE_KEY, GBB_TURNSTILE_SECRET, a configured Redis, explicit GBB_HUMAN_TRUSTED_PROXIES, and GBB_ADMIN_GROUP.
Redis is the redis: block. GBB_HUMAN_REDIS_URL remains the supported way to supply it and is what existing deployments use; GBB_REDIS_URL is the same setting under the block's own name and wins if both are set. The discrete fields (redis.host, redis.user, redis.password_file, redis.db, redis.tls.*) are the alternative, and redis.db is how two deployments share one instance, since the key prefixes are fixed.
The origin must be HTTPS with no path, query, or fragment. Trusted proxy entries are whitespace-separated CIDRs for immediate ingress peers. Redis must support the shared verification and enforcement scripts. Public request settings must agree across API and gateway replicas.
GBB_DOWNLOAD_GATEWAY_ENABLED=true disables the API's old download delivery path at gateway cutover. Set it only with ingress routing configured. See Security and Deployment and operations.
Retention
retention.artifacts: "0s" keeps artifacts indefinitely. Nonzero retention stamps a deadline when a build succeeds; shortening the configuration does not retroactively shorten existing deadlines. Log retention is separate and uses file modification time. Audit retention, collector interval, and batch size are independently configurable.
Keep real configuration and credentials out of version control. Commit example values only.
Guide
- Home
- Getting Started
- Building Godot
- Configuration
- Modules and Administration
- API
- Architecture
- Deployment and Operations
- Security
- Troubleshooting
- Development
Reference
- API
- Architecture
- Modules
- Module registry
- Admin
- Artifacts
- Deployment
- Kubernetes execution
- Durable execution store
- Immutable build configuration
- Download gateway
- Public logs
- Anonymous verification
- Abuse enforcement
- Public service remediation
- Authelia administration
- CI/CD
- macOS SDK