Commit Graph

1025 Commits

Author SHA1 Message Date
Jose Diaz-Gonzalez
d00a7d741a feat: attach vector container to additional docker networks
Adds a new global `vector-networks` property on the logs plugin that takes a comma-separated list of Docker networks. When set, the rendered compose file declares each network plus `bridge` as external and joins them on the vector service, so `docker compose up` reconciles attachments on every `logs:vector-start`. When unset, the existing `network_mode: bridge` template is preserved unchanged. The value is validated against `docker network inspect` at set time, rejects the reserved `bridge` entry, and is surfaced in `dokku logs:report` via `--logs-vector-global-networks`.
2026-05-12 22:05:50 -04:00
Jose Diaz-Gonzalez
b096d0f131 Merge pull request #8627 from dokku/8619-certs-add-rewrites-explicit-https-443-port-mappings
Preserve explicit https:443 port mappings on cert update
2026-05-12 21:29:47 -04:00
Jose Diaz-Gonzalez
cecd07d914 fix: preserve explicit https:443 port mappings on cert update
The ports plugin's `post-certs-update` trigger was rewriting every `https:443:*` mapping from the app's `http:80:*` mappings, silently overwriting any user-defined mapping such as `https:443:443` used by apps that terminate TLS inside the container. The trigger now skips the rewrite when an `https:443:*` mapping already exists, keeping the default behavior only when the app has no explicit HTTPS mapping configured.

