Environments
Every app has a production environment. You can add more, deploy to them by name, and give them
their own config vars. Each environment is served from its own hostname, so a preview build never
takes over production traffic.
The model
Section titled “The model”An environment is a named deployment target belonging to one app. Environments share the app’s image, its build, and its app-wide config vars; what differs is:
- Which deployment is live. Each environment has its own live deployment, so deploying a preview does not retire the production containers.
- Which containers serve it. The proxy pools only the running web containers of that environment. A preview container is never added to the production upstream.
- Which hostname it answers on. Production keeps the app’s domains. Every other environment gets a generated hostname.
- Which config var values it receives. An override shadows the app-wide value inside one environment and nowhere else.
Generated hostnames
Section titled “Generated hostnames”Production is served on the domains you add with deku domains add. Every other environment is
served on:
<app>-<slug>.<global_domain>For an app named demo with a staging environment and global_domain = "apps.test", that is
demo-staging.apps.test. The hostname is derived, not stored, so renaming the app or changing
global_domain changes it on the next reconcile.
An app with no domain of its own is served at <app>-production.<global_domain> as well, so
that production has a stable hostname instead of only the per-deployment URLs that change with
every deploy. Adding a domain switches production back to it and drops the generated hostname.
Two consequences worth knowing:
-
Environments need a
global_domainin the daemon config (deku setupprompts for it) to be reachable. Without it there is no name to route on, so Deku writes no vhost for them.global_domain = "apps.test" -
Generated hostnames are served over HTTP unless automatic certificates are configured, which obtains one wildcard certificate covering all of them. An app’s own domains are covered by that app’s certificate either way.
All of an app’s vhosts live in one <app>.conf. The file is per app rather than per hostname
because <app>-<slug> has the same shape as an app name: an app called demo-staging and the
staging environment of demo would otherwise collide.
Deploying to an environment
Section titled “Deploying to an environment”deku deploy run demo # productiondeku deploy run demo --environment staging # the staging environmentdeku deploy rollback demo # rolls back within the target's environmentThe same applies over the API: environment is a field on the deploy body, and a query parameter
on the archive upload.
An unknown environment fails the request before the deploy starts, naming the slugs that do exist, rather than accepting the deploy and failing later.
A rollback re-deploys the environment the deployment it targets belongs to. Rolling back a production deployment cannot silently deploy into whichever environment happens to hold the newest deployment.
Preview URLs
Section titled “Preview URLs”Every retained deployment is reachable at a hostname of its own:
<app>-<slug>-<shortid>.<global_domain>Production is spelled out (<app>-production-...) like any other environment, even though its
stable hostname is the app’s own domains.
deku deploy run demo --environment staging prints the environment’s URL and the build’s own URL.
The build URL serves that exact deployment, so it keeps working after a later deploy replaces it,
until the deployment falls out of the retention window.
Retention
Section titled “Retention”An environment’s recent deployments stay running so their URLs keep working:
[previews]keep_deployments = 3 # per environment, counting the live oneA deploy keeps the live deployment plus the newest keep_deployments - 1 before it, and retires
anything older after the retire grace period. Set it to 1 to keep only the live deployment, whose
URL then goes dark when the next deploy replaces it.
Each retained deployment holds its own containers, so raising this number costs memory and ports per environment. Lowering it takes effect on the next deploy.
Hostnames are derived, not stored: a URL resolves only while its containers are retained, and its
vhost is removed when they are retired, so an expired URL stops resolving rather than failing
through the proxy. deku deploy list <app> shows the URL for each deployment that is currently
reachable and - for the rest.
Config overrides
Section titled “Config overrides”An app-wide config var is inherited by every environment:
deku config set demo GREETING=helloAdding --environment writes an override that applies inside that environment only:
deku config set demo GREETING=preview --environment stagingdeku config list demo --environment staging # shows the effective set, overrides markeddeku config unset demo GREETING --environment staging # removes the override, keeps the app-wide valueconfig list without --environment shows the app-wide values. With it, each row reports where its
value came from: an inherited app-wide value or an environment override. Overrides are encrypted at
rest exactly like app-wide values when an encryption key is configured.
Overrides reach the container on the next deploy: config vars are injected when the environment’s deployment starts, so a redeploy is needed for a change to take effect.
Managing environments
Section titled “Managing environments”deku env list demodeku env create demo Staging --slug staging --branch maindeku env remove demo stagingThe slug is derived from the name unless you pass --slug, and it must be lowercase letters,
digits, and -. --branch records the git ref the environment tracks; it is metadata today and is
not wired to automatic deploys.
production cannot be removed.
Current limits
Section titled “Current limits”- Generated hostnames, including per-deployment URLs, are HTTP-only until a wildcard certificate covers them, as described above.
git pushdeploys to production. Branch-to-environment mapping is not wired up.- Authentication, maintenance mode, and redirects are app-scoped: they apply to every environment’s vhost, not per environment.