Skip to content

fix(install): read prompts from /dev/tty so curl | bash works#525

Merged
algirdasc merged 6 commits into
mainfrom
fix/install-script-tty
Jul 4, 2026
Merged

fix(install): read prompts from /dev/tty so curl | bash works#525
algirdasc merged 6 commits into
mainfrom
fix/install-script-tty

Conversation

@algirdasc

Copy link
Copy Markdown
Owner

Problem

Running the installer via curl -fsSL .../install.sh | sudo bash exited silently right after Creating directory.

Cause: when piped, stdin is the script text, not the terminal. Interactive read calls hit EOF immediately, and under set -euo pipefail the non-zero return killed the script without any error.

Fix

  • Redirect all read calls (ask, ask_secret, confirm) to < /dev/tty
  • Add a guard in main() that fails with a clear message if no terminal is available

Result

curl -fsSL .../install.sh | sudo bash now prompts correctly and completes installation.

algirdasc added 6 commits July 4, 2026 19:31
When piped via 'curl ... | sudo bash', stdin is the script text, not the
terminal. Interactive read calls returned EOF immediately, and under
'set -e' the script exited silently after creating the install dir.

Fix: redirect all read calls to /dev/tty. Add a guard that fails with a
clear message when no terminal is available.
Script exited silently after collecting config. Root causes:
- set -e killed the script on any non-zero return with no message
- mkdir/cd failures were not reported

Changes:
- Drop 'set -e' (keep 'set -uo pipefail'), add EXIT trap that prints
  a visible message on non-zero exit
- Explicit error handling around mkdir and cd with actionable hints
Two root causes for the script exiting silently after prompts:

1. gen_password piped /dev/urandom into 'head -c', which closes the pipe
   early and raises SIGPIPE, killing the pipeline (and script).
   Fix: read a fixed 4096-byte chunk via process substitution, then cut.

2. Under 'curl ... | bash' the script body lives on stdin. After the last
   /dev/tty read, bash had no more script to read and exited.
   Fix: when stdin is not a TTY, re-download to a temp file and re-exec
   with 'bash $tmp < /dev/tty' (guarded by EXPENSAVE_REEXEC).
Previous re-exec fetched install.sh from main, so testing a branch would
run the OLD main version — masking the fix and still dying in the old
gen_password. Instead, copy this very script from stdin to a temp file
('cat > $tmp') and re-exec it with /dev/tty as stdin. No re-download,
no version drift.
- gen_password: no pipes/process-substitution, transform in-memory
- re-exec: drop $@ passthrough, add debug markers
- add [debug] marker between collect_config and do_install
to pinpoint where it stops
The re-exec copied stdin to a temp file, but bash had ALREADY consumed
the first ~19 lines (including COMPOSE_URL and DEFAULT_INSTALL_DIR
definitions) before 'cat > tmp' ran. The re-exec'd copy was missing
those vars — hence empty install dir and 'curl: (3) bad URL'.

Fix:
- Remove re-exec entirely. Interactive reads already use /dev/tty, which
  works fine under 'curl | bash'.
- Restore 'set -e' so failed curl/sed/docker commands stop the script
  instead of printing a fake success checkmark.
- Keep a trap for a clear failure message.
@algirdasc
algirdasc merged commit c134673 into main Jul 4, 2026
3 checks passed
@algirdasc
algirdasc deleted the fix/install-script-tty branch July 4, 2026 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant