#!/bin/bash # Script to install Docker and CyberChef with verification and redeployment capabilities # Must be run with root privileges # Error handling set -e trap 'echo "Error on line $LINENO. Exit code: $?"' ERR # Configuration INSTALL_DIR="/docker/cyberchef" COMPOSE_FILE="${INSTALL_DIR}/docker-compose.yml" LOG_FILE="/var/log/cyberchef-install.log" CYBERCHEF_VERSION="latest" CONTAINER_NAME="cyberchef" # Utility functions check_port_availability() { local port=$1 if lsof -i ":$port" >/dev/null 2>&1; then local process_info=$(lsof -i ":$port" | tail -n 1) local pid=$(echo "$process_info" | awk '{print $2}') local process_name=$(echo "$process_info" | awk '{print $1}') log_message "⚠ Error: Port $port is already in use by process $process_name (PID: $pid)" return 1 fi return 0 } check_required_ports() { local required_ports=(8000) local ports_in_use=() for port in "${required_ports[@]}"; do if ! check_port_availability "$port"; then ports_in_use+=($port) fi done if [ ${#ports_in_use[@]} -ne 0 ]; then log_message "The following required ports are already in use: ${ports_in_use[*]}" log_message "Please free these ports before proceeding with the installation." log_message "You can either:" log_message "1. Stop the services using these ports" log_message "2. Modify the docker-compose.yml to use different ports" log_message "3. Run 'lsof -i :' to identify which process is using each port" return 1 fi log_message "✓ All required ports are available" return 0 } log_message() { local message="[$(date '+%Y-%m-%d %H:%M:%S')] $1" echo "$message" echo "$message" >> "$LOG_FILE" } show_container_status() { log_message "Current container status:" echo "----------------------------------------" docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}" echo "----------------------------------------" } check_service_status() { local container_name="cyberchef-web-1" # Check if container exists and is running if ! docker ps -q -f name="$container_name" >/dev/null 2>&1; then log_message "Container $container_name not found" return 1 fi local status=$(docker inspect -f '{{.State.Status}}' "$container_name" 2>/dev/null) if [ "$status" != "running" ]; then log_message "Container status is $status, expected running" return 1 fi # Give the nginx server inside container time to start local max_attempts=30 local attempt=1 local delay=2 while [ $attempt -le $max_attempts ]; do if curl -sf http://localhost:8000 >/dev/null 2>&1; then log_message "Web service is responding on port 8000" return 0 fi log_message "Waiting for web service to respond (attempt $attempt/$max_attempts)..." sleep $delay attempt=$((attempt + 1)) done log_message "Web service failed to respond after $max_attempts attempts" return 1 } verify_installation() { log_message "Verifying CyberChef installation..." if ! check_service_status; then log_message "CyberChef service is not running properly" return 1 fi log_message "CyberChef service is running properly" return 0 } check_docker_version() { local current_version=$(docker --version | cut -d ' ' -f3 | cut -d ',' -f1) log_message "Current Docker version: $current_version" # Check for updates apt-get update >/dev/null 2>&1 local available_version=$(apt-cache policy docker-ce | grep Candidate | cut -d ' ' -f4) if [ "$current_version" != "$available_version" ]; then log_message "New Docker version available: $available_version" read -p "Do you want to upgrade Docker? (y/N) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then apt-get install -y docker-ce docker-ce-cli containerd.io fi fi } redeploy_service() { log_message "Redeploying CyberChef..." cd "$INSTALL_DIR" docker compose down docker compose up -d # Wait for service to be healthy local retries=0 while ! check_service_status && [ $retries -lt 5 ]; do log_message "Waiting for CyberChef to become healthy..." sleep 10 retries=$((retries + 1)) done if [ $retries -eq 5 ]; then log_message "Failed to redeploy CyberChef after 5 attempts" return 1 fi log_message "CyberChef redeployed successfully" return 0 } backup_existing_data() { if [ -d "$INSTALL_DIR" ]; then local backup_dir="${INSTALL_DIR}_backup_$(date +%Y%m%d_%H%M%S)" log_message "Creating backup of existing installation at $backup_dir" cp -r "$INSTALL_DIR" "$backup_dir" fi } check_existing_installation() { log_message "Checking existing CyberChef installation..." if [ -f "$COMPOSE_FILE" ]; then log_message "Existing installation found" show_container_status if verify_installation; then log_message "✓ CyberChef is running correctly" log_message "✓ CyberChef is accessible at http://localhost:8000" return 0 else log_message "⚠ Service issues detected. Starting recovery process..." return 1 fi fi return 1 } # Main script execution starts here # Check if script is run as root if [ "$EUID" -ne 0 ]; then echo "Please run as root" exit 1 fi # Initialize log file mkdir -p "$(dirname "$LOG_FILE")" touch "$LOG_FILE" log_message "Starting CyberChef installation/verification script" # Check if Docker is installed if ! command -v docker &> /dev/null; then log_message "Docker not found. Installing Docker..." curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh apt-get update apt-get install -y docker-compose-plugin log_message "Docker installed successfully" else log_message "Docker already installed" check_docker_version fi # Check existing installation or proceed with new installation if check_existing_installation; then exit 0 else if [ -f "$COMPOSE_FILE" ]; then # Attempt to recover existing installation backup_existing_data if ! redeploy_service; then log_message "Failed to redeploy CyberChef. Manual intervention may be required." exit 1 fi else # New installation log_message "Starting new CyberChef installation" # Create installation directory mkdir -p "$INSTALL_DIR" cd "$INSTALL_DIR" # Check if required ports are available if ! check_required_ports; then log_message "⚠ Port conflict detected. Please resolve the conflicts and run the script again." exit 1 fi # Create docker-compose.yml cat > docker-compose.yml <<'EOF' version: "3.8" services: web: image: mpepping/cyberchef:latest container_name: cyberchef-web restart: unless-stopped networks: - cyberchef_network ports: - "8000:8000" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000"] interval: 30s timeout: 10s retries: 5 environment: - TZ=UTC volumes: - cyberchef_data:/opt/cyberchef networks: cyberchef_network: driver: bridge volumes: cyberchef_data: name: cyberchef_data EOF # Start services log_message "Starting CyberChef service..." docker compose up -d # Give service time to initialize log_message "Waiting for service to initialize..." # Initial wait for container to start up sleep 5 # Verify installation if verify_installation; then log_message "✓ Installation completed successfully!" show_container_status log_message "Important next steps:" log_message "1. Set up a reverse proxy in CloudPanel" log_message "2. Create SSL certificate for your domain" log_message "3. Access CyberChef at http://localhost:8000" else log_message "Installation completed but service is not running properly" log_message "Please check the logs and try redeploying the service" exit 1 fi fi fi