Add bootstrap.sh with zsh and git modules
Cross-distro (RHEL/Debian) VM setup: zsh + oh-my-zsh with a self-healing bash fallback for environments that reset the root filesystem or hardcode bash for new terminals (e.g. Kasm Workspaces), plus git identity and HTTPS credential-store configuration. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Executable
+87
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env sh
|
||||
# zsh/install.sh — install zsh + oh-my-zsh and make zsh the login shell.
|
||||
# Works on RHEL-family (dnf/yum) and Debian-family (apt) hosts. Idempotent:
|
||||
# safe to re-run on a box that already has some/all of this in place.
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
|
||||
REPO_ROOT="$(dirname -- "$SCRIPT_DIR")"
|
||||
|
||||
# shellcheck source=../lib/os-detect.sh
|
||||
. "$REPO_ROOT/lib/os-detect.sh"
|
||||
|
||||
say() { printf '%s\n' "$*" >&2; }
|
||||
|
||||
# --- 1. install zsh ---------------------------------------------------------
|
||||
if command -v zsh >/dev/null 2>&1; then
|
||||
say "zsh already installed ($(command -v zsh))."
|
||||
else
|
||||
say "Installing zsh..."
|
||||
pkg_install zsh
|
||||
fi
|
||||
ZSH_BIN="$(command -v zsh)"
|
||||
|
||||
# --- 2. install oh-my-zsh (unattended) --------------------------------------
|
||||
if [ -d "$HOME/.oh-my-zsh" ]; then
|
||||
say "oh-my-zsh already installed."
|
||||
else
|
||||
say "Installing oh-my-zsh..."
|
||||
command -v curl >/dev/null 2>&1 || pkg_install curl
|
||||
RUNZSH=no CHSH=no KEEP_ZSHRC=yes \
|
||||
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
|
||||
fi
|
||||
|
||||
# --- 3. install our .zshrc ---------------------------------------------------
|
||||
DEST="$HOME/.zshrc"
|
||||
SRC="$SCRIPT_DIR/zshrc"
|
||||
if [ -f "$DEST" ] && ! cmp -s "$SRC" "$DEST"; then
|
||||
BACKUP="$DEST.bak.$(date +%Y%m%d%H%M%S 2>/dev/null || printf 'pre-dotfiles')"
|
||||
say "Backing up existing $DEST -> $BACKUP"
|
||||
cp "$DEST" "$BACKUP"
|
||||
fi
|
||||
cp "$SRC" "$DEST"
|
||||
say "Installed $DEST"
|
||||
|
||||
# --- 4. make zsh the login shell --------------------------------------------
|
||||
if ! grep -qxF "$ZSH_BIN" /etc/shells 2>/dev/null; then
|
||||
say "Adding $ZSH_BIN to /etc/shells"
|
||||
echo "$ZSH_BIN" | sudo tee -a /etc/shells >/dev/null
|
||||
fi
|
||||
|
||||
CURRENT_SHELL="$(getent passwd "$(id -un)" 2>/dev/null | cut -d: -f7)"
|
||||
if [ "$CURRENT_SHELL" = "$ZSH_BIN" ]; then
|
||||
say "zsh is already the login shell."
|
||||
else
|
||||
say "Changing login shell to $ZSH_BIN"
|
||||
# Use usermod (root, via sudo) instead of chsh: chsh runs its own PAM
|
||||
# authentication for the invoking user's password, which fails with a PAM
|
||||
# error in minimal containers (e.g. Kasm images) even when sudo itself is
|
||||
# passwordless. usermod edits /etc/passwd directly as root, no PAM prompt.
|
||||
sudo usermod -s "$ZSH_BIN" "$(id -un)"
|
||||
fi
|
||||
|
||||
# --- 5. bash fallback: auto-exec into zsh -----------------------------------
|
||||
# Some environments (e.g. Kasm Workspaces) hardcode/inherit bash for new
|
||||
# terminals regardless of the /etc/passwd shell, and reset the root
|
||||
# filesystem (including installed packages and /etc/passwd) on rebuild while
|
||||
# keeping $HOME. Sourcing this from ~/.bashrc — which lives in $HOME — makes
|
||||
# every fresh bash self-heal into zsh, reinstalling it first if needed.
|
||||
BASHRC="$HOME/.bashrc"
|
||||
HOOK_MARKER="# >>> dotfiles zsh auto-exec >>>"
|
||||
if [ -f "$BASHRC" ] && grep -qF "$HOOK_MARKER" "$BASHRC" 2>/dev/null; then
|
||||
say "bash auto-exec hook already present in $BASHRC."
|
||||
else
|
||||
say "Adding zsh auto-exec hook to $BASHRC (covers terminals that always spawn bash)."
|
||||
{
|
||||
printf '\n%s\n' "$HOOK_MARKER"
|
||||
printf '%s\n' "# Re-exec into zsh for interactive shells, self-healing (reinstalling"
|
||||
printf '%s\n' "# zsh) if this container's root filesystem was reset since last run."
|
||||
printf '%s\n' 'if [ -n "$PS1" ] && [ -z "${ZSH_VERSION:-}" ]; then'
|
||||
printf ' %s\n' "command -v zsh >/dev/null 2>&1 || \"$SCRIPT_DIR/install.sh\" >/dev/null 2>&1 || true"
|
||||
printf ' %s\n' 'command -v zsh >/dev/null 2>&1 && exec zsh -l'
|
||||
printf '%s\n' 'fi'
|
||||
printf '%s\n' "# <<< dotfiles zsh auto-exec <<<"
|
||||
} >> "$BASHRC"
|
||||
fi
|
||||
|
||||
say "Done. Open a new terminal to use zsh."
|
||||
Reference in New Issue
Block a user