Fadebox 1.4
The 1.4 line: fadebox/fadebox:1.4 follows its newest release, and the
1.4 docs describe every release on it. Moving between releases is covered in
Upgrading.
1.4.5 — 2026-10-07
This release makes the editors for environment variables and injected files easier to read and harder to get wrong. Nothing about how Fadebox deploys changes.
Environment variables are edited in a code editor. A service's overrides, an environment's
shared variables and an instance's variables used to be plain text boxes. Keys and comments are
now coloured, and typing {{ offers the placeholders you can use there, including the
environment's own services. A line the deploy would ignore, a key set twice and an unusual
variable name are flagged under their line. A line that overrides a value from the template or the
shared variables says which value it replaces, and the inherited variables left alone are listed
under the editor. An instance's variables take only literal values, so a {{ there is flagged
before you save.
Injected files are highlighted by type. The file editor used to highlight YAML only. It now also highlights JSON, SQL, XML, TOML, shell scripts, env- and ini-style config and nginx config, and marks placeholders in all of them. See the spec editor for how a file's type is told. The catalog shows an entry's Compose and files with the same highlighting, and the file editor now uses the height of its drawer.
Upgrade notes. None.
The fadebox/fadebox:1.4 image follows this release; pull it.
1.4.4 — 2026-10-06
This release fixes a leak in the MCP endpoint that could take a whole installation down. It also corrects what some assistant tools tell an agent about your data.
Heavy MCP use no longer exhausts the database connections. Some tool calls kept a database
connection after they had answered. The most common was get_instance_logs for a service with no
container yet, which is what an agent does while it watches a deploy come up. Each such call kept
its connection for good. Once enough of them had done so, every request to Fadebox failed with
Unable to acquire JDBC Connection until Fadebox was restarted, the web interface and the ingress
included. Every tool call now hands its connection back when it answers.
Tool descriptions say what deleting and moving do to data. delete_instance told the agent it
removed the instance's volumes. On a static runtime it keeps them, and reset_instance is what
wipes an instance's data. On an elastic runtime, deleting an instance or moving it to another
runtime destroys its machine, disk included. The descriptions now say so, and move_instance is
marked destructive, so a client asks you before it moves an instance.
Stateless MCP requests without clientInfo are accepted. The protocol makes it optional, and
a request that left it out used to fail.
Upgrade notes. None.
The fadebox/fadebox:1.4 image follows this release; pull it.
1.4.3 — 2026-10-05
This release is a hardening pass that came out of a review of 1.4. Most of it changes nothing you will notice. It closes ways a project, an account or a page served on an instance could reach further than it should, and fixes places where Fadebox reported a failure badly or left something behind. The most significant fixes are below. The rest are smaller corrections across the server, the web interface and the CLI.
A page on an instance can no longer act as the person viewing it. Instances usually share a
site with Fadebox (fadebox.example.com and *.envs.example.com), so the browser sent a
visitor's Fadebox session along with requests that a page on an instance made. Such a page could
deploy or reset an instance, or approve an OAuth consent, as whoever opened it. Fadebox now
refuses a change that carries a session cookie unless it comes from Fadebox's own pages, and no
other page may show Fadebox in a frame. API keys, OAuth tokens, the CLI and MCP clients send no
session cookie and are not affected.
A private image stays with the projects that can pull it. An image already on a runtime could be deployed by any project that named it, so a project without a registry login could run another project's private image. When a project holds a login for an image's registry, each project that deploys the image now pulls it first. If the registry refuses that project, its deploy fails instead of using the copy already on the runtime.
Deleting an environment or a project no longer leaves instances running for nobody. Such a
delete used to leave the instances' containers running and free their URLs while the ingress
still routed them. It is now refused with instances_have_containers (409) while any instance
under it still has containers, and the refusal names the instances to stop first. Deleting a
single instance already followed this rule. The web interface also asks before it deletes an
instance or removes a service. Both used to happen on one click.
Accounts, keys and connected applications.
- Settings → API Keys now lists your connected applications: the MCP clients and other OAuth applications you have approved. You can revoke any of them there. The consent page now leads with the host it will send you back to.
- On the Free tier, reactivating an account now counts against the user cap, as creating one does.
- A service account that holds API keys but has no role in any project can no longer be given a role in another project, and only administrators manage such accounts.
- The CLI sends a context's token only to that context's server. A
--urlorFADEBOX_URLthat pointed elsewhere used to receive it. Such an override now needs its own token.
Runtimes.
- A runtime given only part of its TLS material (CA certificate, client certificate, client key)
was connected to without TLS, and nothing said so. Creating or updating one is now refused with
runtime_tls_incomplete, which names what is missing. - When a runtime's Docker daemon cannot be reached, Fadebox now answers
runtime_unreachable(503) and names the runtime. It used to fail with a 500, which sent the web interface to its error page. - Image reclaim's minimum age now counts from when Fadebox first saw an image, not from when the image was built. A deploy's images are also held from before its pull, so a freshly pulled image can no longer be reclaimed from under a deploy.
Upgrade notes.
- No migration, and no setting you have to add, with one exception. Users may open Fadebox over
plain
http://on an address other than localhost, through a proxy that does not pass the originalHoston. If they do, setFADEBOX_PUBLIC_URLto that address, or every change made from the web interface is refused. Over https, or through a proxy that keeps theHostor forwards it, there is nothing to do. See Reverse proxy. - Fadebox can no longer be embedded in a frame on another page.
- A script that deletes an environment or a project has to stop its instances first.
- A remote runtime saved earlier with only part of its TLS material is still connected to without TLS until you complete the set or clear it. Check your remote runtimes.
- The shipped compose file no longer publishes Postgres on the host's port 5432. An existing
installation keeps its own compose file. If you take the new one, reach the database through
the container:
docker compose exec db psql -U fadebox fadebox. - Update the CLI to get its token fix; see Install.
The fadebox/fadebox:1.4 image follows this release; pull it.
1.4.2 — 2026-10-01
This release closes the gaps in one rule 1.4.1 introduced: a published port cannot sit on the same
host as a gated instance's URLs. 1.4.1 checked the rule just before a deploy started, and three
cases got past that check. Each is now refused like the rest, with ingress_host_port_conflict
(409).
Two deploys at the same moment. A gated deploy and a deploy that publishes a port on the same host could each pass the check before the other was recorded, and both landed. The rule is now checked again as each deploy is recorded, one at a time per host, so the later of the two is refused.
A redeploy that closes the gate. The URLs an instance already had stayed marked open until its redeploy finished, and a port deployed in that window landed beside them. An instance now counts as gated from the moment a deploy with its gate closed starts. A gate closed while a deploy is already under way counts too: it refuses a neighbour's port until that deploy ends, although the gate itself still waits for the next deploy, as before.
An elastic instance whose gate was closed while its machine started. Its deploy had been
checked with the gate open, and nothing looked at its front's published ports again. They are
now checked once the machine is ready, before any container starts. If a port is there, the
instance ends in ERROR with the refusal's message, and its machine is stopped.
See Gated instances and published ports.
Upgrade notes. None: no migration, no setting, nothing new on the API, and the CLI is unchanged. If one of these cases let a port land beside a gated instance on 1.4.1, the two are still there after the upgrade, and the next deploy of either one is refused. Move one of them to another runtime, drop the port, or open the gate.
The fadebox/fadebox:1.4 image follows this release; pull it.
1.4.1 — 2026-09-30
This release narrows who a gated instance lets in, from anyone with a Fadebox account to the people in its project. It also closes several ways a sign-in could reach the wrong place, and fixes about forty places where two copies of the same rule had drifted apart. Most of those rules now live in one place, so they cannot drift again.
A gate says who gets in, not just whether you sign in. Require sign-in was on or off, and a gated instance let in anyone with a Fadebox account. An instance's Access is now one of three levels:
- Open: anyone who can reach the URL.
- Members: the project's members, meaning anyone with a role in it, and administrators.
- Creator: the instance's creator while they are a member of the project, the project's editors, and administrators.
Someone signed in but not admitted lands on a page that names the project and says whom to ask. An environment's New instances setting picks the level its instances start at. A change between Members and Creator applies to new sign-ins at once; a session admitted before it lasts until its cookie expires, which for a gated instance is now at most an hour. Opening or closing the gate still applies on the instance's next deploy, as before.
Raising the level stays with whoever may operate the instance. Lowering it takes the
editor role, and so does creating an instance below its environment's default. In the CLI,
--gate open|members|creator works on instance create and up. instance gate <slug> closes an
instance to its project's members, or to its creator with --creator. --gated, --ungated and
instance ungate work as before; neither instance gate nor --gated lowers a gate already set
to Creator. An administrator gets through every gate, and when the level would have refused
them, the admission is audited as ingress.admin_admitted. A pipeline's access token (fadebox instance token) passes the same
check, so a deployer who is neither the creator nor an editor gets no token for a Creator
instance. See Requiring a sign-in and
Letting a pipeline through.
Sign-ins stay where they were meant to go.
- The sign-in cookie of a gated instance is now tied to that instance. A new instance that takes over a deleted one's address no longer accepts the old one's cookies.
- The redirect back after signing in only goes to the scheme and port the ingress actually serves the instance on.
- A published port can no longer sit on the same host as a gated instance. A browser sends the
sign-in cookie to every port of the host, so such a port would receive it. On a static runtime,
a deploy that would put a published port, fixed or picked by Docker, on the same host as a gated
instance's URLs is refused with
ingress_host_port_conflict, whichever of the two comes second. Closing the gate of an instance whose own services publish a port, or creating one closed, is refused the same way. The refusal never names another project's instance, nor its service or port. An elastic runtime's own machines are not affected. See Gated instances and published ports. - Accounts are looked up unambiguously. Restoring a session, and changing your own password, find the account by its username only. A username that happened to equal another account's email could reach that account's roles or password. Signing in by email works only when one account has that address. Linking an OIDC sign-in by verified email does the same, and refuses an address that only deactivated accounts hold. A new OIDC account's username never takes another account's email. See Account linking.
Security updates in the platform. Quarkus moves to 3.40.1. It brings Hibernate ORM 7.4.9,
fixing CVE-2026-77874 (Fadebox never calls the affected HQL JSON functions), and a fix for
security path matching on wildcard permissions. Its Elytron fixes CVE-2026-19611 by changing how
passwords are normalized before they are hashed; see the upgrade notes. A proxy named by hostname
in QUARKUS_HTTP_PROXY_TRUSTED_PROXIES no longer leaks a network socket on every request.
The CLI:
- It prints the server's message instead of the raw JSON of the error.
- Usage mistakes exit with
2, as documented. That includes malformed--tag,--varand--linkvalues, which no longer print a Java class name. --waitpolls over one connection instead of opening a new one each time.- Expiry times print in your shell's time zone.
template listsays when it stopped at the server's page limit.instance tokenno longer blames the runtime for an instance that needs no token.- A malformed server URL says
Invalid server URLinstead of printing a Java exception. instance getlines up its Not applied value with the other fields.
The web interface:
- A refusal to extend or move an instance reads correctly, with the right way through.
- Project API keys show how long they have left and flag an expired one, as personal keys already did.
- ⌘K no longer lists administrator pages to people who are not administrators.
- The environment composer no longer submits a runtime that was disabled while the form was open.
- The dashboard and machine views follow the 12- or 24-hour clock setting.
- Relative times read the same everywhere ("3 minutes ago").
- Every audit action can be filtered on.
- A new template's slug is checked like every other slug.
- A provisioner field renders the same on the account and profile forms: a list of options as a choice, a secret hidden, even when it offers options.
- A git reference with spaces around its file or JSON path shows the path trimmed, the way the server reads it.
- A template with one service no longer offers a one-option Service picker for its files.
- A refused environment delete says what failed, with the server's reason beneath.
- When creating an environment fails partway, the project list still counts the environment that was created.
Deploy and templates:
- A Compose export of a template with no main service now matches what the deploy runs. It no
longer points
depends_onat a service the file does not declare, or fails outright. It also refuses container names that differ only in case, as the deploy does. - Retagging an image pinned by digest (
app@sha256:…) now works. A{{git:…}}image tag whose file path contains/no longer breaks the retag. - Template validation warns about network and volume settings Fadebox does not apply: a volume driver or its options, a non-bridge network, network aliases. It never refuses them.
- A deploy onto a disabled runtime is refused with
runtime_unavailable, naming the runtimes you can use, as create and move already were. - An image named
DOCKER.IO/…goes through the registry mirror as Docker Hub, in any letter case. FADEBOX_PUBLIC_URLmay carry surrounding spaces or a trailing slash.- A server whose JVM runs in a Turkish locale reads
service_healthycorrectly. - Template validation no longer warns that an image is unpinned when its tag is a
{{git:…}}placeholder whose file path contains/. - A truncated log's marker writes its size with a decimal point, whatever the server's locale.
The API:
- A page far past the end of a listing is empty, with the real total, instead of wrapping around to the first page or failing.
- The audit listing falls back to newest first for a
?sort=field it does not know, and breaks ties newest first underoccurredAt,descas well.
Elastic runtimes:
- Test connection reports a refused account with the same sentence the machines page shows, instead of "failed unexpectedly (NullPointerException)".
- An empty optional field in the account form is left out instead of stored and refused later.
- A refused stop whose instance is wanted running again is no longer flagged Refused. Retrying it no longer shortens the instance's start timeout.
FADEBOX_RUNTIME_USAGE_SWEEP_INTERVALin the short form (2m) now also sizes each pass, asPT2Malways did.
SSO and the assistant:
- An
email_verifiedclaim sent as the string"true"now counts for account linking, as it already did for required claims. - The built-in authorization server for MCP clients names itself on every authorization response, including refusals, and says so in its metadata (RFC 9207).
GET /api/meshows the email for API-key and OAuth sessions.- The assistant's
resolve_git_valueoffers a{{git:…}}placeholder only when a deploy can read it.
Upgrade notes.
- A gated instance now admits only its project's members. One migration,
V025, turns every gated instance, and every environment whose new instances start gated, into Members; nothing becomes Creator. A colleague who opened a gated URL without a role in its project is refused after the upgrade: give themvieweron the project, or a group that has it (see Who gets which role). The old on/off columns are kept in step, so going back to 1.4.0 keeps every closed gate closed. - Visitors of gated instances sign in again once, after each instance's next deploy. Their browser does it for them if they are signed in to Fadebox.
- Behind a reverse proxy, if the proxy serves the ingress on another port and the runtime's Public port is not set, the redirect back after signing in is refused. The message names the address to set. See Custom ports and reverse proxies.
- A published port beside a gated instance on the same static runtime makes the next deploy of either one refused. Move one of them to another runtime, drop the port, or open the gate.
- Some local passwords need a reset. A password set on 1.4.0 or earlier that contains a
character the old normalization rewrote no longer signs in: superscripts such as
²,µ,º, or the fullwidth letters some input methods type. An administrator resets it (see Passwords); failed attempts count toward the login lockout until then. Plain ASCII and ordinary accented letters (ö,é) are unaffected, and so are OIDC accounts and API keys. - Signing in by an email two accounts share no longer works; sign in by username.
- The CLI. Download it again from the upgraded server for the gate levels and the fixed error
output. A 1.4.0 CLI keeps working. Scripts that read
instance get's text findGate: open|members|creatorwhere they foundGated: yes/no;-o jsononly gains fields. - On the API, instances carry
gate(OPEN,MEMBERSorCREATOR) besidegated, and environments carryinstanceGatebesidegatedInstances.gated: truefrom an older client means at least members and never lowers a gate. New refusals:instance_gate_restricted(403),instance_access_denied(403) andingress_host_port_conflict(409). A deploy onto a disabled runtime answersruntime_unavailable.
The fadebox/fadebox:1.4 image follows this release; pull it. No setting is new or required.
1.4.0 — 2026-09-27
This release is about where an instance runs. Until now every instance shared a Docker host an admin had built beforehand. An instance can now get a virtual machine of its own, made when it deploys and switched off when it stops. Beside that, the sign-in gate moves from the runtime to the instance, and an OIDC provider can say who may sign in through it.
Elastic runtimes: a machine per instance, on Google Compute Engine. An elastic runtime holds a
cloud account instead of a Docker host. Deploying an instance onto it creates a machine at the
provider and deploys onto that machine once it is ready. Stopping the instance switches the
machine off and keeps its disk, so the next deploy starts with the images already pulled. A reset
keeps the machine and wipes the volumes, and deleting or moving the instance destroys the
machine. While the machine comes up the instance reads PROVISIONING, which survives a
restart of Fadebox, and a machine log narrates the boot step by step: on the card, in the log
pane, and in fadebox instance up --wait. The first deploy is minutes rather than seconds, and the
concepts page weighs that before anything else.
- Sizes are the admin's. A runtime offers named machine profiles (machine type, disk, spot or not, a public address or none), one of them the default. An environment can name one as its Machine profile.
- Machines need no image of your own. A profile boots the published Fadebox runtime image unless it names another. The image contract and a reference Packer template are in the setup guide for an image you build yourself.
- Each machine is locked down at boot. It gets a certificate authority of its own for its Docker daemon, a host firewall that admits only Fadebox and the front, and no route from containers to the metadata service. Once the machine is ready, the boot document, which holds that CA's key, is removed from the provider's metadata.
- Instance URLs come from a front. A machine has no DNS name and no certificate, so its instance URLs are served by a front: a static runtime with an ingress domain and the managed ingress stack. The front forwards each hostname to the machine over mutual TLS. The runtime form can create the front and install its stack on the spot.
- Admins can see and clean up what is billing. The machines view lists every machine, what
it is doing and what needs attention. A pass compares the rows with what the cloud account
actually holds, and a machine Fadebox lost track of can be reclaimed from there.
Stopped-machine retention, set per runtime, gives up a disk nobody came back for, and the
instance card counts down to it.
fadebox runtime machineslists the machines too. - Every tier has it. A runtime counts as one runtime, and its machines are bounded by the
per-runtime instance cap. On Free the front can be the disabled
local.
See Elastic runtimes and Setting up an elastic runtime, whose Compute Engine section lists the one-time prerequisites in the project.
The sign-in gate belongs to the instance. Require Fadebox sign-in used to be a switch on the
runtime, so every instance on a host was either behind a sign-in or open. Each instance now has
its own Require sign-in: the internal tool can be closed and the customer demo beside it open.
An environment's Instances require sign-in sets what new instances start as. Whoever may
operate an instance can change it afterwards, from the card's More menu or with
fadebox instance gate / ungate, and instance up --gated gates before it deploys. A change
applies on the next deploy, and until then the card and instance list show what is in force
(open → gated). Changes are audited as instance.gate_changed. See
Requiring a sign-in.
An OIDC provider can say who may sign in. A provider now takes required claims: rules on
the ID token, such as a Google Workspace domain (hd), an email suffix, an Entra tenant (tid) or
a group, that are checked before any account is created or linked. A rule on email also requires
email_verified. Someone the rules refuse lands back on the sign-in page with a message, and the
refusal is audited as user.login_refused, naming the claim and never its value. See
Required claims.
The ingress stack reports whether it is reaching Fadebox. Every managed ingress stack now asks
Fadebox for the routes of the elastic runtimes it fronts, and a stack that fronts nothing gets an
empty answer. Fadebox works out where the stack should call from FADEBOX_PUBLIC_URL, or from the
runtime's daemon when that is unset. Where it can tell that the address it worked out cannot work,
it refuses to install or update the stack rather than leave it broken. This covers a
containerized Fadebox with a remote daemon, a loopback address, and Fadebox listening on loopback
only. Where it cannot tell in advance, the runtime's Ingress dialog shows whether the stack is
polling (OK, Waiting or Stale). The dialog also says why an instance there cannot require
a sign-in, and what fixes it. A container of another installation holding one of the stack's names
is now refused with ingress_stack_foreign (409) instead of an error. See
How the stack reaches Fadebox.
The instance card leads with one action. The card shows the one action its state calls for: Deploy, Redeploy, Stop or Cancel. Reset, Extend, Describe, overrides, Move, the verdict, sharing, the sign-in gate and Delete sit behind More. An action you may not use stays in the menu, greyed out, and names whom to ask.
The CLI reads states it does not know. A CLI shows a state its release does not know as
unknown and waits through it instead of failing. That only helps with the next new state:
PROVISIONING arrived in this release, so a 1.3 CLI fails on elastic instances. See the upgrade
notes.
Upgrade notes. Eleven migrations run on start, V014 to V024. Most of them only add the
elastic-runtime tables and columns, and every runtime you have stays a static one. Three change
what you will see:
- Sign-in gates. The per-runtime sign-in switch becomes each instance's own (
V014,V024). Every instance on a runtime that required a sign-in stays gated. Instances require sign-in is turned on for every environment whose project could deploy onto such a runtime, whatever instances it has now. Where new instances should start open, an editor turns it off. The runtime switch is gone: an API call that still sendsingressAuth: truefor a runtime is refused with a400rather than leaving the runtime open. Turning the gate on for an instance is refused withoutFADEBOX_PUBLIC_URL, as the gate always needed it. - Managed ingress stacks. Every managed ingress stack shows outdated once, because each
stack now polls Fadebox; press Update in each runtime's Ingress dialog. The pinned
traefik:v3.7andtecnativa/docker-socket-proxy:v0.5.0images are unchanged. If Fadebox runs in a container and a static runtime's daemon is remote (tcp://), or Fadebox listens on a loopback address only, setFADEBOX_PUBLIC_URLfirst to an address the runtime's host can reach. Until it is set, Update is refused and the dialog says why. If you publish Fadebox on aFADEBOX_PORTother than 8080, setFADEBOX_PUBLIC_URLtoo, or the stack's poll reads Stale. - The CLI. Download the CLI again from the upgraded server: a 1.3 CLI fails on the
PROVISIONINGstate of instances on elastic runtimes (see Download the CLI again).
In the compose file, change the image line to fadebox/fadebox:1.4. The
installation file gains only a comment on the ports line, and no variable is new or
required. The new settings are the seven FADEBOX_MACHINE_* cadences,
FADEBOX_EGRESS_ECHO_URL and FADEBOX_MACHINES_GCP_DEFAULT_IMAGE, all under
Elastic machines. Their defaults cost one query per
pass on an installation without an elastic runtime.
For API clients:
- Runtimes carry
placement(STATICorELASTIC) and, on an elastic one, anelasticblock.GET /api/provisionerslists the providers this build carries (gcp).PUT/DELETE /api/runtimes/{name}/profiles/{profile}define the sizes.GET /api/runtimes/{name}/machines,…/machines/findings,POST …/machines/reconcile,…/machines/reclaimand…/machines/{machine}/retryare the fleet. - The ingress stack status carries
applyRefused,pollandgateUnavailable. - Instances gain the
PROVISIONINGstatus,gated, amachineblock andmachineExpiredAt.PUT …/instances/{slug}/gatechanges the gate, andGET …/instances/{slug}/machine/logreads the machine log. - Environments gain
gatedInstancesandmachineProfile. - OIDC providers gain
requiredClaims.
A client that fails on an instance status it does not know has to learn PROVISIONING before it
meets an elastic runtime.