wallarm/wallarm-ct-uninstall.sh
2026-03-24 14:16:47 +00:00

537 lines
No EOL
19 KiB
Bash

#!/bin/bash
# ==============================================================================
# WALLARM UNINSTALL SCRIPT - V1.0
# ==============================================================================
# Purpose: Safely remove Wallarm filtering node and cleanup Docker installation
# Features:
# - Interactive confirmation with safety checks
# - Stops and removes Wallarm container and image
# - Removes Docker service files created by deployment script
# - Optional cleanup of Docker binaries (if no other containers exist)
# - Preserves user data and logs (with option to remove)
# - DAU-friendly warnings and confirmations
# ==============================================================================
# Color definitions for better UX
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[1;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Strict error handling
set -euo pipefail
# Simple error handler for early failures (before log_message is defined)
early_error_handler() {
echo -e "${RED}${BOLD}[ERROR]${NC} Script failed at line $LINENO. Command: $BASH_COMMAND" >&2
exit 1
}
trap early_error_handler ERR
# Logging function
log_message() {
local level="$1"
local message="$2"
local timestamp
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
case "$level" in
"INFO") color="${BLUE}" ;;
"SUCCESS") color="${GREEN}" ;;
"WARNING") color="${YELLOW}" ;;
"ERROR") color="${RED}" ;;
"DEBUG") color="${CYAN}" ;;
*) color="${NC}" ;;
esac
echo -e "${color}[${timestamp}] ${level}: ${message}${NC}" >&2
}
# Ask for confirmation
confirm() {
local prompt="$1"
local default="${2:-n}"
local options="[y/N]"
if [ "$default" = "y" ]; then
options="[Y/n]"
fi
echo -e -n "${YELLOW}${prompt} ${options}${NC} "
read -r response
case "$response" in
[yY][eE][sS]|[yY])
return 0
;;
[nN][oO]|[nN])
return 1
;;
"")
# Use default
if [ "$default" = "y" ]; then
return 0
else
return 1
fi
;;
*)
# Invalid input, treat as no
return 1
;;
esac
}
# Check if running as root or with sudo
check_sudo() {
if [ "$EUID" -ne 0 ]; then
log_message "INFO" "This script requires sudo privileges"
if ! sudo -n true 2>/dev/null; then
log_message "INFO" "Please enter your sudo password when prompted"
sudo -v
fi
fi
}
# Detect init system
detect_init_system() {
if command -v systemctl >/dev/null 2>&1 && systemctl --version >/dev/null 2>&1; then
echo "systemd"
elif [ -d /run/openrc ]; then
echo "openrc"
elif [ -f /etc/init.d/docker ]; then
echo "sysvinit"
else
echo "unknown"
fi
}
# Check if Docker is installed and running
check_docker() {
if ! command -v docker >/dev/null 2>&1; then
log_message "WARNING" "Docker command not found"
return 1
fi
if ! sudo docker info >/dev/null 2>&1; then
log_message "WARNING" "Docker is not running"
return 1
fi
return 0
}
# Check for other Docker containers (besides Wallarm)
check_other_containers() {
local wallarm_container="wallarm-node"
local all_containers
all_containers=$(sudo docker ps -a -q 2>/dev/null | wc -l)
local wallarm_containers
wallarm_containers=$(sudo docker ps -a --filter "name=${wallarm_container}" -q 2>/dev/null | wc -l)
if [ "$all_containers" -gt "$wallarm_containers" ]; then
log_message "WARNING" "Found other Docker containers besides Wallarm"
sudo docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}" | grep -v "$wallarm_container" || true
return 0 # Other containers exist
fi
return 1 # Only Wallarm containers or no containers
}
# Stop and remove Wallarm container
remove_wallarm_container() {
local container_name="wallarm-node"
log_message "INFO" "Looking for Wallarm container..."
if sudo docker ps -a --filter "name=${container_name}" --format "{{.Names}}" | grep -q "${container_name}"; then
log_message "INFO" "Found Wallarm container: ${container_name}"
# Stop container if running
if sudo docker ps --filter "name=${container_name}" --filter "status=running" --format "{{.Names}}" | grep -q "${container_name}"; then
log_message "INFO" "Stopping Wallarm container..."
sudo docker stop "${container_name}" || {
log_message "WARNING" "Failed to stop container, attempting force stop"
sudo docker kill "${container_name}" 2>/dev/null || true
}
fi
# Remove container
log_message "INFO" "Removing Wallarm container..."
sudo docker rm -f "${container_name}" 2>/dev/null || {
log_message "WARNING" "Failed to remove container, it may already be removed"
}
log_message "SUCCESS" "Wallarm container removed"
else
log_message "INFO" "No Wallarm container found"
fi
}
# Remove Wallarm image
remove_wallarm_image() {
local image_name="wallarm/node"
log_message "INFO" "Looking for Wallarm image..."
if sudo docker images --format "{{.Repository}}" | grep -q "^${image_name}"; then
log_message "INFO" "Found Wallarm image: ${image_name}"
# Check if image is used by any containers
local used_by
used_by=$(sudo docker ps -a --filter "ancestor=${image_name}" -q 2>/dev/null | wc -l)
if [ "$used_by" -gt 0 ]; then
log_message "WARNING" "Image ${image_name} is still in use by containers, skipping removal"
return
fi
# Remove image
log_message "INFO" "Removing Wallarm image..."
sudo docker rmi "${image_name}:latest" 2>/dev/null || {
log_message "WARNING" "Failed to remove image, it may be in use or already removed"
}
# Also try to remove by ID if tag removal failed
local image_id
image_id=$(sudo docker images --filter "reference=${image_name}" --format "{{.ID}}" 2>/dev/null | head -1)
if [ -n "$image_id" ]; then
sudo docker rmi -f "$image_id" 2>/dev/null || true
fi
log_message "SUCCESS" "Wallarm image removed"
else
log_message "INFO" "No Wallarm image found"
fi
}
# Remove Docker service files (created by deployment script)
remove_docker_service_files() {
local init_system
init_system=$(detect_init_system)
log_message "INFO" "Removing Docker service files for init system: ${init_system}"
case "$init_system" in
"systemd")
# Stop and disable Docker service
if sudo systemctl is-active docker --quiet 2>/dev/null; then
log_message "INFO" "Stopping Docker service..."
sudo systemctl stop docker 2>/dev/null || true
fi
if sudo systemctl is-enabled docker --quiet 2>/dev/null; then
log_message "INFO" "Disabling Docker service..."
sudo systemctl disable docker 2>/dev/null || true
fi
# Remove systemd unit files (if they exist and were created by our script)
local systemd_files=(
"/etc/systemd/system/docker.socket"
"/etc/systemd/system/docker.service"
"/usr/lib/systemd/system/docker.socket"
"/usr/lib/systemd/system/docker.service"
)
for file in "${systemd_files[@]}"; do
if [ -f "$file" ]; then
log_message "INFO" "Removing systemd file: $file"
sudo rm -f "$file"
fi
done
sudo systemctl daemon-reload 2>/dev/null || true
;;
"openrc")
# Stop and remove from runlevels
if sudo rc-service docker status 2>/dev/null | grep -q "started"; then
log_message "INFO" "Stopping Docker service (OpenRC)..."
sudo rc-service docker stop 2>/dev/null || true
fi
if [ -f /etc/init.d/docker ]; then
log_message "INFO" "Removing OpenRC init script..."
sudo rc-update del docker default 2>/dev/null || true
sudo rm -f /etc/init.d/docker
fi
;;
"sysvinit")
# Stop service
if [ -f /etc/init.d/docker ]; then
log_message "INFO" "Stopping Docker service (SysV init)..."
sudo service docker stop 2>/dev/null || true
# Remove from startup
if command -v update-rc.d >/dev/null 2>&1; then
sudo update-rc.d -f docker remove 2>/dev/null || true
elif command -v chkconfig >/dev/null 2>&1; then
sudo chkconfig --del docker 2>/dev/null || true
fi
log_message "INFO" "Removing SysV init script..."
sudo rm -f /etc/init.d/docker
fi
;;
*)
log_message "WARNING" "Unknown init system, skipping service file cleanup"
;;
esac
log_message "SUCCESS" "Docker service files removed"
}
# Remove Docker binaries (optional, only if no other containers exist)
remove_docker_binaries() {
local docker_binaries=(
"/usr/bin/docker"
"/usr/bin/dockerd"
"/usr/bin/docker-init"
"/usr/bin/docker-proxy"
"/usr/bin/containerd"
"/usr/bin/containerd-shim"
"/usr/bin/containerd-shim-runc-v1"
"/usr/bin/containerd-shim-runc-v2"
"/usr/bin/runc"
)
log_message "INFO" "Checking Docker binaries..."
local binaries_found=0
for binary in "${docker_binaries[@]}"; do
if [ -f "$binary" ]; then
binaries_found=$((binaries_found + 1))
fi
done
if [ "$binaries_found" -eq 0 ]; then
log_message "INFO" "No Docker binaries found in /usr/bin/"
return
fi
if confirm "Remove Docker binaries from /usr/bin/? (Only do this if Docker was installed by wallarm-ct-deploy.sh)" "n"; then
log_message "WARNING" "Removing Docker binaries..."
for binary in "${docker_binaries[@]}"; do
if [ -f "$binary" ]; then
log_message "INFO" "Removing $binary"
sudo rm -f "$binary"
fi
done
# Also remove CNI plugins if they exist
if [ -d "/opt/cni/bin" ]; then
log_message "INFO" "Removing CNI plugins from /opt/cni/bin/"
sudo rm -rf /opt/cni/bin/*
fi
log_message "SUCCESS" "Docker binaries removed"
else
log_message "INFO" "Skipping Docker binary removal"
fi
}
# Remove Docker configuration files
remove_docker_config() {
local config_files=(
"/etc/docker/daemon.json"
"/etc/containerd/config.toml"
"/var/lib/docker" # Warning: This removes all Docker data!
)
log_message "INFO" "Checking Docker configuration files..."
# Only remove daemon.json if it was created by our script
if [ -f "/etc/docker/daemon.json" ]; then
log_message "INFO" "Found /etc/docker/daemon.json"
if grep -q "storage-driver.*vfs" "/etc/docker/daemon.json" 2>/dev/null; then
log_message "INFO" "This appears to be the VFS configuration from wallarm-ct-deploy.sh"
if confirm "Remove /etc/docker/daemon.json?" "n"; then
sudo rm -f "/etc/docker/daemon.json"
log_message "SUCCESS" "Docker configuration removed"
fi
else
log_message "WARNING" "/etc/docker/daemon.json doesn't appear to be from wallarm-ct-deploy.sh, skipping"
fi
fi
# Warn about Docker data directory
if [ -d "/var/lib/docker" ]; then
log_message "WARNING" "/var/lib/docker contains Docker data (images, containers, volumes)"
log_message "WARNING" "Removing this directory will delete ALL Docker data on the system"
if confirm "Remove /var/lib/docker? (WARNING: Deletes ALL Docker data)" "n"; then
log_message "WARNING" "Removing /var/lib/docker - this may take a while..."
sudo rm -rf /var/lib/docker
log_message "SUCCESS" "Docker data directory removed"
fi
fi
}
# Remove docker group (if empty)
remove_docker_group() {
log_message "INFO" "Checking docker group..."
if getent group docker >/dev/null; then
local group_users
group_users=$(getent group docker | cut -d: -f4)
if [ -z "$group_users" ]; then
log_message "INFO" "Docker group exists and has no users"
if confirm "Remove docker group?" "n"; then
sudo groupdel docker 2>/dev/null || {
log_message "WARNING" "Failed to remove docker group (may be system group)"
}
log_message "SUCCESS" "Docker group removed"
fi
else
log_message "WARNING" "Docker group has users: $group_users"
log_message "INFO" "Skipping docker group removal (users still present)"
fi
else
log_message "INFO" "Docker group not found"
fi
}
# Remove Wallarm-specific files and logs
remove_wallarm_files() {
local wallarm_files=(
"$HOME/wallarm-start.sh"
"$HOME/wallarm-stop.sh"
"$HOME/wallarm-status.sh"
"/usr/local/bin/wallarm-start"
"/usr/local/bin/wallarm-stop"
"/usr/local/bin/wallarm-status"
)
log_message "INFO" "Removing Wallarm scripts and logs..."
# Remove scripts
for file in "${wallarm_files[@]}"; do
if [ -f "$file" ]; then
log_message "INFO" "Removing $file"
sudo rm -f "$file"
fi
done
# Remove log directory (if empty)
local log_dir="$HOME/logs"
if [ -d "$log_dir" ]; then
log_message "INFO" "Found log directory: $log_dir"
if [ -z "$(ls -A "$log_dir" 2>/dev/null)" ]; then
log_message "INFO" "Log directory is empty, removing..."
sudo rmdir "$log_dir" 2>/dev/null || true
else
log_message "INFO" "Log directory contains files, preserving..."
fi
fi
# Remove .env file if it exists
if [ -f ".env" ]; then
log_message "INFO" "Removing .env file..."
rm -f ".env"
fi
log_message "SUCCESS" "Wallarm files cleaned up"
}
# Main uninstall function
main() {
echo -e "${CYAN}${BOLD}"
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ WALLARM UNINSTALLATION ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo -e "${NC}"
echo -e "${YELLOW}This script will remove Wallarm filtering node and cleanup Docker installation.${NC}"
echo -e "${YELLOW}You will be asked for confirmation before each destructive operation.${NC}"
echo ""
if ! confirm "Do you want to continue with the uninstallation?" "n"; then
log_message "INFO" "Uninstallation cancelled by user"
exit 0
fi
# Check sudo
check_sudo
# Check Docker
if check_docker; then
log_message "INFO" "Docker is installed and running"
# Check for other containers
if check_other_containers; then
log_message "WARNING" "Other Docker containers exist on this system"
echo -e "${YELLOW}Warning: Removing Docker may affect other containers.${NC}"
echo -e "${YELLOW}Consider leaving Docker installed if you need it for other purposes.${NC}"
echo ""
fi
else
log_message "WARNING" "Docker is not running or not installed"
fi
# Step 1: Remove Wallarm container and image
echo ""
echo -e "${CYAN}${BOLD}Step 1: Remove Wallarm container and image${NC}"
if confirm "Stop and remove Wallarm container and image?" "y"; then
remove_wallarm_container
remove_wallarm_image
else
log_message "INFO" "Skipping Wallarm container/image removal"
fi
# Step 2: Remove Docker service files
echo ""
echo -e "${CYAN}${BOLD}Step 2: Remove Docker service files${NC}"
if confirm "Remove Docker service files (systemd/OpenRC/SysV init scripts)?" "y"; then
remove_docker_service_files
else
log_message "INFO" "Skipping Docker service file removal"
fi
# Step 3: Optional Docker binary removal
echo ""
echo -e "${CYAN}${BOLD}Step 3: Docker binaries and configuration${NC}"
remove_docker_binaries
remove_docker_config
# Step 4: Remove docker group
echo ""
echo -e "${CYAN}${BOLD}Step 4: System cleanup${NC}"
remove_docker_group
# Step 5: Remove Wallarm files
echo ""
echo -e "${CYAN}${BOLD}Step 5: Wallarm files and logs${NC}"
if confirm "Remove Wallarm scripts and log files?" "y"; then
remove_wallarm_files
else
log_message "INFO" "Skipping Wallarm file cleanup"
fi
# Final message
echo ""
echo -e "${GREEN}${BOLD}╔══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}${BOLD}║ UNINSTALLATION COMPLETE ║${NC}"
echo -e "${GREEN}${BOLD}╚══════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${GREEN}Wallarm filtering node has been removed.${NC}"
echo ""
echo -e "${YELLOW}Note:${NC}"
echo -e " • Docker may still be installed on your system"
echo -e " • Docker data in /var/lib/docker may still exist"
echo -e " • User may still be in docker group (check with 'groups')"
echo ""
echo -e "To completely remove Docker, you may need to:"
echo -e " 1. Remove Docker package using your system's package manager"
echo -e " 2. Remove /var/lib/docker directory (contains all Docker data)"
echo -e " 3. Remove user from docker group: sudo gpasswd -d \$USER docker"
echo ""
}
# Run main function
main "$@"