Files
StianNOR-ZSHkit/uninstall.sh
2026-03-25 15:22:34 +01:00

460 lines
19 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# =============================================================================
# 🗑️ StianNOR — COMPLETE UNINSTALLER v1.0
# Uninstalls everything installed by:
# - setup_zsh_font.sh (Zsh, Oh My Zsh, p10k, plugins, colorls, fastfetch, Hack Nerd Font)
# - portainerup.sh (Portainer CE, Docker, Docker Compose)
# =============================================================================
set -uo pipefail
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
BLUE='\033[0;34m'; CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m'
LINE="────────────────────────────────────────────────────────────────────────────"
info() { echo -e "${CYAN} $*${RESET}"; }
success() { echo -e "${GREEN}$*${RESET}"; }
warn() { echo -e "${YELLOW}$*${RESET}"; }
error() { echo -e "${RED}$*${RESET}"; }
step() { echo -e "\n${BOLD}${BLUE}$*${RESET}"; echo -e "${BLUE}${LINE}${RESET}"; }
skip() { echo -e " ${BLUE}$* — not found, skipping${RESET}"; }
# =============================================================================
# DETECT PACKAGE MANAGER
# =============================================================================
detect_pm() {
if command -v pacman >/dev/null 2>&1; then PM="pacman"
elif command -v apt >/dev/null 2>&1; then PM="apt"
elif command -v dnf >/dev/null 2>&1; then PM="dnf"
elif command -v zypper >/dev/null 2>&1; then PM="zypper"
elif command -v apk >/dev/null 2>&1; then PM="apk"
else PM="unknown"; fi
}
detect_pm
pkg_remove() {
case "$PM" in
pacman) sudo pacman -Rns --noconfirm "$@" 2>/dev/null || true ;;
apt) sudo apt remove -y --purge "$@" 2>/dev/null || true; sudo apt autoremove -y 2>/dev/null || true ;;
dnf) sudo dnf remove -y "$@" 2>/dev/null || true ;;
zypper) sudo zypper remove -y "$@" 2>/dev/null || true ;;
apk) sudo apk del "$@" 2>/dev/null || true ;;
esac
}
# =============================================================================
# CONFIRM — show full plan before doing anything
# =============================================================================
clear
echo -e "${LINE}"
echo -e "${BOLD}${RED} 🗑️ StianNOR COMPLETE UNINSTALLER${RESET}"
echo -e "${LINE}"
echo ""
echo -e " This will remove the following — ${BOLD}select what to uninstall:${RESET}"
echo ""
echo -e " ${BOLD}${CYAN}[A] ZSH + FONT SETUP${RESET}"
echo -e " • Hack Nerd Font (system-wide)"
echo -e " • fontconfig monospace alias (/etc/fonts/local.conf)"
echo -e " • Oh My Zsh + Powerlevel10k + all plugins"
echo -e " • colorls Ruby gem"
echo -e " • fastfetch"
echo -e " • ~/.zshrc and ~/.p10k.zsh"
echo -e " • Default shell reverted to bash"
echo ""
echo -e " ${BOLD}${CYAN}[B] PORTAINER + DOCKER${RESET}"
echo -e " • Portainer CE container + data volume"
echo -e " • Docker CE + Docker Compose"
echo -e " • docker group membership for $USER"
echo -e " • Docker config dir (~/.docker)"
echo ""
echo -e " ${BOLD}${CYAN}[C] BOTH (full wipe)${RESET}"
echo ""
echo -e "${LINE}"
echo -e " ${YELLOW}[q]${RESET} cancel and exit"
echo -e "${LINE}"
echo ""
printf " Choice: "
read -r CHOICE
echo ""
case "${CHOICE,,}" in
a) DO_ZSH=true; DO_DOCKER=false ;;
b) DO_ZSH=false; DO_DOCKER=true ;;
c) DO_ZSH=true; DO_DOCKER=true ;;
q|"") echo -e " ${YELLOW}Cancelled.${RESET}"; exit 0 ;;
*) echo -e " ${RED}Invalid choice. Exiting.${RESET}"; exit 1 ;;
esac
# Final confirm
echo -e "${LINE}"
echo -e " ${BOLD}${RED}This is destructive and cannot be undone.${RESET}"
printf " Type ${BOLD}YES${RESET} to confirm: "
read -r CONFIRM
echo ""
[[ "$CONFIRM" != "YES" ]] && echo -e " ${YELLOW}Aborted.${RESET}" && exit 0
# =============================================================================
# LOG FILE
# =============================================================================
LOG_DIR="$HOME/Homelab/logs"
mkdir -p "$LOG_DIR" 2>/dev/null || LOG_DIR="/tmp"
LOG_FILE="$LOG_DIR/uninstall-$(date +%Y%m%d-%H%M%S).log"
exec > >(tee -a "$LOG_FILE") 2>&1
info "Logging to $LOG_FILE"
# =============================================================================
# A — UNINSTALL ZSH + FONT SETUP
# =============================================================================
uninstall_zsh_font() {
# ── 1. Revert default shell to bash ──────────────────────────────────────
step "Reverting default shell to bash"
BASH_PATH=$(command -v bash 2>/dev/null || echo "/bin/bash")
CURRENT_SHELL=$(getent passwd "$USER" | cut -d: -f7)
if [[ "$CURRENT_SHELL" == *zsh* ]]; then
grep -qxF "$BASH_PATH" /etc/shells || echo "$BASH_PATH" | sudo tee -a /etc/shells
if chsh -s "$BASH_PATH" 2>/dev/null; then
success "Default shell reverted to $BASH_PATH"
else
warn "Could not change shell automatically — run: chsh -s $BASH_PATH"
fi
else
skip "Shell was not zsh ($CURRENT_SHELL)"
fi
# ── 2. Remove Oh My Zsh ──────────────────────────────────────────────────
step "Removing Oh My Zsh"
if [[ -d "$HOME/.oh-my-zsh" ]]; then
rm -rf "$HOME/.oh-my-zsh"
success "Oh My Zsh removed"
else
skip "~/.oh-my-zsh"
fi
# ── 3. Remove Powerlevel10k (standalone clone, if outside OMZ) ───────────
step "Removing Powerlevel10k"
for p10k_path in \
"$HOME/.oh-my-zsh/custom/themes/powerlevel10k" \
"$HOME/powerlevel10k" \
"${ZSH_CUSTOM:-}/themes/powerlevel10k"; do
if [[ -d "$p10k_path" ]]; then
rm -rf "$p10k_path"
success "Removed $p10k_path"
fi
done
# ── 4. Remove Zsh plugin dirs ─────────────────────────────────────────────
step "Removing Zsh plugins"
for plugin in zsh-autosuggestions zsh-syntax-highlighting zsh-completions; do
PLUGIN_DIR="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/$plugin"
if [[ -d "$PLUGIN_DIR" ]]; then
rm -rf "$PLUGIN_DIR"
success "Removed plugin: $plugin"
else
skip "Plugin $plugin"
fi
done
# ── 5. Remove colorls gem ─────────────────────────────────────────────────
step "Removing colorls Ruby gem"
if gem list -i colorls >/dev/null 2>&1; then
gem uninstall colorls -a -x 2>/dev/null && success "colorls removed" \
|| warn "colorls uninstall had warnings"
else
skip "colorls gem"
fi
# Clean up gem home if empty
GEM_HOME_DIR="$HOME/.gem"
if [[ -d "$GEM_HOME_DIR" ]]; then
REMAINING=$(find "$GEM_HOME_DIR" -name "*.gemspec" 2>/dev/null | wc -l)
if [[ "$REMAINING" -eq 0 ]]; then
rm -rf "$GEM_HOME_DIR"
success "Removed empty ~/.gem"
else
info "$REMAINING other gems remain in ~/.gem — leaving it"
fi
fi
# ── 6. Remove fastfetch ───────────────────────────────────────────────────
step "Removing fastfetch"
if command -v fastfetch >/dev/null 2>&1; then
FF_PATH=$(command -v fastfetch)
# If installed via package manager
removed=false
case "$PM" in
pacman) sudo pacman -Rns --noconfirm fastfetch 2>/dev/null && removed=true ;;
apt) sudo apt remove -y --purge fastfetch 2>/dev/null && removed=true ;;
dnf) sudo dnf remove -y fastfetch 2>/dev/null && removed=true ;;
zypper) sudo zypper remove -y fastfetch 2>/dev/null && removed=true ;;
apk) sudo apk del fastfetch 2>/dev/null && removed=true ;;
esac
# If it was a manually installed binary
if [[ "$removed" == false ]] || command -v fastfetch >/dev/null 2>&1; then
sudo rm -f /usr/local/bin/fastfetch /usr/bin/fastfetch 2>/dev/null || true
fi
command -v fastfetch >/dev/null 2>&1 \
&& warn "fastfetch still found at $(command -v fastfetch) — remove manually" \
|| success "fastfetch removed"
else
skip "fastfetch"
fi
# ── 7. Remove Zsh itself ──────────────────────────────────────────────────
step "Removing Zsh"
if command -v zsh >/dev/null 2>&1; then
printf " Remove zsh package itself? (leaves system zsh on some distros) [y/N]: "
read -r yn
if [[ "${yn,,}" == "y" ]]; then
pkg_remove zsh
command -v zsh >/dev/null 2>&1 \
&& warn "zsh still present (may be a system dependency)" \
|| success "zsh removed"
else
info "Zsh package kept (shell reverted to bash above)"
fi
else
skip "zsh (not installed)"
fi
# ── 8. Remove dot files ───────────────────────────────────────────────────
step "Removing ~/.zshrc and ~/.p10k.zsh"
for f in "$HOME/.zshrc" "$HOME/.p10k.zsh" "$HOME/.zsh_history"; do
if [[ -f "$f" ]]; then
# Back up before deleting
cp "$f" "${f}.uninstall-backup-$(date +%Y%m%d)" 2>/dev/null || true
rm -f "$f"
success "Removed $f (backup saved as ${f}.uninstall-backup-*)"
else
skip "$f"
fi
done
# ── 9. Remove Hack Nerd Font ──────────────────────────────────────────────
step "Removing Hack Nerd Font"
FONT_DIR="/usr/local/share/fonts/nerd-fonts"
if [[ -d "$FONT_DIR" ]]; then
sudo rm -rf "$FONT_DIR"
sudo fc-cache -f 2>/dev/null || true
success "Hack Nerd Font removed from $FONT_DIR"
else
skip "$FONT_DIR"
fi
# Also check user font dir
USER_FONT_DIR="$HOME/.local/share/fonts/nerd-fonts"
if [[ -d "$USER_FONT_DIR" ]]; then
rm -rf "$USER_FONT_DIR"
fc-cache -f "$HOME/.local/share/fonts" 2>/dev/null || true
success "Removed user font dir $USER_FONT_DIR"
fi
# ── 10. Remove fontconfig override ───────────────────────────────────────
step "Removing fontconfig monospace alias"
if [[ -f /etc/fonts/local.conf ]]; then
if grep -q "Hack Nerd Font" /etc/fonts/local.conf 2>/dev/null; then
sudo rm -f /etc/fonts/local.conf
sudo fc-cache -f 2>/dev/null || true
success "Removed /etc/fonts/local.conf"
else
info "/etc/fonts/local.conf exists but doesn't contain Hack Nerd Font — leaving it"
fi
else
skip "/etc/fonts/local.conf"
fi
# ── 11. Clean up PATH entries added to shell rc files ────────────────────
step "Cleaning gem PATH entries from shell rc files"
for rc in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.bash_profile" "$HOME/.profile"; do
if [[ -f "$rc" ]]; then
if grep -q "\.gem" "$rc" 2>/dev/null; then
sed -i '/\.gem\/ruby/d' "$rc" 2>/dev/null || true
sed -i '/GEM_HOME/d' "$rc" 2>/dev/null || true
success "Cleaned gem PATH from $rc"
fi
fi
done
}
# =============================================================================
# B — UNINSTALL PORTAINER + DOCKER
# =============================================================================
uninstall_docker_portainer() {
# ── 1. Stop and remove Portainer ─────────────────────────────────────────
step "Removing Portainer CE"
if command -v docker >/dev/null 2>&1; then
DOCKER_CMD="docker"
docker info >/dev/null 2>&1 || DOCKER_CMD="sudo docker"
if $DOCKER_CMD ps -a --format '{{.Names}}' 2>/dev/null | grep -q "^portainer$"; then
$DOCKER_CMD stop portainer 2>/dev/null || true
$DOCKER_CMD rm portainer 2>/dev/null || true
success "Portainer container stopped and removed"
else
skip "Portainer container"
fi
# Remove portainer data volume
if $DOCKER_CMD volume ls --format '{{.Name}}' 2>/dev/null | grep -q "^portainer_data$"; then
printf " Remove portainer_data volume? This deletes all Portainer settings [y/N]: "
read -r yn
if [[ "${yn,,}" == "y" ]]; then
$DOCKER_CMD volume rm portainer_data 2>/dev/null || true
success "portainer_data volume removed"
else
info "portainer_data volume kept"
fi
else
skip "portainer_data volume"
fi
# Remove the image
if $DOCKER_CMD image ls --format '{{.Repository}}:{{.Tag}}' 2>/dev/null | grep -q "portainer/portainer-ce"; then
printf " Remove Portainer CE docker image? [y/N]: "
read -r yn
if [[ "${yn,,}" == "y" ]]; then
$DOCKER_CMD rmi portainer/portainer-ce:latest 2>/dev/null || true
success "Portainer CE image removed"
else
info "Portainer CE image kept"
fi
fi
else
skip "Docker not installed — Portainer check skipped"
fi
# ── 2. Remove Docker ──────────────────────────────────────────────────────
step "Removing Docker"
if command -v docker >/dev/null 2>&1; then
printf " ${BOLD}${RED}Remove Docker CE completely?${RESET} This removes ALL containers, images and volumes [y/N]: "
read -r yn
if [[ "${yn,,}" != "y" ]]; then
info "Docker kept — only Portainer was removed"
return
fi
# Stop daemon first
sudo systemctl stop docker docker.socket 2>/dev/null || sudo service docker stop 2>/dev/null || true
sudo systemctl disable docker docker.socket 2>/dev/null || true
case "$PM" in
pacman)
sudo pacman -Rns --noconfirm docker docker-compose 2>/dev/null || true
;;
apt)
sudo apt remove -y --purge \
docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin \
docker-compose 2>/dev/null || true
sudo apt autoremove -y 2>/dev/null || true
# Remove Docker apt repo
sudo rm -f /etc/apt/sources.list.d/docker.list
sudo rm -f /etc/apt/keyrings/docker.gpg
sudo apt update -qq 2>/dev/null || true
;;
dnf)
sudo dnf remove -y \
docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin 2>/dev/null || true
sudo rm -f /etc/yum.repos.d/docker-ce.repo 2>/dev/null || true
;;
zypper)
sudo zypper remove -y docker docker-compose 2>/dev/null || true
;;
apk)
sudo apk del docker docker-compose 2>/dev/null || true
sudo rc-update del docker boot 2>/dev/null || true
;;
esac
# Remove standalone docker-compose binary if present
[[ -f /usr/local/bin/docker-compose ]] && sudo rm -f /usr/local/bin/docker-compose \
&& success "Removed standalone docker-compose"
success "Docker CE removed"
else
skip "Docker (not installed)"
fi
# ── 3. Remove Docker data directories ────────────────────────────────────
step "Removing Docker data directories"
for dir in /var/lib/docker /var/lib/containerd /etc/docker; do
if [[ -d "$dir" ]]; then
printf " Remove %s? [y/N]: " "$dir"
read -r yn
if [[ "${yn,,}" == "y" ]]; then
sudo rm -rf "$dir"
success "Removed $dir"
else
info "Kept $dir"
fi
else
skip "$dir"
fi
done
# Remove user docker config
if [[ -d "$HOME/.docker" ]]; then
rm -rf "$HOME/.docker"
success "Removed ~/.docker"
fi
# ── 4. Remove user from docker group ─────────────────────────────────────
step "Removing $USER from docker group"
if getent group docker >/dev/null 2>&1; then
if groups "$USER" | grep -qw docker; then
sudo gpasswd -d "$USER" docker 2>/dev/null \
&& success "$USER removed from docker group" \
|| warn "Could not remove $USER from docker group"
else
skip "$USER was not in docker group"
fi
printf " Delete the docker group itself? [y/N]: "
read -r yn
if [[ "${yn,,}" == "y" ]]; then
sudo groupdel docker 2>/dev/null && success "docker group deleted" \
|| warn "Could not delete docker group"
fi
else
skip "docker group (does not exist)"
fi
# ── 5. Remove Docker socket and service files (if any remain) ────────────
step "Cleaning up Docker service files"
for f in \
/lib/systemd/system/docker.service \
/lib/systemd/system/docker.socket \
/etc/systemd/system/docker.service \
/etc/systemd/system/docker.socket; do
if [[ -f "$f" ]]; then
sudo rm -f "$f"
success "Removed $f"
fi
done
sudo systemctl daemon-reload 2>/dev/null || true
}
# =============================================================================
# RUN SELECTED SECTIONS
# =============================================================================
[[ "$DO_ZSH" == true ]] && uninstall_zsh_font
[[ "$DO_DOCKER" == true ]] && uninstall_docker_portainer
# =============================================================================
# DONE
# =============================================================================
echo ""
echo -e "${LINE}"
echo -e "${BOLD}${GREEN} ✅ Uninstall complete!${RESET}"
echo -e "${LINE}"
[[ "$DO_ZSH" == true ]] && echo -e " ${CYAN}Zsh/Font:${RESET} removed — default shell reverted to bash"
[[ "$DO_DOCKER" == true ]] && echo -e " ${CYAN}Docker:${RESET} removed — log out and back in to clear group session"
echo -e " ${YELLOW}Log:${RESET} $LOG_FILE"
echo -e "${LINE}"
echo ""
if [[ "$DO_ZSH" == true ]]; then
echo -e " ${YELLOW}Note:${RESET} Log out and back in for shell change to take full effect."
fi
if [[ "$DO_DOCKER" == true ]]; then
echo -e " ${YELLOW}Note:${RESET} Log out and back in to clear docker group from your session."
fi
echo ""