From 748b66f669e787d451a47c689eaaa27797e9ab95 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Sun, 24 May 2026 02:00:17 -0400 Subject: [PATCH] docs: clarify byte-preserving behavior of config:set --encoded The canonical encode pipeline `echo "value" | base64` silently appends `\n` to the value, which round-trips through base64 and ends up stored in the env. Document that decoded values are stored byte-for-byte, recommend `printf '%s'` or `echo -n` for short inline values, and show `cat | base64 -w 0` for files. Adds a bats test asserting all four encoding patterns produce the expected stored bytes. Closes #8647. --- docs/configuration/environment-variables.md | 13 ++++++ tests/unit/config.bats | 51 +++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/docs/configuration/environment-variables.md b/docs/configuration/environment-variables.md index 8f07fdc6f..80e9bb656 100644 --- a/docs/configuration/environment-variables.md +++ b/docs/configuration/environment-variables.md @@ -42,6 +42,19 @@ Dokku can also read base64 encoded values. That's the easiest way to set a value dokku config:set --encoded node-js-app KEY="$(base64 -w 0 ~/.ssh/id_rsa)" ``` +Decoded values are stored byte-for-byte exactly as they were encoded. Be aware that `echo "value" | base64` appends a trailing `\n` before encoding because `echo` always adds a newline, and that newline becomes part of the stored value. This is rarely what you want for short inline values - use `printf '%s'` or `echo -n` instead: + +```shell +dokku config:set --encoded node-js-app KEY="$(printf '%s' "myvalue" | base64 -w 0)" +dokku config:set --encoded node-js-app KEY="$(echo -n "myvalue" | base64 -w 0)" +``` + +For multi-line values from a file (such as an SSH private key), `cat` and `base64 -w 0` preserve the file contents exactly: + +```shell +dokku config:set --encoded node-js-app KEY="$(cat ~/.ssh/id_rsa | base64 -w 0)" +``` + When setting or unsetting environment variables, you may wish to avoid an application restart. This is useful when developing plugins or when setting multiple environment variables in a scripted manner. To do so, use the `--no-restart` flag: ```shell diff --git a/tests/unit/config.bats b/tests/unit/config.bats index d29605468..6feda5afe 100644 --- a/tests/unit/config.bats +++ b/tests/unit/config.bats @@ -399,6 +399,57 @@ teardown() { assert_output "hello world" } +@test "(config) config:set --encoded preserves decoded bytes" { + local encoded_echo encoded_printf encoded_echo_n encoded_cat tmpfile + encoded_echo="$(echo "myvalue" | base64 -w 0)" + encoded_printf="$(printf '%s' "myvalue" | base64 -w 0)" + encoded_echo_n="$(echo -n "myvalue" | base64 -w 0)" + tmpfile="$(mktemp)" + printf 'filecontent' > "$tmpfile" + encoded_cat="$(cat "$tmpfile" | base64 -w 0)" + rm -f "$tmpfile" + + run /bin/bash -c "dokku config:set --encoded --no-restart $TEST_APP test_echo=$encoded_echo" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku config:get $TEST_APP test_echo | wc -c" + echo "output: $output" + echo "status: $status" + assert_output "9" + + run /bin/bash -c "dokku config:set --encoded --no-restart $TEST_APP test_printf=$encoded_printf" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku config:get $TEST_APP test_printf | wc -c" + echo "output: $output" + echo "status: $status" + assert_output "8" + + run /bin/bash -c "dokku config:set --encoded --no-restart $TEST_APP test_echo_n=$encoded_echo_n" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku config:get $TEST_APP test_echo_n | wc -c" + echo "output: $output" + echo "status: $status" + assert_output "8" + + run /bin/bash -c "dokku config:set --encoded --no-restart $TEST_APP test_cat=$encoded_cat" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku config:get $TEST_APP test_cat | wc -c" + echo "output: $output" + echo "status: $status" + assert_output "12" +} + @test "(config) config:clear" { run ssh "dokku@$DOKKU_DOMAIN" config:set $TEST_APP test_var=true test_var2=\"hello world\" test_var3=\"with\\nnewline\" echo "output: $output"