Closes #8619.
2026-05-12 19:02:47 -04:00
Jose Diaz-Gonzalez
436825b782 feat: split caddy report tls-internal into raw, computed, and global
The bare `tls-internal` key previously returned the computed value, so external tooling could not tell whether the property had been set on the app or was merely defaulting to `false`. The property is now also configurable with `--global`, the report exposes `computed-tls-internal` and `global-tls-internal` keys alongside the bare raw key, and the deploy path honors the per-app value with a fallback to the global value before the built-in default. Closes #8625.
2026-05-12 18:54:26 -04:00
Jose Diaz-Gonzalez
b30eb48444 test: isolate scheduler-k3s registry tags per bats file
Parallel `unit.scheduler-k3s-*` matrix jobs all pushed to the same `savant/rdmtestapp:1` tag on Docker Hub, so a herokuish run pod could pull a CNB or dockerfile image that another job had just overwritten and fail with `exec: "/exec": stat /exec: no such file or directory`. The image-repo-template now embeds the bats file basename so each job owns its own tag namespace.
2026-05-12 11:43:58 -04:00
Jose Diaz-Gonzalez
7898f98488 Merge pull request #8615 from dokku/8612-openresty-set-accepts-per-app-writes-for-global-only-properties-silently-follow-up-to-8597
Reject per-app sets for openresty global-only properties
2026-05-12 01:34:57 -04:00
Jose Diaz-Gonzalez
3a36de7349 Merge pull request #8614 from dokku/8611-scheduler-docker-local-report-raw-computed-keys
Split scheduler-docker-local report into raw, computed, and global
2026-05-12 01:29:59 -04:00
Jose Diaz-Gonzalez
4551f258b2 Merge pull request #8613 from dokku/8610-git-report-deploy-branch-keep-git-dir-return-computed-value-at-bare-key-no-raw-per-app-key
Expose raw deploy-branch and keep-git-dir in git:report
2026-05-12 01:29:43 -04:00
Jose Diaz-Gonzalez
ebdd5f2b2f fix: reject per-app sets for openresty global-only properties
`openresty:set <app>` previously accepted per-app writes for properties whose readers only consult the global store, so `:set myapp image foo` printed a success message while `:report myapp` kept showing the global default. The per-app form is now rejected with `The key '<key>' can only be set globally`, matching the behavior introduced for `caddy`, `haproxy`, and `traefik` in #8602.
2026-05-11 22:55:37 -04:00
Jose Diaz-Gonzalez
7d73cf78c4 feat: split scheduler-docker-local report into raw, computed, and global
The bare `init-process` and `parallel-schedule-count` keys previously returned the computed value, so external tooling could not tell whether a property had been set on the app or was merely defaulting. Both properties are now also configurable with `--global`, the report exposes `computed-*` and `global-*` keys alongside the bare raw keys, and the deploy path honors the global value before falling back to the linuxserver.io vendor heuristic.
2026-05-11 22:29:28 -04:00
Jose Diaz-Gonzalez
c45b95fc4d fix: expose raw deploy-branch and keep-git-dir in git:report
The bare `deploy-branch` and `keep-git-dir` keys in `git:report` returned the computed (effective) value rather than the raw per-app value, with no separate `computed-*` key to distinguish "set per-app" from "falling back to global or default". This left external tooling unable to detect a per-app unset without out-of-band state. The bare keys now hold the raw per-app value (empty when unset) and new `computed-deploy-branch` and `computed-keep-git-dir` keys hold the effective value, matching the convention used by `nginx-vhosts`, `network`, and `builder`. Closes #8610.
2026-05-11 22:18:17 -04:00
Jose Diaz-Gonzalez
d0588698f5 test: add scheduler-k3s run parity tests across builders
Extends bats coverage for the scheduler-k3s scheduler so that
herokuish and dockerfile builders match the cnb test surface for
`dokku run`, `dokku run:detached`, `dokku cron:run`, deployment
manifests, cronjob manifests, and Procfile-key resolution. Adds
the corresponding `app-cron-procfile.json` fixture for the python
app and `app-cron.json` / `app-cron-procfile.json` fixtures for
the dockerfile-procfile app.
2026-05-11 12:10:54 -04:00
Jose Diaz-Gonzalez
ff1296859b test: stabilize scheduler-k3s cnb bats tests
Drop the assertion that the web deployment has no command since the python buildpack auto-emits a web Procfile entry, which correctly routes through launcher just like docker-local. Shorten the cron command fixture so the base36-encoded cron-id stays under the 63-byte kubernetes label limit, and relax the `dokku run` and `dokku cron:run` output assertions to `assert_output_contains` so they tolerate the leading blank line emitted on k3s.
2026-05-11 02:05:56 -04:00
Jose Diaz-Gonzalez
3a845f4d14 fix: route CNB images through launcher on scheduler-k3s
Mirror the docker-local fix in #8525 for the k3s scheduler. CNB images default to a `/cnb/process/web` entrypoint that ignores incoming args, so non-web deployments, scheduled cron jobs, and ad-hoc `dokku run` / `cron:run` commands all need an explicit `launcher` entrypoint. The deployment and cron-job helm templates now set `command: [launcher]` when `image.type` is `pack`, and `TriggerSchedulerRun` sets the entrypoint to `launcher` for pack images while finishing the previously stubbed Procfile lookup branch so the resolved command is actually scheduled.
2026-05-11 02:05:56 -04:00
Jose Diaz-Gonzalez
3ddce21aef Merge pull request #8602 from dokku/8597-caddy-haproxy-traefik-accept-per-app-set-but-report-only-returns-global-value 2026-05-11 01:04:14 -04:00
Jose Diaz-Gonzalez
cdce68f8a2 Merge pull request #8601 from dokku/8598-app-json-set-appjson-path-succeeds-but-app-json-appjson-path-is-not-a-valid-report-flag
Rename app-json:report flags to match property
2026-05-10 23:58:05 -04:00
Jose Diaz-Gonzalez
74dc94bad2 Merge pull request #8599 from dokku/dokku-container-healthcheck
Add docker healthcheck to dokku container
2026-05-10 23:50:29 -04:00
Jose Diaz-Gonzalez
822b7dddcd fix: reject per-app sets for global-only proxy properties
`caddy:set`, `haproxy:set`, and `traefik:set` previously accepted per-app writes for properties that only have a single host-wide reader, so `:set myapp image foo:bar` printed a success message while `:report myapp` kept showing the global default. The per-app form is now rejected with `The key '<key>' can only be set globally`, matching the existing rejection used for haproxy `refresh-conf` and traefik `challenge-mode`. Caddy `tls-internal` remains the only legitimate per-app property in this family.
2026-05-10 22:42:57 -04:00
Jose Diaz-Gonzalez
4eee229bbc fix: rename app-json:report flags to match property
The property name set via `app-json:set` is `appjson-path`, but the matching read-back flags on `app-json:report` were named `--app-json-selected`, `--app-json-global-selected`, and `--app-json-computed-selected`. The mismatch meant `dokku app-json:report <app> --app-json-appjson-path` (the form already documented in deployment-tasks.md) was rejected as an invalid flag, and the `--format json` output advertised keys that did not correspond to any settable property. The flags and JSON keys are renamed to `--app-json-appjson-path`, `--app-json-global-appjson-path`, and `--app-json-computed-appjson-path` so that the property name round-trips through set and report.
2026-05-10 22:32:16 -04:00
Jose Diaz-Gonzalez
bd748052a1 fix: report info-flag should not error when app undeployed
Several plugin `:report` subcommands erroneously failed with `not deployed` when an info-flag matched a property that was empty. Empty values are legitimate for configuration properties pre-deploy and the `--format json` path already returns them without error. Remove the `value_exists` check across nginx, checks, git, certs, scheduler-docker-local, and the builder-* plugins so the info-flag form behaves consistently with the JSON form.
2026-05-10 22:15:27 -04:00
Jose Diaz-Gonzalez
2c274217de chore: run shfmt 2026-05-10 21:42:35 -04:00
Jose Diaz-Gonzalez
2a4393a63a test: cover dokku container healthcheck wiring
Adds a bats lint test that guards the static wiring (nginx conf, dokku-restore finish-script ordering, my_init sentinel reset, and the Dockerfile HEALTHCHECK line) plus a docker smoke test that boots the built image, waits for the health flip, exercises the loopback endpoint, asserts the port is not published to the host, and verifies the negative path. The smoke test is invoked via a new `make test-image-healthcheck` target and runs automatically in the build-image action after `docker buildx --load`.
2026-05-10 21:39:43 -04:00
Jose Diaz-Gonzalez
9adf6e5f36 Merge pull request #8593 from dokku/fix-debian-bullseye-ssl-reject-handshake 2026-05-10 16:16:16 -04:00
Jose Diaz-Gonzalez
392ac73d33 fix: gate ssl_reject_handshake behind nginx 1.19.4
The shipped catch-all default site uses `ssl_reject_handshake`, which is unsupported on nginx older than 1.19.4 and causes nginx to fail to start on Debian Bullseye. The postinst now detects the installed nginx version and installs an HTTP-only variant of the catch-all on older systems.
2026-05-09 16:32:30 -04:00
Jose Diaz-Gonzalez
4f4fed7101 test: update apps:rename assertions for quoted git-hook app name
The security fix that quoted `$APP` inside the pre-receive hook heredoc changed the literal hook contents from `dokku git-hook foo` to `dokku git-hook "foo"`, so the existing substring assertions no longer match.
2026-05-09 16:06:27 -04:00
Jose Diaz-Gonzalez
93f87a0f07 fix: restrict app names to prevent command injection
The previous app name validation regex permitted shell metacharacters such as `;`, `$`, backticks, `|`, and `&`. These names were embedded unquoted into the generated git pre-receive hook script, allowing an authenticated user to execute arbitrary commands as the dokku user simply by pushing to a remote with a crafted app name. App names are now restricted to lowercase alphanumerics, dots, and hyphens, and the hook script also quotes the app variable as a defense-in-depth measure.
2026-05-09 16:00:51 -04:00
Jose Diaz-Gonzalez
d00aaf3ff3 Merge pull request #8586 from dokku/assert-output-contains
Count assert_output_contains matches as fixed strings
2026-05-09 16:00:27 -04:00
Jose Diaz-Gonzalez
e78d3bcc78 Merge pull request #8591 from dokku/arbitrary-file-write
Harden archive extraction against symlink traversal
2026-05-09 15:58:31 -04:00
Jose Diaz-Gonzalez
33dd8005dd Merge pull request #8589 from dokku/netrc-permissions 2026-05-09 15:36:10 -04:00
Jose Diaz-Gonzalez
f4213a4bf5 tests: prevent assert_output_contains from aborting on no match
Bats runs tests under `set -eo pipefail`, so when `grep -F -o` finds nothing inside the count pipe it exits 1, the whole pipe fails, errexit fires, and the function aborts before reaching the count comparison. Wrap grep in `{ ... || true; }` so the pipe stays zero when the pattern is absent and the helper falls through to the flunk message.
2026-05-09 13:36:29 -04:00
Jose Diaz-Gonzalez
9decf16ea1 feat: configure archive limits via git properties
Replaces the `DOKKU_ARCHIVE_MAX_SIZE` and `DOKKU_ARCHIVE_MAX_FILES` environment variables with global git properties (`archive-max-size` and `archive-max-files`), configurable via `dokku git:set --global` and surfaced through `dokku git:report --global`. Defaults remain `1073741824` bytes and `10000` entries.
2026-05-09 13:08:23 -04:00
Jose Diaz-Gonzalez
2df0791fcd fix: prevent tar symlink traversal in archive extraction
Archives passed to git:from-archive and certs:add were extracted without symlink or path validation, allowing a crafted archive to write arbitrary files anywhere writable by the dokku user via symlink traversal. Extraction now pre-scans entries for absolute paths, parent traversal, and unsafe symlinks, applies the GNU tar `--no-unsafe-links` flag when available, and validates symlinks after extraction.
2026-05-09 12:54:42 -04:00
Jose Diaz-Gonzalez
6eb8b8632c fix: enforce 0600 permissions on .netrc credentials file
The previous use of `touch` before `netrc set` allowed the file to inherit the umask and be world-readable, exposing stored git credentials to local users. The set and unset paths now explicitly chmod 0600 and chown to the dokku user, and the plugin install hook repairs permissions on already-affected installations.
2026-05-09 12:22:17 -04:00
Jose Diaz-Gonzalez
a70728f61e fix: sanitize openresty include filenames to prevent eval injection
Add defense-in-depth sanitization for OpenResty include files to prevent
OS command injection via malicious filenames that break shell quoting in eval.

