d351b6030e
- Changed macOS deployment directory from ~/homelab/ to ~/hops/ - Updated all core scripts to use new path structure: • Main working directory: ~/hops/ • Config directory: ~/hops/config/ • Media directory: ~/hops/media/ • Environment file: ~/hops/.env - Updated documentation in CLAUDE.md and README.md - Changed log file naming from homelab-* to hops-* - Linux paths remain unchanged (/opt/appdata, /mnt/media) Benefits: - Better brand consistency with project name - Cleaner, more professional directory structure - Shorter, easier to remember paths - Immediately obvious what directory belongs to HOPS 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
560 lines
22 KiB
Bash
Executable File
560 lines
22 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
uninstall_hops() {
|
||
# Clear terminal at startup
|
||
clear
|
||
|
||
# Exit on any error (but allow some failures during cleanup)
|
||
set +e
|
||
|
||
# Script version for consistency
|
||
local SCRIPT_VERSION="3.1.0"
|
||
|
||
# --------------------------------------------
|
||
# LOGGING SETUP
|
||
# --------------------------------------------
|
||
local LOG_DIR="/var/log/hops"
|
||
local LOG_FILE="$LOG_DIR/hops-uninstall-$(date +%Y%m%d-%H%M%S).log"
|
||
mkdir -p "$LOG_DIR"
|
||
touch "$LOG_FILE"
|
||
|
||
log() {
|
||
echo -e "$(date '+%Y-%m-%d %T') - $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
error_exit() {
|
||
log "❌ ERROR: $1"
|
||
log "❌ Uninstallation failed. Check logs at: $LOG_FILE"
|
||
exit 1
|
||
}
|
||
|
||
warning() {
|
||
log "⚠️ WARNING: $1"
|
||
}
|
||
|
||
# --------------------------------------------
|
||
# HEADER
|
||
# --------------------------------------------
|
||
cat << "EOF"
|
||
|
||
_ _ ____ ____ ____
|
||
| | | || _ \| _ \/ ___|
|
||
| |__| || |_) | |_) \___ \
|
||
| __ || __/| __/ ___) |
|
||
|_| |_||_| |_| |____/
|
||
|
||
EOF
|
||
echo -e "🗑️ Homelab Orchestration Provisioning Script - UNINSTALLER v${SCRIPT_VERSION}\n"
|
||
log "🗑️ Starting HOPS Uninstallation v${SCRIPT_VERSION}"
|
||
|
||
# --------------------------------------------
|
||
# ROOT CHECK
|
||
# --------------------------------------------
|
||
if [[ $EUID -ne 0 ]]; then
|
||
error_exit "This script must be run as root or with sudo."
|
||
fi
|
||
|
||
# --------------------------------------------
|
||
# CONFIRMATION PROMPT
|
||
# --------------------------------------------
|
||
show_uninstall_warning() {
|
||
echo -e "⚠️ WARNING: This will completely remove your HOPS installation!"
|
||
echo -e "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
echo -e "This uninstaller will:"
|
||
echo -e " • Stop and remove all Docker containers"
|
||
echo -e " • Remove Docker images (optional)"
|
||
echo -e " • Remove Docker Compose configuration"
|
||
echo -e " • Clean up application data (optional)"
|
||
echo -e " • Remove firewall rules"
|
||
echo -e " • Uninstall Docker (optional)"
|
||
echo -e ""
|
||
echo -e "⚠️ YOUR MEDIA FILES WILL NOT BE DELETED"
|
||
echo -e "⚠️ APPLICATION DATA REMOVAL IS OPTIONAL"
|
||
echo -e "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
}
|
||
|
||
get_uninstall_options() {
|
||
echo -e "\n🔧 Uninstall Options:"
|
||
|
||
# Container and compose removal (always done)
|
||
REMOVE_CONTAINERS=true
|
||
REMOVE_COMPOSE=true
|
||
|
||
# Optional removals
|
||
echo -e "\n❓ Remove Docker images? (saves disk space but requires re-download) [y/N]: "
|
||
read -r remove_images
|
||
REMOVE_IMAGES=false
|
||
[[ "$remove_images" =~ ^[Yy]$ ]] && REMOVE_IMAGES=true
|
||
|
||
echo -e "\n❓ Remove application data? (⚠️ DELETES ALL CONFIGURATIONS!) [y/N]: "
|
||
read -r remove_appdata
|
||
REMOVE_APPDATA=false
|
||
[[ "$remove_appdata" =~ ^[Yy]$ ]] && REMOVE_APPDATA=true
|
||
|
||
echo -e "\n❓ Uninstall Docker completely? [y/N]: "
|
||
read -r remove_docker
|
||
REMOVE_DOCKER=false
|
||
[[ "$remove_docker" =~ ^[Yy]$ ]] && REMOVE_DOCKER=true
|
||
|
||
echo -e "\n❓ Remove firewall rules? [Y/n]: "
|
||
read -r remove_firewall
|
||
REMOVE_FIREWALL=true
|
||
[[ "$remove_firewall" =~ ^[Nn]$ ]] && REMOVE_FIREWALL=false
|
||
|
||
# Final confirmation
|
||
echo -e "\n⚠️ FINAL CONFIRMATION"
|
||
echo -e "━━━━━━━━━━━━━━━━━━━━━━━"
|
||
echo -e "Actions to perform:"
|
||
echo -e " • Remove containers: ✅"
|
||
echo -e " • Remove compose files: ✅"
|
||
[[ $REMOVE_IMAGES == true ]] && echo -e " • Remove Docker images: ✅" || echo -e " • Remove Docker images: ❌"
|
||
[[ $REMOVE_APPDATA == true ]] && echo -e " • Remove app data: ✅" || echo -e " • Remove app data: ❌"
|
||
[[ $REMOVE_DOCKER == true ]] && echo -e " • Uninstall Docker: ✅" || echo -e " • Uninstall Docker: ❌"
|
||
[[ $REMOVE_FIREWALL == true ]] && echo -e " • Remove firewall rules: ✅" || echo -e " • Remove firewall rules: ❌"
|
||
|
||
echo -e "\n❓ Proceed with uninstallation? [y/N]: "
|
||
read -r final_confirm
|
||
if [[ ! "$final_confirm" =~ ^[Yy]$ ]]; then
|
||
log "🚫 Uninstallation cancelled by user"
|
||
exit 0
|
||
fi
|
||
}
|
||
|
||
# --------------------------------------------
|
||
# HOMELAB DIRECTORY DETECTION
|
||
# --------------------------------------------
|
||
find_homelab_directory() {
|
||
local POSSIBLE_DIRS=(
|
||
"$HOME/hops"
|
||
"/home/*/hops"
|
||
"/opt/hops"
|
||
"/srv/hops"
|
||
)
|
||
|
||
# Try to find from running user's home first
|
||
if [[ -n "$SUDO_USER" ]]; then
|
||
local user_home=$(eval echo "~$SUDO_USER")
|
||
POSSIBLE_DIRS=("$user_home/hops" "${POSSIBLE_DIRS[@]}")
|
||
fi
|
||
|
||
HOMELAB_DIR=""
|
||
for dir in "${POSSIBLE_DIRS[@]}"; do
|
||
if [[ -f "$dir/docker-compose.yml" ]]; then
|
||
HOMELAB_DIR="$dir"
|
||
log "✅ Found homelab directory: $HOMELAB_DIR"
|
||
break
|
||
fi
|
||
done
|
||
|
||
if [[ -z "$HOMELAB_DIR" ]]; then
|
||
echo -e "\n📂 Could not auto-detect homelab directory."
|
||
echo -e "Please enter the path to your homelab directory (contains docker-compose.yml):"
|
||
read -r user_dir
|
||
|
||
if [[ -f "$user_dir/docker-compose.yml" ]]; then
|
||
HOMELAB_DIR="$user_dir"
|
||
log "✅ Using homelab directory: $HOMELAB_DIR"
|
||
else
|
||
warning "No docker-compose.yml found in $user_dir"
|
||
log "📝 Will proceed with container cleanup by name instead"
|
||
fi
|
||
fi
|
||
|
||
# Set APPDATA_DIR from env file if available
|
||
if [[ -f "$HOMELAB_DIR/.env" ]]; then
|
||
APPDATA_DIR=$(grep "^CONFIG_ROOT=" "$HOMELAB_DIR/.env" | cut -d= -f2)
|
||
log "📁 Found appdata directory: $APPDATA_DIR"
|
||
fi
|
||
}
|
||
|
||
# --------------------------------------------
|
||
# SERVICE DETECTION
|
||
# --------------------------------------------
|
||
detect_running_services() {
|
||
log "🔍 Detecting running HOPS services..."
|
||
|
||
# Known HOPS service names
|
||
local KNOWN_SERVICES=(
|
||
"sonarr" "radarr" "lidarr" "readarr" "bazarr" "prowlarr" "tdarr"
|
||
"nzbget" "sabnzbd" "transmission" "qbittorrent"
|
||
"plex" "jellyfin" "emby" "jellystat" "jellystat-db"
|
||
"overseerr" "jellyseerr" "ombi"
|
||
"traefik" "nginx-proxy-manager" "authelia"
|
||
"portainer" "watchtower" "uptime-kuma"
|
||
"postgres" "redis"
|
||
)
|
||
|
||
DETECTED_SERVICES=()
|
||
for service in "${KNOWN_SERVICES[@]}"; do
|
||
if docker ps -a --format "{{.Names}}" | grep -q "^${service}$"; then
|
||
DETECTED_SERVICES+=("$service")
|
||
fi
|
||
done
|
||
|
||
if [[ ${#DETECTED_SERVICES[@]} -gt 0 ]]; then
|
||
log "✅ Detected services: ${DETECTED_SERVICES[*]}"
|
||
else
|
||
log "⚠️ No HOPS services detected"
|
||
fi
|
||
}
|
||
|
||
# --------------------------------------------
|
||
# CONTAINER CLEANUP
|
||
# --------------------------------------------
|
||
stop_and_remove_containers() {
|
||
log "🛑 Stopping and removing containers..."
|
||
|
||
if [[ -n "$HOMELAB_DIR" && -f "$HOMELAB_DIR/docker-compose.yml" ]]; then
|
||
cd "$HOMELAB_DIR"
|
||
|
||
# Stop services gracefully
|
||
log "🔄 Stopping services with docker compose..."
|
||
if docker compose ps -q | grep -q .; then
|
||
if ! docker compose down --timeout 30 2>&1 | tee -a "$LOG_FILE"; then
|
||
warning "Docker compose down failed, attempting force removal"
|
||
docker compose down --timeout 10 --remove-orphans --volumes 2>&1 | tee -a "$LOG_FILE" || true
|
||
fi
|
||
else
|
||
log "ℹ️ No running compose services found"
|
||
fi
|
||
fi
|
||
|
||
# Fallback: Remove containers by name
|
||
if [[ ${#DETECTED_SERVICES[@]} -gt 0 ]]; then
|
||
log "🧹 Cleaning up remaining containers..."
|
||
for service in "${DETECTED_SERVICES[@]}"; do
|
||
if docker ps -a --format "{{.Names}}" | grep -q "^${service}$"; then
|
||
log "🗑️ Removing container: $service"
|
||
docker stop "$service" 2>/dev/null || true
|
||
docker rm -f "$service" 2>/dev/null || true
|
||
fi
|
||
done
|
||
fi
|
||
|
||
log "✅ Container cleanup complete"
|
||
}
|
||
|
||
# --------------------------------------------
|
||
# IMAGE CLEANUP
|
||
# --------------------------------------------
|
||
remove_docker_images() {
|
||
if [[ $REMOVE_IMAGES == true ]]; then
|
||
log "🗑️ Removing Docker images..."
|
||
|
||
# Common HOPS images
|
||
local HOPS_IMAGES=(
|
||
"lscr.io/linuxserver/sonarr"
|
||
"lscr.io/linuxserver/radarr"
|
||
"lscr.io/linuxserver/lidarr"
|
||
"lscr.io/linuxserver/readarr"
|
||
"lscr.io/linuxserver/bazarr"
|
||
"lscr.io/linuxserver/prowlarr"
|
||
"ghcr.io/haveagitgat/tdarr"
|
||
"lscr.io/linuxserver/nzbget"
|
||
"lscr.io/linuxserver/sabnzbd"
|
||
"lscr.io/linuxserver/transmission"
|
||
"lscr.io/linuxserver/qbittorrent"
|
||
"plexinc/pms-docker"
|
||
"jellyfin/jellyfin"
|
||
"emby/embyserver"
|
||
"sctx/overseerr"
|
||
"fallenbagel/jellyseerr"
|
||
"lscr.io/linuxserver/ombi"
|
||
"traefik"
|
||
"jc21/nginx-proxy-manager"
|
||
"authelia/authelia"
|
||
"portainer/portainer-ce"
|
||
"containrrr/watchtower"
|
||
"louislam/uptime-kuma"
|
||
"postgres"
|
||
"redis"
|
||
"cyfershepard/jellystat"
|
||
)
|
||
|
||
for image in "${HOPS_IMAGES[@]}"; do
|
||
if docker images --format "{{.Repository}}" | grep -q "^${image}$"; then
|
||
log "🗑️ Removing image: $image"
|
||
docker rmi -f "$image" 2>/dev/null || true
|
||
fi
|
||
done
|
||
|
||
# Clean up dangling images
|
||
log "🧹 Cleaning up dangling images..."
|
||
docker image prune -f 2>/dev/null || true
|
||
|
||
log "✅ Image cleanup complete"
|
||
else
|
||
log "⏭️ Skipping image removal"
|
||
fi
|
||
}
|
||
|
||
# --------------------------------------------
|
||
# NETWORK CLEANUP
|
||
# --------------------------------------------
|
||
cleanup_networks() {
|
||
log "🌐 Cleaning up Docker networks..."
|
||
|
||
local HOPS_NETWORKS=("homelab" "traefik" "database")
|
||
|
||
for network in "${HOPS_NETWORKS[@]}"; do
|
||
if docker network ls --format "{{.Name}}" | grep -q "^${network}$"; then
|
||
log "🗑️ Removing network: $network"
|
||
docker network rm "$network" 2>/dev/null || warning "Could not remove network: $network"
|
||
fi
|
||
done
|
||
|
||
log "✅ Network cleanup complete"
|
||
}
|
||
|
||
# --------------------------------------------
|
||
# VOLUME CLEANUP
|
||
# --------------------------------------------
|
||
cleanup_volumes() {
|
||
log "💾 Cleaning up Docker volumes..."
|
||
|
||
local HOPS_VOLUMES=("postgres_data" "redis_data")
|
||
|
||
for volume in "${HOPS_VOLUMES[@]}"; do
|
||
if docker volume ls --format "{{.Name}}" | grep -q "^${volume}$"; then
|
||
log "🗑️ Removing volume: $volume"
|
||
docker volume rm "$volume" 2>/dev/null || warning "Could not remove volume: $volume"
|
||
fi
|
||
done
|
||
|
||
# Clean up orphaned volumes
|
||
log "🧹 Cleaning up orphaned volumes..."
|
||
docker volume prune -f 2>/dev/null || true
|
||
|
||
log "✅ Volume cleanup complete"
|
||
}
|
||
|
||
# --------------------------------------------
|
||
# FILE CLEANUP
|
||
# --------------------------------------------
|
||
cleanup_compose_files() {
|
||
if [[ $REMOVE_COMPOSE == true && -n "$HOMELAB_DIR" ]]; then
|
||
log "📝 Removing Docker Compose files..."
|
||
|
||
cd "$HOMELAB_DIR"
|
||
|
||
# Backup before removal
|
||
if [[ -f docker-compose.yml ]]; then
|
||
local BACKUP_FILE="docker-compose.yml.removed.$(date +%Y%m%d%H%M%S)"
|
||
log "📦 Backing up compose file to: $BACKUP_FILE"
|
||
cp docker-compose.yml "$BACKUP_FILE" 2>/dev/null || warning "Could not backup compose file"
|
||
rm -f docker-compose.yml
|
||
fi
|
||
|
||
# Remove other compose-related files
|
||
rm -f docker-compose.override.yml .env 2>/dev/null || true
|
||
|
||
# Remove empty homelab directory if it's empty
|
||
cd ..
|
||
if [[ -d "$HOMELAB_DIR" ]]; then
|
||
rmdir "$HOMELAB_DIR" 2>/dev/null && log "📁 Removed empty homelab directory" || log "📁 Homelab directory not empty, keeping it"
|
||
fi
|
||
|
||
log "✅ Compose file cleanup complete"
|
||
else
|
||
log "⏭️ Skipping compose file removal"
|
||
fi
|
||
}
|
||
|
||
cleanup_appdata() {
|
||
if [[ $REMOVE_APPDATA == true && -n "$APPDATA_DIR" ]]; then
|
||
log "🗂️ Removing application data..."
|
||
|
||
echo -e "\n⚠️ FINAL WARNING: This will delete ALL application configurations!"
|
||
echo -e "Application data directory: $APPDATA_DIR"
|
||
echo -e "❓ Are you absolutely sure? Type 'DELETE' to confirm: "
|
||
read -r delete_confirm
|
||
|
||
if [[ "$delete_confirm" == "DELETE" ]]; then
|
||
# Create a backup first
|
||
local BACKUP_DIR="/tmp/hops-appdata-backup-$(date +%Y%m%d%H%M%S)"
|
||
log "📦 Creating backup at: $BACKUP_DIR"
|
||
|
||
if cp -r "$APPDATA_DIR" "$BACKUP_DIR" 2>/dev/null; then
|
||
log "✅ Backup created successfully"
|
||
|
||
# Remove the original
|
||
if rm -rf "$APPDATA_DIR" 2>/dev/null; then
|
||
log "✅ Application data removed"
|
||
log "📦 Backup available at: $BACKUP_DIR"
|
||
else
|
||
warning "Failed to remove application data directory"
|
||
fi
|
||
else
|
||
warning "Could not create backup, skipping appdata removal"
|
||
fi
|
||
else
|
||
log "🚫 Application data removal cancelled"
|
||
fi
|
||
else
|
||
log "⏭️ Skipping application data removal"
|
||
fi
|
||
}
|
||
|
||
# --------------------------------------------
|
||
# FIREWALL CLEANUP
|
||
# --------------------------------------------
|
||
cleanup_firewall() {
|
||
if [[ $REMOVE_FIREWALL == true ]]; then
|
||
log "🔥 Removing firewall rules..."
|
||
|
||
if command -v ufw &>/dev/null; then
|
||
# Remove HOPS-specific rules by searching for comments
|
||
local rules_to_remove=()
|
||
|
||
# Get numbered rules that contain HOPS service names
|
||
mapfile -t rules_to_remove < <(ufw status numbered | grep -E "(sonarr|radarr|lidarr|readarr|bazarr|prowlarr|jellyfin|plex|portainer|traefik|npm)" | awk '{print $1}' | tr -d '[]')
|
||
|
||
# Remove rules in reverse order to maintain numbering
|
||
if [[ ${#rules_to_remove[@]} -gt 0 ]]; then
|
||
for ((i=${#rules_to_remove[@]}-1; i>=0; i--)); do
|
||
local rule_num="${rules_to_remove[i]}"
|
||
log "🗑️ Removing firewall rule #$rule_num"
|
||
echo "y" | ufw delete "$rule_num" 2>/dev/null || true
|
||
done
|
||
fi
|
||
|
||
log "✅ Firewall cleanup complete"
|
||
else
|
||
log "ℹ️ UFW not installed, skipping firewall cleanup"
|
||
fi
|
||
else
|
||
log "⏭️ Skipping firewall cleanup"
|
||
fi
|
||
}
|
||
|
||
# --------------------------------------------
|
||
# DOCKER UNINSTALLATION
|
||
# --------------------------------------------
|
||
uninstall_docker() {
|
||
if [[ $REMOVE_DOCKER == true ]]; then
|
||
log "🐳 Uninstalling Docker..."
|
||
|
||
# Stop Docker service
|
||
systemctl stop docker 2>/dev/null || true
|
||
systemctl disable docker 2>/dev/null || true
|
||
|
||
# Remove Docker packages
|
||
local DOCKER_PACKAGES=(
|
||
"docker-ce" "docker-ce-cli" "containerd.io" "docker-buildx-plugin"
|
||
"docker-compose-plugin" "docker.io" "docker-doc" "docker-compose"
|
||
"podman-docker" "containerd" "runc"
|
||
)
|
||
|
||
for package in "${DOCKER_PACKAGES[@]}"; do
|
||
if dpkg -l | grep -q "^ii.*$package"; then
|
||
log "🗑️ Removing package: $package"
|
||
apt-get remove -y "$package" 2>/dev/null || true
|
||
fi
|
||
done
|
||
|
||
# Clean up Docker directories
|
||
log "🗑️ Removing Docker directories..."
|
||
rm -rf /var/lib/docker /etc/docker /var/run/docker.sock 2>/dev/null || true
|
||
rm -rf ~/.docker 2>/dev/null || true
|
||
|
||
# Remove from user directories too
|
||
if [[ -n "$SUDO_USER" ]]; then
|
||
local user_home=$(eval echo "~$SUDO_USER")
|
||
rm -rf "$user_home/.docker" 2>/dev/null || true
|
||
fi
|
||
|
||
# Remove Docker group
|
||
if getent group docker &>/dev/null; then
|
||
groupdel docker 2>/dev/null || warning "Could not remove docker group"
|
||
fi
|
||
|
||
# Clean up package cache
|
||
apt-get autoremove -y 2>/dev/null || true
|
||
apt-get autoclean 2>/dev/null || true
|
||
|
||
log "✅ Docker uninstallation complete"
|
||
else
|
||
log "⏭️ Skipping Docker uninstallation"
|
||
fi
|
||
}
|
||
|
||
# --------------------------------------------
|
||
# CLEANUP LOG FILES
|
||
# --------------------------------------------
|
||
cleanup_logs() {
|
||
log "📋 Cleaning up HOPS log files..."
|
||
|
||
# Keep current log file, remove others
|
||
find "$LOG_DIR" -name "homelab-*.log" -not -name "$(basename "$LOG_FILE")" -delete 2>/dev/null || true
|
||
|
||
# Remove log directory if empty (except current log)
|
||
local remaining_logs=$(find "$LOG_DIR" -name "*.log" | wc -l)
|
||
if [[ $remaining_logs -le 1 ]]; then
|
||
log "📁 Log directory will be cleaned after this session"
|
||
fi
|
||
|
||
log "✅ Log cleanup complete"
|
||
}
|
||
|
||
# --------------------------------------------
|
||
# MAIN UNINSTALLATION FLOW
|
||
# --------------------------------------------
|
||
show_uninstall_warning
|
||
get_uninstall_options
|
||
|
||
log "🚀 Starting HOPS uninstallation process..."
|
||
|
||
find_homelab_directory
|
||
detect_running_services
|
||
|
||
# Core cleanup steps
|
||
stop_and_remove_containers
|
||
remove_docker_images
|
||
cleanup_networks
|
||
cleanup_volumes
|
||
cleanup_compose_files
|
||
cleanup_appdata
|
||
cleanup_firewall
|
||
uninstall_docker
|
||
cleanup_logs
|
||
|
||
# --------------------------------------------
|
||
# FINAL SUMMARY
|
||
# --------------------------------------------
|
||
echo -e "\n✅ HOPS Uninstallation Complete!"
|
||
echo -e "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
|
||
log "📋 Uninstallation Summary:"
|
||
echo -e "\n🗑️ Removed Components:"
|
||
echo " • Docker containers: ✅"
|
||
echo " • Docker Compose files: ✅"
|
||
[[ $REMOVE_IMAGES == true ]] && echo " • Docker images: ✅" || echo " • Docker images: ❌ (kept)"
|
||
[[ $REMOVE_APPDATA == true ]] && echo " • Application data: ✅" || echo " • Application data: ❌ (kept)"
|
||
[[ $REMOVE_DOCKER == true ]] && echo " • Docker installation: ✅" || echo " • Docker installation: ❌ (kept)"
|
||
[[ $REMOVE_FIREWALL == true ]] && echo " • Firewall rules: ✅" || echo " • Firewall rules: ❌ (kept)"
|
||
|
||
echo -e "\n📂 Preserved:"
|
||
echo " • Media files: ✅ (never touched)"
|
||
[[ $REMOVE_APPDATA != true ]] && echo " • Application configurations: ✅"
|
||
|
||
if [[ $REMOVE_APPDATA == true ]]; then
|
||
echo -e "\n📦 Backup Location:"
|
||
echo " • Application data backup: /tmp/hops-appdata-backup-*"
|
||
echo " • Consider moving this backup to a permanent location"
|
||
fi
|
||
|
||
echo -e "\n📋 Complete log: $LOG_FILE"
|
||
echo -e "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
|
||
log "✅ HOPS uninstallation completed successfully!"
|
||
|
||
if [[ -n "$SUDO_USER" ]]; then
|
||
echo -e "\n💡 Note: You may want to restart your session to ensure all group changes take effect."
|
||
fi
|
||
|
||
if [[ $REMOVE_DOCKER == true ]]; then
|
||
echo -e "\n🔄 Recommendation: Reboot your system to complete Docker removal."
|
||
fi
|
||
|
||
return 0
|
||
} |