feat(docker): guided first run for the Compose deployment

A new Docker install was: clone (undocumented), copy .env.example by hand,
fix an Unraid data path and a Perth time zone, replace `changeme`, run the
start script, and then guess when the server was up. Start-Codeman.sh now
does all of it from a fresh clone:

- Preflight names the fix for a missing docker CLI, a missing or too-old
  Compose plugin (config --environment needs 2.27.2, docker/compose#11891),
  and an unreachable daemon (docker group, never sudo).
- With no docker/.env, it asks three questions (data folder, port,
  password; Enter takes each default: ~/codeman-docker, 3000 or the next
  free port, a generated password) and writes docker/.env FROM the example,
  so every key the updater's diffRequiredEnvKeys expects is present. Mode
  0600, host time zone, values Compose would interpolate single-quoted.
  Refuses $HOME, ~/.codeman (a native install's state dir) and anything
  inside the checkout (the image build context). --yes / no TTY take the
  defaults, --setup-only stops after writing the file. An existing .env is
  never edited, and root never runs the setup (Unraid keeps the hand route).
- After `up`, it waits until the server answers (docker exec probe, crash
  loop caught by the restart count) and prints the URL, the LAN URL, the
  generated password and the logs/stop commands; --no-wait skips the wait.
- `changeme` is refused before anything starts (the container publishes on
  every interface and holds the Docker socket); Update-Codeman.sh checks it
  before its build and down so the stack is never left stopped.
- Compose settings are read with ONE config --environment call, with its
  error reported, instead of three silent ones.

docker-compose.yaml and server.Dockerfile are untouched (their hashes gate
the in-app updater), and .env.example changes values and comments only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-10-09 19:14:49 +02:00
parent 3a0cee6b90
commit 0a63588716
8 changed files with 1191 additions and 39 deletions
+16
View File
@@ -177,6 +177,22 @@ if [[ -z "$appdata_path" || ! -d "$appdata_path" ]]; then
exit 1
fi
# Start-Codeman.sh refuses to start while the password is still the example's
# `changeme`. Checked here too, BEFORE the build and the `down` below: found
# only at the handoff, that refusal would leave the stack this script just
# stopped down. No early `exit` in awk, so printf never meets a closed pipe.
codeman_password=$(
"${compose_command[@]}" config --environment |
awk -F= '$1 == "CODEMAN_PASSWORD" && !found { sub(/^[^=]*=/, ""); print; found = 1 }'
)
if [[ "$codeman_password" == 'changeme' ]]; then
printf 'Error: CODEMAN_PASSWORD is still the example value "changeme".\n' >&2
printf 'Codeman is reachable from your network and controls Docker on this machine, so\n' >&2
printf 'set a real password in %s, then rerun this script. Nothing was stopped.\n' "$env_file" >&2
exit 1
fi
unset codeman_password
# `stat -c` is GNU, `stat -f` is BSD/macOS; the bind source lives on the Docker
# host, so both need to work. Identical to Start-Codeman.sh's own helper.
owner_of() {