- Add filename validation in core-post-extract using regex [^a-zA-Z0-9_.-]
- Validate both http-includes and location-includes paths
- Abort deploy via dokku_log_fail on unsafe filenames
- Skip non-regular files (symlinks, directories) during extraction
- Add security regression test with unsafe filename containing space
- Keep existing guards in docker-args-process-deploy as belt-and-suspenders
- Update documentation to clarify allowed filename characters

Addresses CVSS 9.9 vulnerability where filenames like poc'$(cmd)'x.conf
could escape shell quoting and execute arbitrary commands during deploy.
2026-05-09 12:20:50 -04:00
Jose Diaz-Gonzalez
25abd38387 tests: use /bin/bash -c to execute commands in init tests 2026-05-09 10:48:29 -04:00
Jose Diaz-Gonzalez
38de83eabf tests: use inverted assert
Also echo the status
2026-05-08 21:39:57 -04:00
Jose Diaz-Gonzalez
01268ebad9 tests: fix count 2026-05-08 21:38:22 -04:00
Jose Diaz-Gonzalez
2cf2846c6b test: count assert_output_contains matches as fixed strings
Replace the bash pattern-substitution loop with grep -F -o piped to wc -l so the helper counts literal substring occurrences instead of treating the expected value as a glob pattern. The old implementation interpreted `[`, `]`, `*`, `?`, and `\` as pattern syntax, which made `assert_output_contains "['task.py', 'test']"` report 17 matches against an output that contained the string exactly once - the inner characters were being matched as a character class. assert_output_not_contains delegates to assert_output_contains and is fixed transitively.
2026-05-08 18:56:33 -04:00
Jose Diaz-Gonzalez
5d212f3195 test: use BATS_TEST_TMPDIR in core-post-extract regression tests
The previous form set `trap "rm -rf '$TMP_DIR'" RETURN` inside the test, but bats propagates `RETURN` traps to nested function calls, so the trap fired on the first `assert_success` and removed the work directory before the trigger script ran. Switching to bats's per-test `BATS_TEST_TMPDIR` removes the trap entirely and lets bats handle cleanup.
2026-05-08 01:34:05 -04:00
Jose Diaz-Gonzalez
bc8adfa6e2 test: add run_plugn_trigger and run_plugin_script bats helpers
Both helpers wrap `run /bin/bash -c "..."` with the env vars dokku plugin scripts and `plugn` need, replacing the long inline boilerplate that was duplicated across `tests/unit/resource_3.bats` and the new `core-post-extract` regression tests in the builder bats files.
2026-05-07 12:47:00 -04:00
Jose Diaz-Gonzalez
eb17a383c6 fix: reference SOURCECODE_WORK_DIR in builder core-post-extract
The builder-dockerfile, builder-lambda, builder-nixpacks, builder-pack and builder-railpack `core-post-extract` triggers assigned `$2` to a local `SOURCECODE_WORK_DIR` but called `pushd "$TMP_WORK_DIR"`, which was unset. Bash 5.2 silently accepted `pushd ""`, so the bug stayed dormant. Bash 5.3 (shipped with Ubuntu 26.04) makes it a hard error and `set -e` aborts the trigger, causing every `git push` to fail with `pushd: null directory`.
2026-05-07 12:39:46 -04:00
Jose Diaz-Gonzalez
f0a4a7fc29 chore: remove now invalid tests 2026-05-04 13:16:28 -04:00
Jose Diaz-Gonzalez
49dc1c1e64 fix: correct the assertion 2026-05-04 09:30:00 -04:00
Jose Diaz-Gonzalez
964c0fc4e9 fix: source property-functions where fn-plugin-property-* helpers are used
The release_and_deploy function and several proxy plugin scripts call fn-plugin-property-* helpers without sourcing `plugins/common/property-functions`, producing `command not found` errors during deploys. Source the helpers from `plugins/common/functions` and from each proxy plugin entry point that consumes them.
2026-05-04 06:11:22 -04:00
Jose Diaz-Gonzalez
31ce5a7c48 fix: install cnb pack from github releases instead of ppa
The ppa:cncf-buildpacks/pack-cli launchpad source is currently down, breaking the runtime image build and any bats run that calls install_pack. Pack is now tracked in contrib/dependencies.json and pulled from the buildpacks/pack GitHub release tarball, matching how other binary deps are managed. update-deb-dependencies gains hyphen-aware word-boundary matching so single-word names like pack cannot accidentally rewrite unrelated debian/control lines, keeping pack out of the package's hard requirements.
2026-05-02 09:12:46 -04:00
Jose Diaz-Gonzalez
179d09fdd5 fix: chown migrated legacy storage entries to dokku
`SaveEntry` and `touchMigrationFlag` wrote files via `os.WriteFile` and `os.Create` and never chowned them, so the install-time legacy-mount migration produced root-owned `legacy-*.json` files in `/var/lib/dokku/data/storage-registry/entries/`. The dokku user that runs `ps:rebuild` could not read them and every rebuild on a 0.37.x to 0.38.0 upgrade failed with permission denied. The companion `repairRegistryOwnership` pass in `TriggerInstall` rewrites ownership across the whole registry tree so installs that already ran the buggy code are fixed on the next package upgrade, since the per-app migration flag would otherwise cause `MigrateLegacyMounts` to skip the broken files forever.
2026-05-02 05:37:11 -04:00
Jose Diaz-Gonzalez
60fe2400a9 fix: openresty bats global-flag test uses settable key
The previous regression case selected `--openresty-global-hsts`, but `hsts` is rejected by `openresty:set --global` because it is not in the plugin's GLOBAL_KEYS list. Switch to `--openresty-letsencrypt-server`, which the bats setup already pins to a known staging URL, so the test exercises the same `--global --<info-flag>` parsing path without needing a separate set step.
2026-05-01 04:02:26 -04:00
Jose Diaz-Gonzalez
e8d8b0683a fix: preserve info flag in plugin reports with --global
The argument-handling block in each plugin's report command overwrote APP with --global before checking whether $1 actually held an info flag, so `dokku <plugin>:report --global --<plugin>-foo` always emitted the full report instead of the requested value. Reorder the conditionals across the sixteen plugins that share the pattern so the info-flag check runs first, and add a regression bats case for each one.
2026-04-30 21:05:46 -04:00
Jose Diaz-Gonzalez
53ef8c7780 fix: deflake haproxy bats tests
The byjg/easy-haproxy image polls Docker for label changes every 10
seconds by default, which races with the haproxy bats suite and
intermittently produces curl exit 7. Expose `refresh-conf` as a
global-only haproxy property that maps to `EASYHAPROXY_REFRESH_CONF`,
lower it to 2 seconds in the bats setup, and wrap the localhost HTTP
assertions in a retry loop so checks wait for haproxy to converge
rather than failing on the first attempt.
2026-04-30 18:40:57 -04:00
Jose Diaz-Gonzalez
dc5b9cc883 test: relax ssl_certificate occurrence count in nginx-vhosts_16 2026-04-30 17:30:03 -04:00