Skip to main content
Version: 1.4

Configuration reference

Fadebox is configured with environment variables on the app container. Everything here has a working default except the two encryption keys, which the app refuses to start without.

Each variable is the uppercased, underscore form of an underlying property — fadebox.git.cache-dir is FADEBOX_GIT_CACHE_DIR. Durations are ISO-8601 (PT30S, PT5M) unless noted.

Most of what an operator actually configures — runtimes, ingress domains, identity providers, users, groups — is not here. Those are managed in the UI and stored in the database.

Required​

VariableNotes
QUARKUS_HTTP_AUTH_SESSION_ENCRYPTION_KEYEncrypts the session cookie. At least 16 characters; generate with openssl rand -base64 32. Startup fails without it. Changing it signs everyone out.
FADEBOX_ENCRYPTION_KEYEncrypts stored credentials at rest — see Secrets at rest. At least 16 characters; generate with openssl rand -base64 32. Startup fails without it. Deliberately a different secret than the session key: changing it makes every stored credential unreadable until re-entered, so keep it stable and back it up.
QUARKUS_DATASOURCE_JDBC_URLe.g. jdbc:postgresql://db:5432/fadebox.
QUARKUS_DATASOURCE_USERNAME / QUARKUS_DATASOURCE_PASSWORDDatabase credentials. The schema is created and migrated on startup.

General​

