214 lines
8.1 KiB
Cheetah
214 lines
8.1 KiB
Cheetah
#!/usr/bin/env bash
|
|
# run_onchange_linux_install-packages.sh
|
|
# Installs packages on Ubuntu/Debian via apt and manual installs for tools
|
|
# not available (or outdated) in apt.
|
|
# This script re-runs whenever packages/linux.txt changes.
|
|
#
|
|
# Hash of packages file (forces re-run on change):
|
|
# {{ include "packages/linux.txt" | sha256sum }}
|
|
|
|
set -euo pipefail
|
|
|
|
# Ensure snap binaries are visible (chezmoi scripts may not inherit /snap/bin)
|
|
[ -d "/snap/bin" ] && export PATH="$PATH:/snap/bin"
|
|
|
|
CHEZMOI_SOURCE_DIR="{{ .chezmoi.sourceDir }}"
|
|
|
|
echo "==> Updating apt package index..."
|
|
sudo apt-get update -q
|
|
|
|
echo "==> Installing apt packages..."
|
|
apt_packages=$(grep -v '^#' "$CHEZMOI_SOURCE_DIR/packages/linux.txt" | grep -v '^$' | tr '\n' ' ')
|
|
# shellcheck disable=SC2086
|
|
sudo apt-get install -y $apt_packages
|
|
|
|
# --- Tailscale ---
|
|
if ! command -v tailscale &>/dev/null; then
|
|
echo "==> Installing Tailscale..."
|
|
curl -fsSL https://tailscale.com/install.sh | sh
|
|
else
|
|
echo "==> Tailscale already installed"
|
|
fi
|
|
|
|
# --- Go ---
|
|
GO_VERSION=$(curl -fsSL "https://go.dev/dl/?mode=json" | python3 -c "import sys,json; print(json.load(sys.stdin)[0]['version'].lstrip('go'))")
|
|
if ! command -v go &>/dev/null || [[ "$(go version 2>/dev/null | awk '{print $3}' | tr -d 'go')" != "$GO_VERSION" ]]; then
|
|
echo "==> Installing Go $GO_VERSION..."
|
|
curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" -o /tmp/go.tar.gz
|
|
sudo rm -rf /usr/local/go
|
|
sudo tar -C /usr/local -xzf /tmp/go.tar.gz
|
|
rm /tmp/go.tar.gz
|
|
echo "export PATH=\$PATH:/usr/local/go/bin" >> "$HOME/.zshenv"
|
|
else
|
|
echo "==> Go already installed"
|
|
fi
|
|
|
|
# --- Rust ---
|
|
if ! command -v rustup &>/dev/null; then
|
|
echo "==> Installing Rust via rustup..."
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path
|
|
source "$HOME/.cargo/env"
|
|
else
|
|
echo "==> Rust already installed"
|
|
fi
|
|
|
|
# --- NVM (Node Version Manager) ---
|
|
if [ ! -d "$HOME/.nvm" ]; then
|
|
echo "==> Installing NVM..."
|
|
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
|
|
export NVM_DIR="$HOME/.nvm"
|
|
# shellcheck disable=SC1091
|
|
[ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh"
|
|
nvm install --lts
|
|
else
|
|
echo "==> NVM already installed"
|
|
fi
|
|
|
|
# --- Oh My Zsh ---
|
|
if [ ! -d "$HOME/.oh-my-zsh" ]; then
|
|
echo "==> Installing Oh My Zsh..."
|
|
RUNZSH=no CHSH=no sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
|
|
else
|
|
echo "==> Oh My Zsh already installed"
|
|
fi
|
|
|
|
# --- Oh My Zsh plugins ---
|
|
ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
|
|
|
|
if [ ! -d "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ]; then
|
|
echo "==> Installing zsh-autosuggestions..."
|
|
git clone https://github.com/zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions"
|
|
else
|
|
echo "==> zsh-autosuggestions already installed"
|
|
fi
|
|
|
|
if [ ! -d "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" ]; then
|
|
echo "==> Installing zsh-syntax-highlighting..."
|
|
git clone https://github.com/zsh-users/zsh-syntax-highlighting "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting"
|
|
else
|
|
echo "==> zsh-syntax-highlighting already installed"
|
|
fi
|
|
|
|
# --- Neovim ---
|
|
if ! command -v nvim &>/dev/null; then
|
|
echo "==> Installing Neovim (latest)..."
|
|
curl -fsSL https://github.com/neovim/neovim/releases/latest/download/nvim-linux-x86_64.tar.gz -o /tmp/nvim.tar.gz
|
|
sudo tar -C /opt -xzf /tmp/nvim.tar.gz
|
|
sudo ln -sf /opt/nvim-linux-x86_64/bin/nvim /usr/local/bin/nvim
|
|
rm /tmp/nvim.tar.gz
|
|
else
|
|
echo "==> Neovim already installed"
|
|
fi
|
|
|
|
# --- lazygit ---
|
|
if ! command -v lazygit &>/dev/null; then
|
|
echo "==> Installing lazygit..."
|
|
LAZYGIT_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | grep -Po '"tag_name": "v\K[^"]*')
|
|
curl -fsSL "https://github.com/jesseduffield/lazygit/releases/download/v${LAZYGIT_VERSION}/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz" -o /tmp/lazygit.tar.gz
|
|
sudo tar xf /tmp/lazygit.tar.gz lazygit -C /usr/local/bin
|
|
rm /tmp/lazygit.tar.gz
|
|
else
|
|
echo "==> lazygit already installed"
|
|
fi
|
|
|
|
# --- watchexec ---
|
|
if ! command -v watchexec &>/dev/null; then
|
|
echo "==> Installing watchexec..."
|
|
WE_VERSION=$(curl -s "https://api.github.com/repos/watchexec/watchexec/releases/latest" | grep -Po '"tag_name": "v\K[^"]*')
|
|
curl -fsSL "https://github.com/watchexec/watchexec/releases/download/v${WE_VERSION}/watchexec-${WE_VERSION}-x86_64-unknown-linux-musl.tar.xz" -o /tmp/watchexec.tar.xz
|
|
tar -xJf /tmp/watchexec.tar.xz -C /tmp "watchexec-${WE_VERSION}-x86_64-unknown-linux-musl/watchexec"
|
|
sudo mv "/tmp/watchexec-${WE_VERSION}-x86_64-unknown-linux-musl/watchexec" /usr/local/bin/watchexec
|
|
rm -rf /tmp/watchexec.tar.xz "/tmp/watchexec-${WE_VERSION}-x86_64-unknown-linux-musl"
|
|
else
|
|
echo "==> watchexec already installed"
|
|
fi
|
|
|
|
# --- bottom (btm) ---
|
|
if ! command -v btm &>/dev/null; then
|
|
echo "==> Installing bottom (btm)..."
|
|
curl -fsSLO https://github.com/ClementTsang/bottom/releases/latest/download/bottom_x86_64-unknown-linux-musl.tar.gz
|
|
tar -xzf bottom_x86_64-unknown-linux-musl.tar.gz
|
|
sudo mv btm /usr/local/bin/
|
|
rm bottom_x86_64-unknown-linux-musl.tar.gz
|
|
else
|
|
echo "==> bottom already installed"
|
|
fi
|
|
|
|
# --- Bitwarden CLI ---
|
|
if ! command -v bw &>/dev/null; then
|
|
echo "==> Installing Bitwarden CLI..."
|
|
BW_VERSION=$(curl -s "https://api.github.com/repos/bitwarden/clients/releases" | grep -Po '"tag_name": "cli-v\K[^"]*' | head -1)
|
|
if [ -z "$BW_VERSION" ]; then
|
|
echo "WARNING: Could not determine Bitwarden CLI version, skipping install."
|
|
else
|
|
curl -fsSL "https://github.com/bitwarden/clients/releases/download/cli-v${BW_VERSION}/bw-linux-${BW_VERSION}.zip" -o /tmp/bw.zip
|
|
unzip -o /tmp/bw.zip -d /tmp/bw
|
|
sudo mv /tmp/bw/bw /usr/local/bin/bw
|
|
sudo chmod +x /usr/local/bin/bw
|
|
rm -rf /tmp/bw.zip /tmp/bw
|
|
fi
|
|
else
|
|
echo "==> Bitwarden CLI already installed"
|
|
fi
|
|
|
|
# --- Doppler ---
|
|
if ! command -v doppler &>/dev/null; then
|
|
echo "==> Installing Doppler..."
|
|
curl -Ls --tlsv1.2 --proto "=https" --retry 3 https://cli.doppler.com/install.sh | sudo sh
|
|
else
|
|
echo "==> Doppler already installed"
|
|
fi
|
|
|
|
# --- GitHub CLI ---
|
|
if ! command -v gh &>/dev/null; then
|
|
echo "==> Installing GitHub CLI..."
|
|
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
|
|
sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg
|
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
|
|
sudo apt-get update -q
|
|
sudo apt-get install gh -y
|
|
else
|
|
echo "==> GitHub CLI already installed"
|
|
fi
|
|
|
|
# --- uv (Python package/project manager) ---
|
|
if ! command -v uv &>/dev/null; then
|
|
echo "==> Installing uv..."
|
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
else
|
|
echo "==> uv already installed"
|
|
fi
|
|
|
|
# --- Docker ---
|
|
if ! command -v docker &>/dev/null; then
|
|
echo "==> Installing Docker..."
|
|
curl -fsSL https://get.docker.com | sh
|
|
sudo usermod -aG docker "$USER"
|
|
echo "NOTE: Log out and back in for Docker group membership to take effect."
|
|
else
|
|
echo "==> Docker already installed"
|
|
fi
|
|
|
|
# --- .NET SDK (8 + 10) ---
|
|
# Uses Microsoft's official dotnet-install.sh script
|
|
DOTNET_INSTALL_DIR="$HOME/.dotnet"
|
|
DOTNET_SCRIPT=$(mktemp /tmp/dotnet-install-XXXXXX.sh)
|
|
curl -fsSL https://dot.net/v1/dotnet-install.sh -o "$DOTNET_SCRIPT"
|
|
chmod +x "$DOTNET_SCRIPT"
|
|
|
|
for DOTNET_CHANNEL in "8.0" "10.0"; do
|
|
MAJOR="${DOTNET_CHANNEL%%.*}"
|
|
DOTNET_VERSION_INSTALLED=$(find "$DOTNET_INSTALL_DIR/sdk" -maxdepth 1 -name "${MAJOR}.*" 2>/dev/null | head -1 || echo "")
|
|
if [ -z "$DOTNET_VERSION_INSTALLED" ]; then
|
|
echo "==> Installing .NET SDK $DOTNET_CHANNEL..."
|
|
"$DOTNET_SCRIPT" --channel "$DOTNET_CHANNEL" --install-dir "$DOTNET_INSTALL_DIR"
|
|
else
|
|
echo "==> .NET SDK $DOTNET_CHANNEL already installed"
|
|
fi
|
|
done
|
|
|
|
rm -f "$DOTNET_SCRIPT"
|
|
|
|
echo ""
|
|
echo "==> Linux package installation complete!"
|