Files
dokku/docs/appendices/0.38.0-migration-guide.md
Jose Diaz-Gonzalez 8282981361 feat: accept --global on :report subcommands
Every `:report` subcommand now recognizes `--global` as a scope selector that limits the report to globally-configured properties, including in JSON form via `--global --format json`. Previously this combination was rejected because `--global` was treated as an info flag, conflicting with `--format`. The shared `common.ParseReportArgs` helper now returns a `ReportArgs` struct exposing the parsed scope; each Go and bash report selects a global-only flag map when scope is global, and skips per-app verification.
2026-04-29 10:30:59 -04:00

4.6 KiB

0.38.0 Migration Guide

Changes

  • Dokku now generates a minimal nginx configuration for apps without running web processes (undeployed apps, apps with no web process type, or apps with stopped web processes). This configuration returns 502 Bad Gateway responses, ensuring the app's domain resolves and monitoring tools can detect non-200 status codes. The configuration is automatically replaced with the full proxy configuration once the app is deployed with running web processes. See the nginx documentation for more details.

  • Users with custom nginx.conf.sigil templates that reference DOKKU_APP_WEB_LISTENERS should be aware that this variable may now be empty when the template is rendered for apps without running web processes. Custom templates should handle this case gracefully, for example by using a conditional to serve an error page instead of proxying:

    location / {
    {{ if $.DOKKU_APP_WEB_LISTENERS }}
      proxy_pass  http://{{ $.APP }}-{{ $upstream_port }};
    {{ else }}
      return 502;
    {{ end }}
    }
    
  • The path on disk to both the global ENV file and app ENV files have been moved. Users should reference environment variables via the provided plugin triggers rather than directly sourcing the ENV files. Existing ENV files are left untouched and will be removed on the subsequent Dokku install.

  • During a fresh apt install, the upstream nginx default vhost files (/etc/nginx/sites-enabled/default, /etc/nginx/sites-available/default, and /etc/nginx/conf.d/default.conf) are renamed to ${path}.dokku-disabled (not deleted) to avoid a duplicate default server for 0.0.0.0:80 error. Operators with local customizations can recover them by inspecting the .dokku-disabled siblings. Upgrade-in-place installs do not touch any existing nginx files.

  • Fresh apt installs now ship a catch-all default site at /etc/nginx/conf.d/00-default-vhost.conf that rejects requests with unknown Host headers using ssl_reject_handshake on (HTTPS) and return 444 (HTTP). This replaces the manual workaround previously documented in the nginx docs. The behavior can be opted out at install time via the dokku/install_default_site debconf prompt. See the Default site documentation.

  • The docker-local scheduler now sends SIGTERM to old containers immediately after a successful deploy, rather than waiting wait-to-retire seconds before signaling. This matches Heroku's graceful-shutdown contract and lets applications begin draining in-flight work as soon as proxy traffic switches. The wait-to-retire grace period and stop-timeout-seconds hard-stop continue to apply as before. See the zero downtime deploys documentation for more details.

  • The docker-local scheduler no longer queues an image for retirement when another running container of the same app still uses it. This fixes the case where a ps:rebuild against an image-based deploy (git:from-image) produced an identical-SHA image and the dokku-retire cron timer would log Image ... has running containers, skipping rm on every run. Stuck entries from prior versions are pruned automatically on the next ps:retire run.

  • All :report subcommands now accept the --global flag, which scopes the report to globally-configured properties. The flag composes with --format json, so a JSON report of global properties can be obtained via, for example, dokku scheduler:report --global --format json. Previously, combining --global with --format json was rejected with an "info flag" error, and --global on its own was treated as an unknown flag.

TLS handshake behavior change

With the new catch-all installed, an HTTPS request to a hostname that matches a configured dokku app but where the app has no TLS certificate configured will have its TLS handshake rejected by the catch-all (via ssl_reject_handshake on). Previously, nginx fell through to the lexicographically first port-443 server block and presented that block's certificate, producing a cert-mismatch error on the client. The new behavior is a correctness improvement, but operators who deliberately relied on the old fall-through certificate (for monitoring probes, for example) need to either configure a certificate for the target app or remove the catch-all on that host. Existing apps that already have certificates configured are unaffected: nginx selects the right server block via SNI before TLS completion, so the catch-all is never consulted for legitimate requests.