VariableDefaultWhat it does
FADEBOX_PUBLIC_URL(unset)The address users open this installation on. Required for the ingress sign-in flow, which sends a visitor of a gated instance URL here to sign in; a gate cannot be turned on without it. When set, it is also where every managed ingress stack reaches Fadebox, so it must not be a loopback address. Unset, a stack works that address out from its daemon, and installing or updating a stack is refused where that cannot work: Fadebox in a container with a remote (tcp://) runtime — the shipped compose file with a remote static runtime — or Fadebox listening on a loopback address only. Set it then, and also when NAT, a port-forward or Fadebox published on a port other than 8080 makes the worked-out address wrong; the stack's poll status shows that case. Set, it always wins and nothing is probed.
FADEBOX_DOCKER_HOSTunix:///var/run/docker.sockThe daemon the seeded local runtime points at. Additional runtimes are configured in the UI, not here.
FADEBOX_SECURITY_BOOTSTRAP_ADMIN_ENABLEDtrueCreates the admin account with a generated password, logged once, when it is missing. Turn off once you manage accounts another way.

The server's time zone does not matter. Every timestamp is stored and served as an instant — a moment with its offset spelled out — so nothing a viewer sees, and no expiry countdown, depends on the zone the process happens to run in. The only thing that zone reaches is the log output: set TZ on the container if you want logs to read in local time rather than UTC.

Sessions​

How long a signed-in browser session survives without a request — see Sessions. Both values state the same thirty minutes on purpose, so the browser stops presenting the cookie exactly when the server stops accepting it; change them together or not at all.

VariableDefaultWhat it does
QUARKUS_HTTP_AUTH_FORM_TIMEOUTPT30MThe idle expiry the server enforces, slid forward by any request more than a minute after the last one.
QUARKUS_HTTP_AUTH_FORM_COOKIE_MAX_AGEPT30MHow long the browser keeps presenting the cookie. Shorter than the timeout and a session ends early; longer and an idle tab returns a 401 on a cookie the server has already written off.

Single sign-on sessions are held to the same thirty minutes, renewed with the provider behind the scenes — but that window is fixed, not read from these variables, and is bounded by the provider's own session policy. Lengthening the form window therefore lengthens only the form window.

Sign-in hardening​

Two limits on guessing a credential — see Guessing is expensive. Neither changes what a refused caller sees: a locked or throttled attempt answers exactly as a wrong password does, and the audit log is where the difference is written.

VariableDefaultWhat it does
FADEBOX_AUTH_LOCKOUT_THRESHOLD5Consecutive failed sign-ins that lock a password account. 0 switches locking off, for an installation whose WAF already does this.
FADEBOX_AUTH_LOCKOUT_WINDOWPT1MHow long the lock holds. Flat, not escalating, and every lock costs a fresh threshold of failures — raising it buys brute-force resistance and sells availability in the same proportion, since a stranger who knows a username can hold the account shut for as long as they keep failing.
FADEBOX_AUTH_THROTTLE_BURST10Failed credential checks — sign-ins, API keys, agent tokens — one client address may make before it is refused without lookup. Per node, forgotten on restart. 0 switches it off.
FADEBOX_AUTH_THROTTLE_PER_MINUTE10How fast that allowance refills.

The throttle keys on the address that opened the connection, not on a forwarded one, until QUARKUS_HTTP_PROXY_TRUSTED_PROXIES below names the proxy — an address a caller can write in a header is not a rate-limit key. Behind a proxy that leaves every client sharing the proxy's one bucket, which is one more reason to set it.

Reverse proxy​

Fadebox serves plain HTTP and expects a TLS-terminating proxy in front of it. It honours X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-For so that the session cookie is marked Secure, sign-in redirects keep the browser's scheme and host, and the audit log records the real client address. Forwarding itself is on by default and needs no variable — what it needs is a proxy that actually sends the headers. See the Reverse proxy guide for what to send and for worked Traefik and HAProxy configurations.

VariableDefaultWhat it does
QUARKUS_HTTP_PROXY_TRUSTED_PROXIES(unset)The proxy's own address (IP or CIDR, comma-separated). Unset, every peer is trusted: anything that can reach the HTTP port by another route can choose the scheme and host Fadebox advertises and the client address it writes to the audit log. Set it whenever the port is reachable other than through the proxy — with 8080 published, it generally is. Fadebox logs a warning at startup while this is unset.
QUARKUS_HTTP_PROXY_ENABLE_FORWARDED_PREFIXfalseTurn on only when Fadebox is mounted under a sub-path rather than at the root, and have the proxy send X-Forwarded-Prefix.
QUARKUS_HTTP_PROXY_PROXY_ADDRESS_FORWARDINGtrueWhether the forwarding headers are honoured at all. Turn it off only when nothing sits in front of Fadebox — with it off the server reads the socket, so no header can influence what it says about itself.

Deploys​

VariableDefaultWhat it does
FADEBOX_DEPLOY_POOL_SIZE4How many deploys run concurrently across the whole installation.
FADEBOX_DEPLOY_START_CONCURRENCY4How many services within one deploy may start at once (pull, create, health wait). Parallel pulls can saturate a daemon's disk or network, so lower it on a constrained host; 1 makes starts fully sequential.
FADEBOX_DEPLOY_READY_TIMEOUTPT5MCeiling on waiting for readiness — both the per-wave waits and the final aggregation.
FADEBOX_DEPLOY_CANCEL_GRACEPT30SHow long a cancel waits for the interrupted deploy worker to return before tearing containers down anyway, so teardown cannot race a worker still creating them.

System images​

The images Fadebox pins for itself — the managed ingress stack — pull from Docker Hub as shipped. An air-gapped installation mirrors them into a registry its runtime hosts can reach and points Fadebox at it with one prefix, normally set on Administration → System. This variable is the same setting for an installation provisioned before anyone signs in; the page shows it as the value in force until an admin saves one there.

VariableDefaultWhat it does
FADEBOX_IMAGE_REGISTRY(unset)A registry prefix, not a URL — registry.corp:5000/mirror — prepended verbatim to each pinned reference, so traefik:v3.7 is pulled as registry.corp:5000/mirror/traefik:v3.7. A value saved on the System page overrides it until reset; unset with nothing saved means the pins as shipped. Covers Fadebox's own images only — what your templates name is never rewritten. Read at the next ingress install, no restart.

Egress proxy​

The reverse proxy section above is about traffic arriving. This one is about traffic leaving. On a network that only reaches the outside through a proxy, Fadebox has five outbound paths — the OIDC discovery probe, the OIDC client's own calls (discovery, JWKS, the code exchange), git, the elastic runtime form's address echo, and the Google Compute Engine provider's calls to Google for an elastic runtime — and they read one setting between them, credentials included.

VariableDefaultWhat it does
QUARKUS_PROXY_HOST(unset)The proxy's host name. Unset means nothing is proxied, which is the default and the only behaviour an installation without a proxy sees.
QUARKUS_PROXY_PORT3128Applies only when a host is set.
QUARKUS_PROXY_USERNAME / QUARKUS_PROXY_PASSWORD(unset)For a proxy that authenticates.
QUARKUS_PROXY_NON_PROXY_HOSTS(unset)Hosts to reach directly, comma-separated, with * allowed at either end of a pattern — *.internal,10.*.

Setting the host is the whole answer; the rest are refinements. A proxy that asks for Basic credentials needs one more thing for git and for Compute Engine, which both reach their hosts through an HTTPS tunnel: the JVM refuses to send Basic credentials through a tunnel unless it is told otherwise, and Fadebox leaves that default alone. Set JAVA_OPTS_APPEND=-Djdk.http.auth.tunneling.disabledSchemes= on the app container if your proxy wants Basic. Without it, Compute Engine calls fail with a sentence naming the proxy, not the service-account key. One caveat worth knowing: the OIDC client takes a proxy per identity provider and has no notion of exceptions, so a provider whose issuer matches non-proxy-hosts is simply built without a proxy rather than being asked to bypass one.

The managed ingress stack inherits the setting. With a host set, installing the stack on a runtime starts its Traefik container with HTTP_PROXY, HTTPS_PROXY and NO_PROXY, so a Let's Encrypt certificate can be issued from a proxied network — see TLS. NO_PROXY keeps the socket proxy and the private address ranges direct, because Traefik reaches its backends through the same setting, and then carries QUARKUS_PROXY_NON_PROXY_HOSTS in the form Traefik reads: exact hosts, addresses, CIDR blocks and *.suffix patterns as they are, a 10.*-style prefix as the CIDR block it means, and any other wildcard dropped with a warning in the server log. A daemon whose bridge networks lie outside the private ranges (100.64.0.0/10) needs that block listed there too. Re-apply the stack after changing the proxy; pulling the stack's images through one is the daemon's own configuration.

Instance expiry​

Every deploy stamps an instance with an expiry and a sweep stops what has run out — see expiry. The lifetime itself is set per environment; these two are the installation-wide default and the sweep's cadence.

VariableDefaultWhat it does
FADEBOX_INSTANCE_DEFAULT_TTLP7DThe lifetime environments that set none of their own inherit. PT0S turns the default off, so those instances never expire — an environment with a lifetime of its own still expires.
FADEBOX_INSTANCE_EXPIRY_SWEEP_INTERVALPT1MHow often the sweep runs, and so how closely a stop follows the expiry. Also the delay before the first sweep after a restart.

Instance health​

How fadebox keeps each running instance's health current — see that section. Health is derived from the daemon and held in memory, not stored, so nothing here needs a database and a restart simply re-reads. The daemon's event stream does most of the work; the sweep is the safety net behind it.

VariableDefaultWhat it does
FADEBOX_INSTANCE_HEALTH_EVENTS_ENABLEDtrueSubscribe to each runtime's Docker event stream, so a container dying updates health within a second or two instead of at the next sweep. Set to false to rely on the sweep alone.
FADEBOX_INSTANCE_HEALTH_SWEEP_INTERVALPT5MHow often the backing sweep re-reads every runtime — the net that catches what the event stream can't (a container that died while fadebox was down, a stream that is down, a runtime added late). Set to off to stop the timer; opening an instance's status and the runtime's Refresh instances button still observe on demand.
FADEBOX_INSTANCE_HEALTH_SWEEP_DELAYPT5SThe delay before the first sweep after a restart, kept off the startup path so an unreachable runtime cannot hold up boot.

Runtime usage​

How fadebox keeps what each runtime is costing current. Like health, it is read from the daemon and held in memory rather than stored, so nothing here needs a database and a restart simply re-reads. Two passes, because the daemon charges very differently for them: CPU and memory are cheap, and disk makes it walk every image layer and volume on the host.

VariableDefaultWhat it does
FADEBOX_RUNTIME_USAGE_SWEEP_INTERVALPT1MHow often CPU and memory are re-read for every managed container. This is also the window CPU is averaged over, since the figure is the change between two readings, and the time one pass may take: containers not read by then are skipped until the next pass, and the server log says how many. Takes the short form (2m) as well. Set to off to stop collecting: every usage figure then reads as unknown, and the bars and columns show a dash.
FADEBOX_RUNTIME_USAGE_SWEEP_DELAYPT15SThe delay before the first pass after a restart, kept off the startup path so an unreachable runtime cannot hold up boot.
FADEBOX_RUNTIME_DISK_SWEEP_INTERVALPT15MHow often the daemon is asked what it is storing — image, container and volume totals, and each instance's own volumes. Rare on purpose: the daemon walks every layer to answer, which takes seconds on a busy host. Set to off and the disk figures stay empty; the CPU and memory ones are unaffected.

Both passes read every enabled runtime concurrently, so one slow or unreachable daemon delays only its own figures, and both bound how many calls they make at once — a runtime serving hundreds of stats requests is a runtime that has stopped serving deploys.

The Prometheus exporter publishes these same readings, so these two intervals are also how fresh a scrape can be. It is switched on in Administration → System, not here — it is an application setting rather than a variable, because an admin flips it without a restart.

Image reclaim​

The one knob behind removing unused images. Retention itself is a per-runtime setting in the UI, not a variable, because a laptop and an air-gapped host want different answers.

VariableDefaultWhat it does
FADEBOX_RUNTIME_IMAGE_MINIMUM_AGEPT5MHow old an image must be before any door or the retention timer may remove it. It exists so a reclaim cannot take the image a deploy has just pulled but not yet created a container from. Raise it on a host where pulls are slow; there is little reason to lower it.

Elastic machines​

How Fadebox moves the virtual machines of an elastic runtime along — created on deploy, switched off on stop, destroyed on delete. A periodic pass does that rather than a worker parked on the deploy, which is what lets an instance keep waiting across a restart. How long a stopped machine keeps its disk is the runtime's own setting, not a variable. Most of the variables below are cadences, and an installation with no elastic runtime pays a single query per pass for all of them; the last two are Detect's echo service and the default boot image.

VariableDefaultWhat it does
FADEBOX_MACHINE_SWEEP_INTERVALPT10SHow often each machine's state is moved one step toward what was asked of it — ask the provider for a machine, poll for an address, ping the daemon it booted, ready. Also how long a waiting deploy sits between steps, which is why it is seconds. Do not set it to off where elastic runtimes exist: machines would keep billing with nothing left to advance or destroy them.
FADEBOX_MACHINE_PROVISION_TIMEOUTPT15MHow long a machine may spend on one step of coming up — being asked for, booting, or coming back after a stop. Past it the waiting instance goes to ERROR with what the machine was waiting for. Per step, so a machine that is slow at each one but keeps finishing them is not failed; what this ends is a step that stopped moving. It is also how long a stop or destroy the provider accepted is waited on: past it, a machine the provider still reports as up is flagged REFUSED and the call is made again after FADEBOX_MACHINE_REFUSED_RETRY_INTERVAL. Raise it for an image that takes a long time to boot. There is no off — a machine nothing gives up on is an instance waiting for ever.
FADEBOX_MACHINE_READY_CHECK_INTERVALPT1MHow often machines that are already up are asked about, which is the only way a spot machine the cloud reclaimed, or one stopped in the provider's console, is ever noticed. At most fifty per scan, oldest first and continuing where the last scan stopped, so a large fleet costs a bounded number of provider calls.
FADEBOX_MACHINE_RETENTION_CHECK_INTERVALPT1HHow often switched-off machines are checked against their runtime's stopped-machine retention. Only the cadence: once an hour is already far finer than a retention measured in days. At most fifty are given up per scan.
FADEBOX_MACHINE_REFUSED_RETRY_INTERVALPT5MHow long a machine whose stop or destroy the provider refused — or accepted and did not carry out within FADEBOX_MACHINE_PROVISION_TIMEOUT — is left alone before that call is made again — otherwise a refusal that retrying will not fix would be six calls a minute for ever. Neither call is ever escalated into destroying the machine. A transient refusal is not this; that is retried on the very next pass. Raise it on a provider that rate-limits hard; there is no off, because a machine nothing asks about again is a bill nobody ends.
FADEBOX_MACHINE_RECONCILE_INTERVALPT10MHow often each elastic runtime's machines are listed at the provider and compared with Fadebox's rows — one listing per runtime, never one per machine. The pass attaches a lost handle back and reports everything else; nothing is destroyed by it. off stops the periodic pass, and asking for one on demand still works. Never gated on the licence.
FADEBOX_MACHINE_RECONCILE_GRACEPT10MHow young a machine at the provider may be and still not be reported as an orphan. A machine exists at the provider for a moment before Fadebox has finished recording that it does, so without this every deploy in progress would read as a leak. It is also what a reclaim refuses a machine for being younger than, so what a pass hides and what will not be destroyed are one rule. It bounds orphans only: a machine belonging to another installation is reported whatever its age, and a provider that cannot say how old a machine is gets it reported with the note ageUnknown rather than hidden for ever — and a reclaim then asks for that one to be confirmed by hand.
FADEBOX_EGRESS_ECHO_URLhttps://api4.ipify.orgThe echo service the elastic runtime form's Detect asks for this installation's public address — what machines reached across the internet see Fadebox coming from. Asked only when an admin clicks, through the egress proxy if there is one, and never on the server's own initiative. The echo must answer with the address itself: a redirect is not followed, and an answer longer than an address is refused; the default answers over IPv4 only, the family a machine's firewall is written for. A machine on the same network as Fadebox sees an internal address instead, and that one the provisioner reports without any of this — on Google, from the metadata server of the Compute Engine VM Fadebox runs on. Set it empty to disable the echo (an air-gapped installation has nothing to ask); Detect then offers only what the provisioner knows.
FADEBOX_MACHINES_GCP_DEFAULT_IMAGEprojects/fadebox/global/images/family/fadebox-runtimeThe boot image of every Google Compute Engine machine profile that names none. The default is the Fadebox runtime image, public to every authenticated Google account; an organisation that enforces constraints/compute.trustedImageProjects has to trust projects/fadebox first. Point it at your own image or family to move every such profile at once — an air-gapped installation, or one whose policy will not trust an outside project. A profile that names its own image still boots that one. Set it empty for no default: every profile then has to name its image, and one that does not is refused when it is saved.

Log export​

Caps for the instance log download, counted on raw bytes before zip compression. Docker cannot report a log's size in advance, so the export is scoped and capped rather than size-checked: a breached cap cuts that entry with a visible marker instead of failing the download.

VariableDefaultWhat it does
FADEBOX_LOGS_EXPORT_DEFAULT_TAIL100000Lines per container when the request does not say — the recent end, which is the useful one.
FADEBOX_LOGS_EXPORT_MAX_CONTAINER_BYTES64MCeiling for one container's entry.
FADEBOX_LOGS_EXPORT_MAX_TOTAL_BYTES256MCeiling for the whole archive, allocated fairly across its containers.
FADEBOX_LOGS_EXPORT_MAX_CONCURRENT2Simultaneous exports; each holds a worker thread and a daemon read for the whole download. Requests beyond it get a 429.

The same scope and caps bound the log a stop or reset captures before removing the containers: one rule for how much of a log Fadebox will ever move, one truncation marker to recognise.

VariableDefaultWhat it does
FADEBOX_LOGS_CAPTURE_DIR~/.fadebox/logsWhere captured logs are written, one directory per instance and deploy attempt, created owner-only. The bundled Compose file sets /data/logs, on the same volume as the git cache: state Fadebox owns and can lose. Wiping it loses the captures and nothing else — every reader then says there is no capture. Not worth backing up.
FADEBOX_LOGS_CAPTURE_READ_TIMEOUTPT2MThe most a capture may add to a stop, for all of its containers together. A runtime that stops answering mid-read costs that service its capture; the stop carries on.

Git value sources​

See Git value sources.

VariableDefaultWhat it does
FADEBOX_GIT_CACHE_DIR~/.fadebox/gitBare-clone cache making fetches incremental. Keep it on a volume — the shipped compose file does. It is an optimization only: an unreachable remote fails the deploy rather than serving stale content.
FADEBOX_GIT_FETCH_TIMEOUTPT30SCeiling on each remote operation.
FADEBOX_GIT_ALLOWED_URL_SCHEMEShttpsSchemes a repository URL may use. Deliberately narrow: this is the layer that actually opens the URL, and file:// would read the app container's own filesystem.

Single sign-on​

Providers themselves are database rows managed in the UI — see OIDC single sign-on. Only these two are environment variables.

VariableDefaultWhat it does
FADEBOX_SECURITY_OIDC_REGISTRY_REFRESH_INTERVAL60sHow stale a provider edit made on another app instance may be here. A write on this instance applies immediately. Also the pickup interval for a row inserted straight into the database.
FADEBOX_SECURITY_OIDC_ALLOWED_ISSUER_SCHEMEShttpsSchemes an admin-supplied issuer URL may use. The server fetches the discovery document from it, so it is an outbound-request surface even though only a global admin can set one.

:::info Removed variables

QUARKUS_OIDC_TENANT_ENABLED, QUARKUS_OIDC_AUTH_SERVER_URL, QUARKUS_OIDC_CLIENT_ID, QUARKUS_OIDC_CREDENTIALS_SECRET, FADEBOX_SECURITY_OIDC_PROVIDER_NAME and FADEBOX_SECURITY_OIDC_AUTO_PROVISION configured the old single-provider SSO. They no longer exist — providers are managed at runtime instead. Delete them from your compose file.

:::

Audit log​

Enterprise

Recording follows the license's Enterprise entitlement — there is deliberately no on/off switch here. See Audit log.

VariableDefaultWhat it does
FADEBOX_AUDIT_LOG_MIRRORfalseAdditionally emits every recorded event as one JSON line on the fadebox.audit logger, for shipping to a SIEM through the log pipeline. The database remains the source of truth.
FADEBOX_AUDIT_RETENTION(unset)How long events are kept; unset keeps them forever. When set (ISO-8601, e.g. P365D), older events are purged — and the purge records its own audit.purged event on every tier, so the log never shrinks silently. Deliberately configuration-only, with no UI.
FADEBOX_AUDIT_RETENTION_SWEEP_INTERVALPT1HHow often the retention purge runs, when retention is set.

Licensing​

Normally the license is pasted in Administration → License and stored in the database — see Licensing. The first two exist for infrastructure-as-code installs; a pasted license takes precedence over either.

VariableDefaultWhat it does
FADEBOX_LICENSE(unset)The license token itself. Unset means the Free tier.
FADEBOX_LICENSE_PATH(unset)Path to a file holding the token (e.g. a compose secret). Setting both variables fails startup, as does a path that cannot be read.
FADEBOX_LICENSE_STORE_URLhttps://store.fadebox.ioWhere the License page's Upgrade to Team and Upgrade to Enterprise links point. The links are composed in the browser and opened only when clicked; the server never calls the store. Leave it alone unless support tells you otherwise.

Secrets at rest​

Registry passwords, git repository tokens, runtime mTLS client keys, ACME DNS credentials and OIDC client secrets are write-only against the API — accepted on save, never returned — and encrypted in the database (AES-256-GCM) under FADEBOX_ENCRYPTION_KEY, so a database dump or backup does not leak them. User passwords and API keys are hashed, not encrypted.

Two things this does not change: the key lives on the app host, so a full compromise of that host still yields the credentials — the encryption protects the database, its backups, and SQL-level access, not the host itself. And losing the key means losing the stored credentials: they cannot be read back out, only re-entered. Back the key up alongside the database.