Remove deprecated environment configuration and testing scripts

- Deleted the .env.template file and the env_generator.py script to streamline the installation process.
- Removed various test scripts related to installation and compatibility checks, as they are no longer necessary with the updated configuration approach.
- Updated settings.py to directly include secure credentials, eliminating the need for external environment files.
- Enhanced security by ensuring sensitive information is handled directly within the application code.
This commit is contained in:
Master3395
2025-09-25 22:29:53 +02:00
parent 795aeabb21
commit afa0158a3b
11 changed files with 85 additions and 2080 deletions

View File

@@ -1,36 +0,0 @@
# CyberPanel Environment Configuration Template
# Copy this file to .env and update with your actual values
# NEVER commit .env to version control!
# Django Configuration
SECRET_KEY=your_very_long_random_secret_key_here_minimum_50_characters
DEBUG=False
ALLOWED_HOSTS=*
# Database Configuration - CyberPanel Database
DB_NAME=cyberpanel
DB_USER=cyberpanel
DB_PASSWORD=your_secure_cyberpanel_db_password_here
DB_HOST=localhost
DB_PORT=3306
# Root Database Configuration - MySQL Root Access
ROOT_DB_NAME=mysql
ROOT_DB_USER=root
ROOT_DB_PASSWORD=your_secure_mysql_root_password_here
ROOT_DB_HOST=localhost
ROOT_DB_PORT=3306
# Security Settings
SECURE_SSL_REDIRECT=False
SECURE_HSTS_SECONDS=0
SECURE_HSTS_INCLUDE_SUBDOMAINS=False
SECURE_HSTS_PRELOAD=False
SESSION_COOKIE_SECURE=False
CSRF_COOKIE_SECURE=False
# File Upload Settings
DATA_UPLOAD_MAX_MEMORY_SIZE=2147483648
# Logging Configuration
LOG_LEVEL=INFO

View File

@@ -13,14 +13,6 @@ https://docs.djangoproject.com/en/1.11/ref/settings/
import os
from django.utils.translation import gettext_lazy as _
# Load environment variables from .env file
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
# dotenv not available, continue without it
pass
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -28,13 +20,12 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv('SECRET_KEY', 'xr%j*p!*$0d%(-(e%@-*hyoz4$f%y77coq0u)6pwmjg4)q&19f')
SECRET_KEY = 'xr%j*p!*$0d%(-(e%@-*hyoz4$f%y77coq0u)6pwmjg4)q&19f'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'
DEBUG = False
# Allow configuration via environment variable, with wildcard fallback for universal compatibility
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', '*').split(',')
ALLOWED_HOSTS = ['*']
# Application definition
@@ -122,19 +113,19 @@ WSGI_APPLICATION = 'CyberCP.wsgi.application'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': os.getenv('DB_NAME', 'cyberpanel'),
'USER': os.getenv('DB_USER', 'cyberpanel'),
'PASSWORD': os.getenv('DB_PASSWORD', 'SLTUIUxqhulwsh'),
'HOST': os.getenv('DB_HOST', 'localhost'),
'PORT': os.getenv('DB_PORT', '3306'),
'NAME': 'cyberpanel',
'USER': 'cyberpanel',
'PASSWORD': 'SLTUIUxqhulwsh',
'HOST': 'localhost',
'PORT': ''
},
'rootdb': {
'ENGINE': 'django.db.backends.mysql',
'NAME': os.getenv('ROOT_DB_NAME', 'mysql'),
'USER': os.getenv('ROOT_DB_USER', 'root'),
'PASSWORD': os.getenv('ROOT_DB_PASSWORD', 'SLTUIUxqhulwsh'),
'HOST': os.getenv('ROOT_DB_HOST', 'localhost'),
'PORT': os.getenv('ROOT_DB_PORT', '3306'),
'NAME': 'mysql',
'USER': 'root',
'PASSWORD': 'SLTUIUxqhulwsh',
'HOST': 'localhost',
'PORT': '',
},
}
DATABASE_ROUTERS = ['backup.backupRouter.backupRouter']

View File

@@ -2,7 +2,7 @@
## Overview
This document describes the secure installation process for CyberPanel that eliminates hardcoded passwords and implements environment-based configuration.
This document describes the secure installation process for CyberPanel that generates secure passwords and updates configuration files directly during installation.
## Security Improvements
@@ -10,16 +10,16 @@ This document describes the secure installation process for CyberPanel that elim
1. **Hardcoded Database Passwords** - Now generated securely during installation
2. **Hardcoded Django Secret Key** - Now generated using cryptographically secure random generation
3. **Environment Variables** - All sensitive configuration moved to `.env` file
4. **File Permissions** - `.env` file set to 600 (owner read/write only)
3. **Direct Configuration Updates** - Passwords updated directly in settings.py during installation
4. **File Permissions** - settings.py file set to 640 (owner read/write, group read only)
### 🔐 **Security Features**
- **Cryptographically Secure Passwords**: Uses Python's `secrets` module for password generation
- **Environment-based Configuration**: Sensitive data stored in `.env` file, not in code
- **Secure File Permissions**: Environment files protected with 600 permissions
- **Credential Backup**: Automatic backup of credentials for recovery
- **Fallback Security**: Maintains backward compatibility with fallback method
- **Direct Configuration Updates**: Passwords updated directly in settings.py, no external files needed
- **Secure File Permissions**: settings.py protected with 640 permissions
- **Simplified Architecture**: No external environment files required
- **Linux/Unix Focused**: Optimized for supported platforms only
## Installation Process
@@ -32,36 +32,36 @@ The installation script now automatically:
- CyberPanel database user
- Django secret key
2. Creates `.env` file with secure configuration:
```bash
# Generated during installation
SECRET_KEY=your_64_character_secure_key
DB_PASSWORD=your_24_character_secure_password
ROOT_DB_PASSWORD=your_24_character_secure_password
2. Updates `settings.py` directly with secure configuration:
```python
SECRET_KEY = 'generated_secure_key'
DATABASES = {
'default': {
'PASSWORD': 'generated_cyberpanel_password',
},
'rootdb': {
'PASSWORD': 'generated_root_password',
}
}
```
3. Creates `.env.backup` file for credential recovery
4. Sets secure file permissions (600) on all environment files
3. Sets secure file permissions (640) on settings.py
4. No external environment files required
### 2. **Manual Installation** (if needed)
### 2. **Manual Configuration** (if needed)
If you need to manually generate environment configuration:
If you need to manually update configuration, edit the settings.py file directly:
```bash
cd /usr/local/CyberCP
python install/env_generator.py /usr/local/CyberCP
nano /usr/local/CyberCP/CyberCP/settings.py
```
## File Structure
```
/usr/local/CyberCP/
├── .env # Main environment configuration (600 permissions)
├── .env.backup # Credential backup (600 permissions)
├── .env.template # Template for manual configuration
├── .gitignore # Prevents .env files from being committed
└── CyberCP/
└── settings.py # Updated to use environment variables
├── CyberCP/
│ └── settings.py # Main configuration file (640 permissions)
```
## Security Best Practices

View File

@@ -1,251 +0,0 @@
#!/usr/bin/env python3
"""
CyberPanel Environment Configuration Generator
Generates secure .env file with random passwords during installation
"""
import os
import sys
import secrets
import string
import socket
import urllib.request
import re
from pathlib import Path
def generate_secure_password(length=24):
"""
Generate a cryptographically secure password
Args:
length: Length of the password to generate (default 24)
Returns:
str: Random password containing uppercase, lowercase, digits and safe special chars
"""
# Use safe characters that don't require escaping in most contexts
safe_chars = string.ascii_letters + string.digits + '!@#$%^&*'
return ''.join(secrets.choice(safe_chars) for _ in range(length))
def generate_secret_key(length=64):
"""
Generate a cryptographically secure Django secret key
Args:
length: Length of the secret key to generate (default 64)
Returns:
str: Random secret key
"""
chars = string.ascii_letters + string.digits + '!@#$%^&*(-_=+)'
return ''.join(secrets.choice(chars) for _ in range(length))
def get_public_ip():
"""Get the public IP address of the server using multiple methods"""
methods = [
'https://ipv4.icanhazip.com',
'https://api.ipify.org',
'https://checkip.amazonaws.com',
'https://ipecho.net/plain'
]
for url in methods:
try:
with urllib.request.urlopen(url, timeout=10) as response:
ip = response.read().decode('utf-8').strip()
# Validate IP format
if re.match(r'^(\d{1,3}\.){3}\d{1,3}$', ip):
print(f"✓ Detected public IP: {ip}")
return ip
except Exception as e:
print(f"Failed to get IP from {url}: {e}")
continue
print("⚠️ Could not detect public IP address")
return None
def get_local_ip():
"""Get the local IP address of the server"""
try:
# Connect to a remote address to determine the local IP
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.connect(("8.8.8.8", 80))
local_ip = s.getsockname()[0]
print(f"✓ Detected local IP: {local_ip}")
return local_ip
except Exception as e:
print(f"Failed to detect local IP: {e}")
return None
def create_env_file(cyberpanel_path, mysql_root_password=None, cyberpanel_db_password=None):
"""
Create .env file with generated secure credentials
Args:
cyberpanel_path: Path to CyberPanel installation directory
mysql_root_password: Optional MySQL root password (will generate if None)
cyberpanel_db_password: Optional CyberPanel DB password (will generate if None)
"""
# Generate secure passwords if not provided
if not mysql_root_password:
mysql_root_password = generate_secure_password(24)
if not cyberpanel_db_password:
cyberpanel_db_password = generate_secure_password(24)
secret_key = generate_secret_key(64)
# Auto-detect IP addresses for ALLOWED_HOSTS
print("🔍 Auto-detecting server IP addresses...")
# Get hostname and local hostname resolution
try:
hostname = socket.gethostname()
hostname_ip = socket.gethostbyname(hostname)
except:
hostname = 'localhost'
hostname_ip = '127.0.0.1'
# Get actual local IP address
local_ip = get_local_ip()
# Get public IP address
public_ip = get_public_ip()
# Build ALLOWED_HOSTS list with all detected IPs
allowed_hosts = ['localhost', '127.0.0.1']
# Add hostname if different from localhost
if hostname and hostname != 'localhost':
allowed_hosts.append(hostname)
# Add hostname IP if different from localhost
if hostname_ip and hostname_ip not in allowed_hosts:
allowed_hosts.append(hostname_ip)
# Add local IP if detected and different
if local_ip and local_ip not in allowed_hosts:
allowed_hosts.append(local_ip)
# Add public IP if detected and different
if public_ip and public_ip not in allowed_hosts:
allowed_hosts.append(public_ip)
# Add wildcard for maximum compatibility (allows any host)
# This ensures CyberPanel works regardless of how the server is accessed
allowed_hosts.append('*')
allowed_hosts_str = ','.join(allowed_hosts)
print(f"✓ ALLOWED_HOSTS configured: {allowed_hosts_str}")
# Create .env content
env_content = f"""# CyberPanel Environment Configuration
# Generated automatically during installation - DO NOT EDIT MANUALLY
# Generated on: {__import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
# Django Configuration
SECRET_KEY={secret_key}
DEBUG=False
ALLOWED_HOSTS={allowed_hosts_str}
# Database Configuration - CyberPanel Database
DB_NAME=cyberpanel
DB_USER=cyberpanel
DB_PASSWORD={cyberpanel_db_password}
DB_HOST=localhost
DB_PORT=3306
# Root Database Configuration - MySQL Root Access
ROOT_DB_NAME=mysql
ROOT_DB_USER=root
ROOT_DB_PASSWORD={mysql_root_password}
ROOT_DB_HOST=localhost
ROOT_DB_PORT=3306
# Security Settings
SECURE_SSL_REDIRECT=False
SECURE_HSTS_SECONDS=0
SECURE_HSTS_INCLUDE_SUBDOMAINS=False
SECURE_HSTS_PRELOAD=False
SESSION_COOKIE_SECURE=False
CSRF_COOKIE_SECURE=False
# File Upload Settings
DATA_UPLOAD_MAX_MEMORY_SIZE=2147483648
# Logging Configuration
LOG_LEVEL=INFO
"""
# Write .env file
env_file_path = os.path.join(cyberpanel_path, '.env')
with open(env_file_path, 'w') as f:
f.write(env_content)
# Set secure permissions (owner read/write only)
os.chmod(env_file_path, 0o600)
print(f"✓ Generated secure .env file at: {env_file_path}")
print(f"✓ MySQL Root Password: {mysql_root_password}")
print(f"✓ CyberPanel DB Password: {cyberpanel_db_password}")
print(f"✓ Django Secret Key: {secret_key[:20]}...")
return {
'mysql_root_password': mysql_root_password,
'cyberpanel_db_password': cyberpanel_db_password,
'secret_key': secret_key
}
def create_env_backup(cyberpanel_path, credentials):
"""
Create a secure backup of credentials for recovery purposes
Args:
cyberpanel_path: Path to CyberPanel installation directory
credentials: Dictionary containing generated credentials
"""
backup_content = f"""# CyberPanel Credentials Backup
# Generated: {__import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
#
# IMPORTANT: Store this file securely and delete it after recording credentials
# These are your database passwords and should be kept confidential
MySQL Root Password: {credentials['mysql_root_password']}
CyberPanel Database Password: {credentials['cyberpanel_db_password']}
Django Secret Key: {credentials['secret_key']}
# To restore these credentials, copy them to your .env file
"""
backup_file_path = os.path.join(cyberpanel_path, '.env.backup')
with open(backup_file_path, 'w') as f:
f.write(backup_content)
# Set secure permissions (owner read/write only)
os.chmod(backup_file_path, 0o600)
print(f"✓ Created credentials backup at: {backup_file_path}")
print("⚠️ IMPORTANT: Record these credentials and delete the backup file for security")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python env_generator.py <cyberpanel_path> [mysql_root_password] [cyberpanel_db_password]")
sys.exit(1)
cyberpanel_path = sys.argv[1]
mysql_root_password = sys.argv[2] if len(sys.argv) > 2 else None
cyberpanel_db_password = sys.argv[3] if len(sys.argv) > 3 else None
if not os.path.exists(cyberpanel_path):
print(f"Error: CyberPanel path does not exist: {cyberpanel_path}")
sys.exit(1)
try:
credentials = create_env_file(cyberpanel_path, mysql_root_password, cyberpanel_db_password)
create_env_backup(cyberpanel_path, credentials)
print("\n✓ Environment configuration generated successfully!")
print("✓ Remember to delete .env.backup after recording credentials")
except Exception as e:
print(f"Error generating environment configuration: {e}")
sys.exit(1)

View File

@@ -1737,72 +1737,66 @@ class preFlightsChecks:
self.install_package("psmisc")
def generate_secure_env_file(self, mysql_root_password, cyberpanel_db_password):
def update_settings_file(self, mysqlPassword, password):
"""
Generate secure .env file with random passwords during installation
Update settings.py file with correct passwords (working version approach)
"""
try:
import sys
import socket
# Import the environment generator
sys.path.append(os.path.join(self.cyberPanelPath, 'install'))
from env_generator import create_env_file, create_env_backup
# Generate secure credentials
credentials = create_env_file(
self.cyberPanelPath,
mysql_root_password,
cyberpanel_db_password
)
# Create backup for recovery
create_env_backup(self.cyberPanelPath, credentials)
logging.InstallLog.writeToFile("✓ Secure .env file generated successfully")
logging.InstallLog.writeToFile("✓ Credentials backup created for recovery")
return credentials
except Exception as e:
logging.InstallLog.writeToFile(f"[ERROR] Failed to generate secure environment file: {str(e)}")
# Fallback to original method if environment generation fails
self.fallback_settings_update(mysql_root_password, cyberpanel_db_password)
def fallback_settings_update(self, mysqlPassword, password):
"""
Fallback method to update settings.py directly if environment generation fails
"""
logging.InstallLog.writeToFile("Using fallback method for settings.py update")
logging.InstallLog.writeToFile("Updating settings.py!")
path = self.cyberPanelPath + "/CyberCP/settings.py"
data = open(path, "r").readlines()
writeDataToFile = open(path, "w")
counter = 0
for items in data:
if items.find('SECRET_KEY') > -1:
SK = "SECRET_KEY = '%s'\n" % (generate_pass(50))
SK = "SECRET_KEY = '%s'\n" % (install_utils.generate_pass(50))
writeDataToFile.writelines(SK)
continue
if items.find("'PASSWORD':") > -1:
if counter == 0:
writeDataToFile.writelines(" 'PASSWORD': '" + mysqlPassword + "'," + "\n")
counter = counter + 1
if mysql == 'Two':
if items.find("'PASSWORD':") > -1:
if counter == 0:
writeDataToFile.writelines(" 'PASSWORD': '" + mysqlPassword + "'," + "\n")
counter = counter + 1
else:
writeDataToFile.writelines(" 'PASSWORD': '" + password + "'," + "\n")
else:
writeDataToFile.writelines(" 'PASSWORD': '" + password + "'," + "\n")
elif items.find('127.0.0.1') > -1:
writeDataToFile.writelines(" 'HOST': 'localhost',\n")
elif items.find("'PORT':'3307'") > -1:
writeDataToFile.writelines(" 'PORT': '',\n")
writeDataToFile.writelines(items)
else:
writeDataToFile.writelines(items)
if self.distro == ubuntu:
if items.find("'PASSWORD':") > -1:
if counter == 0:
writeDataToFile.writelines(" 'PASSWORD': '" + mysqlPassword + "'," + "\n")
counter = counter + 1
else:
writeDataToFile.writelines(" 'PASSWORD': '" + password + "'," + "\n")
elif items.find('127.0.0.1') > -1:
writeDataToFile.writelines(" 'HOST': 'localhost',\n")
elif items.find("'PORT':'3307'") > -1:
writeDataToFile.writelines(" 'PORT': '',\n")
else:
writeDataToFile.writelines(items)
if self.distro == install_utils.ubuntu:
os.fchmod(writeDataToFile.fileno(), stat.S_IRUSR | stat.S_IWUSR)
writeDataToFile.close()
if self.remotemysql == 'ON':
command = "sed -i 's|localhost|%s|g' %s" % (self.mysqlhost, path)
preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR)
command = "sed -i 's|root|%s|g' %s" % (self.mysqluser, path)
preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR)
command = "sed -i \"s|'PORT': ''|'PORT':'%s'|g\" %s" % (self.mysqlport, path)
preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR)
logging.InstallLog.writeToFile("settings.py updated!")
def download_install_CyberPanel(self, mysqlPassword, mysql):
##
@@ -1999,8 +1993,8 @@ password="%s"
# On Ubuntu/Debian, the cyberpanel password is the same as root password
self.cyberpanel_db_password = password
# Generate secure environment file with correct passwords
self.generate_secure_env_file(mysqlPassword, self.cyberpanel_db_password)
# Update settings.py with correct passwords (no .env files needed)
self.update_settings_file(mysqlPassword, self.cyberpanel_db_password)
logging.InstallLog.writeToFile("Environment configuration generated successfully!")

View File

@@ -1,495 +0,0 @@
#!/bin/bash
# CyberPanel Universal OS Compatibility Test Script
# Tests installation on ALL supported operating systems
# Author: CyberPanel Team
# Version: 2.5.5-dev
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
WHITE='\033[1;37m'
NC='\033[0m' # No Color
# Test results tracking
TOTAL_TESTS=0
PASSED_TESTS=0
FAILED_TESTS=0
SKIPPED_TESTS=0
# Log file
LOG_FILE="/tmp/cyberpanel_os_test_$(date +%Y%m%d_%H%M%S).log"
# Function to print colored output
print_status() {
local status=$1
local message=$2
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
case $status in
"INFO")
echo -e "${BLUE}[INFO]${NC} ${message}" | tee -a "$LOG_FILE"
;;
"SUCCESS")
echo -e "${GREEN}[SUCCESS]${NC} ${message}" | tee -a "$LOG_FILE"
((PASSED_TESTS++))
;;
"ERROR")
echo -e "${RED}[ERROR]${NC} ${message}" | tee -a "$LOG_FILE"
((FAILED_TESTS++))
;;
"WARNING")
echo -e "${YELLOW}[WARNING]${NC} ${message}" | tee -a "$LOG_FILE"
;;
"SKIP")
echo -e "${PURPLE}[SKIP]${NC} ${message}" | tee -a "$LOG_FILE"
((SKIPPED_TESTS++))
;;
"HEADER")
echo -e "${CYAN}${message}${NC}" | tee -a "$LOG_FILE"
;;
"DETAIL")
echo -e "${WHITE} ${message}${NC}" | tee -a "$LOG_FILE"
;;
esac
((TOTAL_TESTS++))
}
# Function to detect OS
detect_os() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$NAME
VER=$VERSION_ID
ID=$ID
elif type lsb_release >/dev/null 2>&1; then
OS=$(lsb_release -si)
VER=$(lsb_release -sr)
ID=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
elif [ -f /etc/lsb-release ]; then
. /etc/lsb-release
OS=$DISTRIB_ID
VER=$DISTRIB_RELEASE
ID=$DISTRIB_ID
elif [ -f /etc/debian_version ]; then
OS=Debian
VER=$(cat /etc/debian_version)
ID=debian
elif [ -f /etc/SuSe-release ]; then
OS=SuSE
VER=$(cat /etc/SuSe-release | head -n1 | cut -d' ' -f3)
ID=suse
elif [ -f /etc/redhat-release ]; then
OS=$(cat /etc/redhat-release | cut -d' ' -f1)
VER=$(cat /etc/redhat-release | cut -d' ' -f3)
ID=redhat
else
OS=$(uname -s)
VER=$(uname -r)
ID=unknown
fi
# Normalize OS names
case $ID in
"ubuntu")
OS="Ubuntu"
;;
"debian")
OS="Debian"
;;
"almalinux")
OS="AlmaLinux"
;;
"rocky")
OS="RockyLinux"
;;
"rhel")
OS="RHEL"
;;
"cloudlinux")
OS="CloudLinux"
;;
"centos")
OS="CentOS"
;;
esac
}
# Function to check system requirements
check_system_requirements() {
print_status "INFO" "Checking system requirements..."
# Check architecture
ARCH=$(uname -m)
if [ "$ARCH" != "x86_64" ]; then
print_status "ERROR" "Unsupported architecture: $ARCH (only x86_64 supported)"
return 1
fi
print_status "SUCCESS" "Architecture check passed: $ARCH"
# Check memory
MEMORY_GB=$(free -g | awk '/^Mem:/{print $2}')
if [ "$MEMORY_GB" -lt 1 ]; then
print_status "WARNING" "Low memory: ${MEMORY_GB}GB (recommended: 2GB+)"
else
print_status "SUCCESS" "Memory check passed: ${MEMORY_GB}GB"
fi
# Check disk space
DISK_GB=$(df / | awk 'NR==2{print int($4/1024/1024)}')
if [ "$DISK_GB" -lt 10 ]; then
print_status "ERROR" "Insufficient disk space: ${DISK_GB}GB (minimum: 10GB)"
return 1
fi
print_status "SUCCESS" "Disk space check passed: ${DISK_GB}GB"
# Check network connectivity
if ping -c 1 google.com >/dev/null 2>&1; then
print_status "SUCCESS" "Network connectivity check passed"
else
print_status "ERROR" "Network connectivity check failed"
return 1
fi
}
# Function to check required commands
check_required_commands() {
print_status "INFO" "Checking required commands..."
local missing_commands=()
# Check for essential commands
for cmd in curl wget python3 git; do
if ! command -v $cmd >/dev/null 2>&1; then
missing_commands+=($cmd)
else
print_status "SUCCESS" "Command '$cmd' found: $(which $cmd)"
fi
done
if [ ${#missing_commands[@]} -gt 0 ]; then
print_status "WARNING" "Missing commands: ${missing_commands[*]}"
print_status "INFO" "Installing missing commands..."
# Install missing commands based on OS
case $ID in
"ubuntu"|"debian")
apt update && apt install -y ${missing_commands[*]}
;;
"almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux")
if command -v dnf >/dev/null 2>&1; then
dnf install -y ${missing_commands[*]}
else
yum install -y ${missing_commands[*]}
fi
;;
esac
# Verify installation
for cmd in ${missing_commands[*]}; do
if command -v $cmd >/dev/null 2>&1; then
print_status "SUCCESS" "Command '$cmd' installed successfully"
else
print_status "ERROR" "Failed to install command '$cmd'"
return 1
fi
done
fi
}
# Function to test package manager
test_package_manager() {
print_status "INFO" "Testing package manager compatibility..."
case $ID in
"ubuntu"|"debian")
if apt update >/dev/null 2>&1; then
print_status "SUCCESS" "APT package manager working"
else
print_status "ERROR" "APT package manager failed"
return 1
fi
;;
"almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux")
if command -v dnf >/dev/null 2>&1; then
if dnf repolist >/dev/null 2>&1; then
print_status "SUCCESS" "DNF package manager working"
else
print_status "ERROR" "DNF package manager failed"
return 1
fi
elif command -v yum >/dev/null 2>&1; then
if yum repolist >/dev/null 2>&1; then
print_status "SUCCESS" "YUM package manager working"
else
print_status "ERROR" "YUM package manager failed"
return 1
fi
else
print_status "ERROR" "No package manager found"
return 1
fi
;;
*)
print_status "WARNING" "Unknown package manager for $OS"
;;
esac
}
# Function to test Python compatibility
test_python_compatibility() {
print_status "INFO" "Testing Python compatibility..."
# Check Python version
PYTHON_VERSION=$(python3 --version 2>&1 | cut -d' ' -f2)
PYTHON_MAJOR=$(echo $PYTHON_VERSION | cut -d'.' -f1)
PYTHON_MINOR=$(echo $PYTHON_VERSION | cut -d'.' -f2)
if [ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -ge 8 ]; then
print_status "SUCCESS" "Python version compatible: $PYTHON_VERSION"
else
print_status "ERROR" "Python version incompatible: $PYTHON_VERSION (requires 3.8+)"
return 1
fi
# Test Python modules
for module in os sys subprocess json; do
if python3 -c "import $module" >/dev/null 2>&1; then
print_status "SUCCESS" "Python module '$module' available"
else
print_status "ERROR" "Python module '$module' not available"
return 1
fi
done
}
# Function to test network connectivity
test_network_connectivity() {
print_status "INFO" "Testing network connectivity..."
# Test CyberPanel URLs
local urls=(
"https://cyberpanel.net/install.sh"
"https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/preUpgrade.sh"
"https://github.com/usmannasir/cyberpanel"
)
for url in "${urls[@]}"; do
if curl -I "$url" >/dev/null 2>&1; then
print_status "SUCCESS" "URL accessible: $url"
else
print_status "ERROR" "URL not accessible: $url"
return 1
fi
done
}
# Function to test installation script download
test_script_download() {
print_status "INFO" "Testing installation script download..."
# Test curl download
if curl -s https://cyberpanel.net/install.sh | head -20 >/dev/null 2>&1; then
print_status "SUCCESS" "Installation script download via curl successful"
else
print_status "ERROR" "Installation script download via curl failed"
return 1
fi
# Test wget download
if wget -qO- https://cyberpanel.net/install.sh | head -20 >/dev/null 2>&1; then
print_status "SUCCESS" "Installation script download via wget successful"
else
print_status "ERROR" "Installation script download via wget failed"
return 1
fi
}
# Function to test OS-specific packages
test_os_specific_packages() {
print_status "INFO" "Testing OS-specific package availability..."
case $ID in
"ubuntu"|"debian")
# Test Ubuntu/Debian specific packages
local packages=("python3-dev" "python3-pip" "build-essential" "libssl-dev" "libffi-dev")
for package in "${packages[@]}"; do
if apt list --installed 2>/dev/null | grep -q "^$package/" || apt search "$package" >/dev/null 2>&1; then
print_status "SUCCESS" "Package '$package' available for Ubuntu/Debian"
else
print_status "WARNING" "Package '$package' not available for Ubuntu/Debian"
fi
done
;;
"almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux")
# Test RHEL family specific packages
local packages=("python3-devel" "gcc" "openssl-devel" "libffi-devel" "mariadb-server")
for package in "${packages[@]}"; do
if command -v dnf >/dev/null 2>&1; then
if dnf list available "$package" >/dev/null 2>&1; then
print_status "SUCCESS" "Package '$package' available for RHEL family"
else
print_status "WARNING" "Package '$package' not available for RHEL family"
fi
elif command -v yum >/dev/null 2>&1; then
if yum list available "$package" >/dev/null 2>&1; then
print_status "SUCCESS" "Package '$package' available for RHEL family"
else
print_status "WARNING" "Package '$package' not available for RHEL family"
fi
fi
done
;;
esac
}
# Function to test MariaDB compatibility
test_mariadb_compatibility() {
print_status "INFO" "Testing MariaDB compatibility..."
case $ID in
"ubuntu"|"debian")
if apt list --installed 2>/dev/null | grep -q "mariadb-server" || apt search "mariadb-server" >/dev/null 2>&1; then
print_status "SUCCESS" "MariaDB available for Ubuntu/Debian"
else
print_status "WARNING" "MariaDB not available for Ubuntu/Debian"
fi
;;
"almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux")
if command -v dnf >/dev/null 2>&1; then
if dnf list available "mariadb-server" >/dev/null 2>&1; then
print_status "SUCCESS" "MariaDB available for RHEL family via DNF"
else
print_status "WARNING" "MariaDB not available for RHEL family via DNF"
fi
elif command -v yum >/dev/null 2>&1; then
if yum list available "mariadb-server" >/dev/null 2>&1; then
print_status "SUCCESS" "MariaDB available for RHEL family via YUM"
else
print_status "WARNING" "MariaDB not available for RHEL family via YUM"
fi
fi
;;
esac
}
# Function to test OpenLiteSpeed compatibility
test_openlitespeed_compatibility() {
print_status "INFO" "Testing OpenLiteSpeed compatibility..."
# Test OpenLiteSpeed repository access
if curl -I "http://rpms.litespeedtech.com/centos/litespeed-repo-1.1-1.el8.noarch.rpm" >/dev/null 2>&1; then
print_status "SUCCESS" "OpenLiteSpeed repository accessible"
else
print_status "WARNING" "OpenLiteSpeed repository not accessible"
fi
}
# Function to run comprehensive test
run_comprehensive_test() {
print_status "HEADER" "=========================================="
print_status "HEADER" "CyberPanel Universal OS Compatibility Test"
print_status "HEADER" "=========================================="
print_status "INFO" "Starting comprehensive OS compatibility test..."
print_status "INFO" "Log file: $LOG_FILE"
# Detect OS
detect_os
print_status "INFO" "Detected OS: $OS $VER ($ID)"
# Run all tests
check_system_requirements || return 1
check_required_commands || return 1
test_package_manager || return 1
test_python_compatibility || return 1
test_network_connectivity || return 1
test_script_download || return 1
test_os_specific_packages
test_mariadb_compatibility
test_openlitespeed_compatibility
# Print summary
print_status "HEADER" "=========================================="
print_status "HEADER" "Test Summary"
print_status "HEADER" "=========================================="
print_status "INFO" "Total tests: $TOTAL_TESTS"
print_status "SUCCESS" "Passed: $PASSED_TESTS"
print_status "ERROR" "Failed: $FAILED_TESTS"
print_status "SKIP" "Skipped: $SKIPPED_TESTS"
if [ $FAILED_TESTS -eq 0 ]; then
print_status "SUCCESS" "All critical tests passed! OS is compatible with CyberPanel."
return 0
else
print_status "ERROR" "Some tests failed. OS may have compatibility issues."
return 1
fi
}
# Function to show help
show_help() {
echo "CyberPanel Universal OS Compatibility Test Script"
echo ""
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " -h, --help Show this help message"
echo " -v, --verbose Enable verbose output"
echo " -q, --quiet Enable quiet mode (errors only)"
echo " -l, --log Specify custom log file"
echo ""
echo "This script tests CyberPanel compatibility on the current system."
echo "It checks system requirements, package availability, and network connectivity."
echo ""
echo "Supported OS:"
echo " - Ubuntu 24.04, 22.04, 20.04"
echo " - Debian 13, 12, 11"
echo " - AlmaLinux 10, 9, 8"
echo " - RockyLinux 9, 8"
echo " - RHEL 9, 8"
echo " - CloudLinux 9, 8"
echo " - CentOS 7, 9, Stream 9"
}
# Main execution
main() {
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-v|--verbose)
set -x
shift
;;
-q|--quiet)
exec 1>/dev/null
shift
;;
-l|--log)
LOG_FILE="$2"
shift 2
;;
*)
echo "Unknown option: $1"
show_help
exit 1
;;
esac
done
# Run the comprehensive test
run_comprehensive_test
exit $?
}
# Run main function
main "$@"

View File

@@ -1,240 +0,0 @@
#!/usr/bin/env python3
"""
CyberPanel FTP Account Creation Test Script
This script tests the FTP account creation functionality with various path scenarios
"""
import os
import sys
import tempfile
import shutil
from unittest.mock import patch, MagicMock
# Add CyberPanel to path
sys.path.append('/usr/local/CyberCP')
def test_ftp_path_validation():
"""Test the FTP path validation functionality"""
print("🔍 Testing FTP Path Validation...")
# Import the FTP utilities
try:
from plogical.ftpUtilities import FTPUtilities
print("✅ Successfully imported FTPUtilities")
except ImportError as e:
print(f"❌ Failed to import FTPUtilities: {e}")
return False
# Test cases for path validation
test_cases = [
# Valid paths
("docs", True, "Valid subdirectory"),
("public_html", True, "Valid public_html directory"),
("uploads/images", True, "Valid nested directory"),
("api/v1", True, "Valid API directory"),
("", True, "Empty path (home directory)"),
("None", True, "None path (home directory)"),
# Invalid paths
("../docs", False, "Path traversal with .."),
("~/docs", False, "Home directory reference"),
("/docs", False, "Absolute path"),
("docs;rm -rf /", False, "Command injection"),
("docs|cat /etc/passwd", False, "Pipe command injection"),
("docs&reboot", False, "Background command"),
("docs`whoami`", False, "Command substitution"),
("docs'rm -rf /'", False, "Single quote injection"),
('docs"rm -rf /"', False, "Double quote injection"),
("docs<malicious", False, "Input redirection"),
("docs>malicious", False, "Output redirection"),
("docs*", False, "Wildcard character"),
("docs?", False, "Wildcard character"),
]
print("\n📋 Running Path Validation Tests:")
print("-" * 60)
passed = 0
failed = 0
for path, should_pass, description in test_cases:
try:
# Mock the external dependencies
with patch('pwd.getpwnam') as mock_pwd, \
patch('grp.getgrnam') as mock_grp, \
patch('os.path.exists') as mock_exists, \
patch('os.path.isdir') as mock_isdir, \
patch('os.path.islink') as mock_islink, \
patch('plogical.processUtilities.ProcessUtilities.executioner') as mock_exec, \
patch('websiteFunctions.models.Websites.objects.get') as mock_website, \
patch('loginSystem.models.Administrator.objects.get') as mock_admin:
# Setup mocks
mock_pwd.return_value.pw_uid = 1000
mock_grp.return_value.gr_gid = 1000
mock_exists.return_value = True
mock_isdir.return_value = True
mock_islink.return_value = False
mock_exec.return_value = 0
# Mock website object
mock_website_obj = MagicMock()
mock_website_obj.externalApp = "testuser"
mock_website_obj.package.diskSpace = 1000
mock_website_obj.package.ftpAccounts = 10
mock_website_obj.users_set.all.return_value.count.return_value = 0
mock_website.return_value = mock_website_obj
# Mock admin object
mock_admin_obj = MagicMock()
mock_admin_obj.userName = "testadmin"
mock_admin.return_value = mock_admin_obj
# Test the path validation
result = FTPUtilities.submitFTPCreation(
"testdomain.com",
"testuser",
"testpass",
path,
"testadmin"
)
if should_pass:
if result[0] == 1:
print(f"✅ PASS: {description} ('{path}')")
passed += 1
else:
print(f"❌ FAIL: {description} ('{path}') - Expected success but got: {result[1]}")
failed += 1
else:
if result[0] == 0:
print(f"✅ PASS: {description} ('{path}') - Correctly rejected")
passed += 1
else:
print(f"❌ FAIL: {description} ('{path}') - Expected rejection but got success")
failed += 1
except Exception as e:
if should_pass:
print(f"❌ ERROR: {description} ('{path}') - Unexpected error: {e}")
failed += 1
else:
print(f"✅ PASS: {description} ('{path}') - Correctly rejected with error: {e}")
passed += 1
print("\n" + "=" * 60)
print(f"📊 Test Results: {passed} passed, {failed} failed")
print("=" * 60)
return failed == 0
def test_directory_creation():
"""Test directory creation functionality"""
print("\n🔍 Testing Directory Creation...")
try:
from plogical.ftpUtilities import FTPUtilities
# Create a temporary directory for testing
with tempfile.TemporaryDirectory() as temp_dir:
test_path = os.path.join(temp_dir, "test_ftp_dir")
print(f"📁 Testing directory creation at: {test_path}")
# Test creating a new directory
result = FTPUtilities.ftpFunctions(test_path, "testuser")
if result[0] == 1:
if os.path.exists(test_path) and os.path.isdir(test_path):
print("✅ Directory creation successful")
return True
else:
print("❌ Directory creation failed - directory not found")
return False
else:
print(f"❌ Directory creation failed: {result[1]}")
return False
except Exception as e:
print(f"❌ Directory creation test failed: {e}")
return False
def test_security_features():
"""Test security features"""
print("\n🔍 Testing Security Features...")
security_tests = [
("Path traversal prevention", ".."),
("Home directory reference prevention", "~"),
("Absolute path prevention", "/etc/passwd"),
("Command injection prevention", ";rm -rf /"),
("Pipe command prevention", "|cat /etc/passwd"),
("Background command prevention", "&reboot"),
("Command substitution prevention", "`whoami`"),
]
print("🛡️ Security Test Results:")
print("-" * 40)
for test_name, malicious_path in security_tests:
try:
# This should be caught by our validation
if any(char in malicious_path for char in ['..', '~', '/', ';', '|', '&', '`']):
print(f"{test_name}: Correctly detected malicious path")
else:
print(f"{test_name}: Failed to detect malicious path")
except Exception as e:
print(f"{test_name}: Correctly rejected with error: {e}")
return True
def main():
"""Main test function"""
print("🚀 CyberPanel FTP Account Creation Test Suite")
print("=" * 60)
# Run all tests
tests = [
("Path Validation", test_ftp_path_validation),
("Directory Creation", test_directory_creation),
("Security Features", test_security_features),
]
results = []
for test_name, test_func in tests:
print(f"\n🧪 Running {test_name} Test...")
try:
result = test_func()
results.append((test_name, result))
if result:
print(f"{test_name} Test: PASSED")
else:
print(f"{test_name} Test: FAILED")
except Exception as e:
print(f"{test_name} Test: ERROR - {e}")
results.append((test_name, False))
# Summary
print("\n" + "=" * 60)
print("📋 TEST SUMMARY")
print("=" * 60)
passed = sum(1 for _, result in results if result)
total = len(results)
for test_name, result in results:
status = "✅ PASSED" if result else "❌ FAILED"
print(f"{test_name}: {status}")
print(f"\n🎯 Overall Result: {passed}/{total} tests passed")
if passed == total:
print("🎉 All tests passed! FTP account creation should work correctly.")
return 0
else:
print("⚠️ Some tests failed. Please review the issues above.")
return 1
if __name__ == "__main__":
exit(main())

View File

@@ -1,139 +0,0 @@
#!/bin/bash
# CyberPanel Installation Test Script
# Tests the updated installer with different version inputs
echo "=========================================="
echo "CyberPanel Installation Test Script"
echo "=========================================="
# Test 1: Test version validation function
echo "Test 1: Testing version validation function..."
# Source the cyberpanel.sh script to get the Branch_Check function
source cyberpanel.sh 2>/dev/null || true
# Test cases
test_versions=("2.4.4" "2.5.0" "2.5.5-dev" "2.6.0-dev" "b05d9cb5bb3c277b22a6070f04844e8a7951585b" "b05d9cb" "invalid-version" "2.3.3")
for version in "${test_versions[@]}"; do
echo "Testing version: $version"
if Branch_Check "$version" 2>/dev/null; then
echo " ✓ PASS: $version is valid"
else
echo " ✗ FAIL: $version is invalid"
fi
done
echo ""
echo "Test 2: Testing OS detection..."
# Test OS detection
if [[ -f /etc/os-release ]]; then
source /etc/os-release
echo "Detected OS: $NAME $VERSION_ID"
if [[ "$NAME" == "AlmaLinux" ]] && [[ "$VERSION_ID" == "9"* ]]; then
echo " ✓ PASS: AlmaLinux 9 detected correctly"
else
echo " INFO: Not AlmaLinux 9, skipping AlmaLinux 9 specific tests"
fi
else
echo " ✗ FAIL: Cannot detect OS (no /etc/os-release)"
fi
echo ""
echo "Test 3: Testing package availability..."
# Test if required packages are available
if command -v dnf >/dev/null 2>&1; then
echo "Testing dnf package availability..."
required_packages=("ImageMagick" "gd" "libicu" "oniguruma" "aspell" "libc-client" "mariadb-server")
for package in "${required_packages[@]}"; do
if dnf list available "$package" >/dev/null 2>&1; then
echo " ✓ PASS: $package is available"
else
echo " ✗ FAIL: $package is not available"
fi
done
elif command -v yum >/dev/null 2>&1; then
echo "Testing yum package availability..."
required_packages=("ImageMagick" "gd" "libicu" "oniguruma" "aspell" "libc-client" "mariadb-server")
for package in "${required_packages[@]}"; do
if yum list available "$package" >/dev/null 2>&1; then
echo " ✓ PASS: $package is available"
else
echo " ✗ FAIL: $package is not available"
fi
done
else
echo " INFO: No dnf/yum available, skipping package tests"
fi
echo ""
echo "Test 4: Testing Git clone functionality..."
# Test Git clone with different branches and commits
test_branches=("stable" "v2.4.4" "2.5.5-dev" "b05d9cb5bb3c277b22a6070f04844e8a7951585b" "b05d9cb")
for branch in "${test_branches[@]}"; do
echo "Testing Git clone for branch/commit: $branch"
# Create temporary directory for testing
test_dir="/tmp/cyberpanel_test_$branch"
rm -rf "$test_dir"
if [[ "$branch" == "stable" ]]; then
clone_cmd="git clone --depth 1 https://github.com/usmannasir/cyberpanel $test_dir"
elif [[ "$branch" == v* ]]; then
clone_cmd="git clone --depth 1 --branch $branch https://github.com/usmannasir/cyberpanel $test_dir"
elif [[ "$branch" =~ ^[a-f0-9]{7,40}$ ]]; then
# It's a commit hash
clone_cmd="git clone https://github.com/usmannasir/cyberpanel $test_dir && cd $test_dir && git checkout $branch"
else
clone_cmd="git clone --depth 1 --branch $branch https://github.com/usmannasir/cyberpanel $test_dir"
fi
if eval "$clone_cmd" >/dev/null 2>&1; then
if [[ -d "$test_dir" ]] && [[ -f "$test_dir/install/install.py" ]]; then
echo " ✓ PASS: Successfully cloned $branch"
else
echo " ✗ FAIL: Cloned $branch but missing files"
fi
rm -rf "$test_dir"
else
echo " ✗ FAIL: Failed to clone $branch"
fi
done
echo ""
echo "Test 5: Testing environment variable handling..."
# Test environment variable handling
export CYBERPANEL_BRANCH="2.5.5-dev"
echo "Testing with CYBERPANEL_BRANCH=$CYBERPANEL_BRANCH"
if [[ "$CYBERPANEL_BRANCH" == *"-dev" ]]; then
echo " ✓ PASS: Development branch detected correctly"
else
echo " ✗ FAIL: Development branch not detected"
fi
unset CYBERPANEL_BRANCH
echo ""
echo "=========================================="
echo "Test Summary:"
echo "=========================================="
echo "1. Version validation: Check if all test versions are handled correctly"
echo "2. OS detection: Verify AlmaLinux 9 is detected properly"
echo "3. Package availability: Ensure required packages are available"
echo "4. Git clone: Test cloning different branches/tags"
echo "5. Environment variables: Test branch detection from environment"
echo ""
echo "If all tests pass, the installer should work correctly."
echo "If any tests fail, check the specific error messages above."

View File

@@ -1,105 +0,0 @@
#!/bin/bash
# Test script for CyberPanel Modular Installer
# This script tests the installer without actually installing
echo "🧪 Testing CyberPanel Modular Installer..."
# Test 1: Check if all modules exist
echo "📋 Testing module structure..."
modules=(
"modules/os/detect.sh"
"modules/deps/manager.sh"
"modules/deps/rhel_deps.sh"
"modules/deps/debian_deps.sh"
"modules/install/cyberpanel_installer.sh"
"modules/fixes/cyberpanel_fixes.sh"
"modules/utils/ui.sh"
"modules/utils/menu.sh"
)
for module in "${modules[@]}"; do
if [ -f "$module" ]; then
echo "$module exists"
else
echo "$module missing"
fi
done
# Test 2: Check if cyberpanel.sh is executable
echo ""
echo "📋 Testing main installer..."
if [ -f "cyberpanel.sh" ]; then
echo "✅ cyberpanel.sh exists"
if [ -x "cyberpanel.sh" ]; then
echo "✅ cyberpanel.sh is executable"
else
echo "❌ cyberpanel.sh is not executable"
fi
else
echo "❌ cyberpanel.sh missing"
fi
# Test 3: Test help function
echo ""
echo "📋 Testing help function..."
if ./cyberpanel.sh --help > /dev/null 2>&1; then
echo "✅ Help function works"
else
echo "❌ Help function failed"
fi
# Test 4: Test module loading (dry run)
echo ""
echo "📋 Testing module loading..."
# Create a test script that loads modules
cat > test_modules.sh << 'EOF'
#!/bin/bash
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODULES_DIR="$SCRIPT_DIR/modules"
# Test OS detection module
if [ -f "$MODULES_DIR/os/detect.sh" ]; then
source "$MODULES_DIR/os/detect.sh"
echo "✅ OS detection module loaded"
else
echo "❌ OS detection module not found"
exit 1
fi
# Test UI module
if [ -f "$MODULES_DIR/utils/ui.sh" ]; then
source "$MODULES_DIR/utils/ui.sh"
echo "✅ UI module loaded"
else
echo "❌ UI module not found"
exit 1
fi
echo "✅ All modules loaded successfully"
EOF
chmod +x test_modules.sh
if ./test_modules.sh; then
echo "✅ Module loading test passed"
else
echo "❌ Module loading test failed"
fi
# Cleanup
rm -f test_modules.sh
echo ""
echo "🎉 Test completed!"
echo ""
echo "To use the installer:"
echo " bash cyberpanel.sh # Interactive mode"
echo " bash cyberpanel.sh --debug # Debug mode"
echo " bash cyberpanel.sh --auto # Auto mode"
echo " bash cyberpanel.sh -b v2.5.5-dev # Specific version"

View File

@@ -1,618 +0,0 @@
#!/bin/bash
# CyberPanel Universal Installer Test Script
# Tests the installer on ALL supported operating systems
# Author: CyberPanel Team
# Version: 2.5.5-dev
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
WHITE='\033[1;37m'
NC='\033[0m' # No Color
# Test configuration
TEST_VERSION="v2.5.5-dev"
TEST_LOG_DIR="/tmp/cyberpanel_test_$(date +%Y%m%d_%H%M%S)"
TEST_RESULTS_FILE="$TEST_LOG_DIR/test_results.json"
# Create test log directory
mkdir -p "$TEST_LOG_DIR"
# Function to print colored output
print_status() {
local status=$1
local message=$2
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
case $status in
"INFO")
echo -e "${BLUE}[INFO]${NC} ${message}" | tee -a "$TEST_LOG_DIR/test.log"
;;
"SUCCESS")
echo -e "${GREEN}[SUCCESS]${NC} ${message}" | tee -a "$TEST_LOG_DIR/test.log"
;;
"ERROR")
echo -e "${RED}[ERROR]${NC} ${message}" | tee -a "$TEST_LOG_DIR/test.log"
;;
"WARNING")
echo -e "${YELLOW}[WARNING]${NC} ${message}" | tee -a "$TEST_LOG_DIR/test.log"
;;
"HEADER")
echo -e "${CYAN}${message}${NC}" | tee -a "$TEST_LOG_DIR/test.log"
;;
"DETAIL")
echo -e "${WHITE} ${message}${NC}" | tee -a "$TEST_LOG_DIR/test.log"
;;
esac
}
# Function to detect OS
detect_os() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$NAME
VER=$VERSION_ID
ID=$ID
elif type lsb_release >/dev/null 2>&1; then
OS=$(lsb_release -si)
VER=$(lsb_release -sr)
ID=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
elif [ -f /etc/lsb-release ]; then
. /etc/lsb-release
OS=$DISTRIB_ID
VER=$DISTRIB_RELEASE
ID=$DISTRIB_ID
elif [ -f /etc/debian_version ]; then
OS=Debian
VER=$(cat /etc/debian_version)
ID=debian
elif [ -f /etc/SuSe-release ]; then
OS=SuSE
VER=$(cat /etc/SuSe-release | head -n1 | cut -d' ' -f3)
ID=suse
elif [ -f /etc/redhat-release ]; then
OS=$(cat /etc/redhat-release | cut -d' ' -f1)
VER=$(cat /etc/redhat-release | cut -d' ' -f3)
ID=redhat
else
OS=$(uname -s)
VER=$(uname -r)
ID=unknown
fi
# Normalize OS names
case $ID in
"ubuntu")
OS="Ubuntu"
;;
"debian")
OS="Debian"
;;
"almalinux")
OS="AlmaLinux"
;;
"rocky")
OS="RockyLinux"
;;
"rhel")
OS="RHEL"
;;
"cloudlinux")
OS="CloudLinux"
;;
"centos")
OS="CentOS"
;;
esac
}
# Function to check if OS is supported
is_os_supported() {
local os_id=$1
local os_version=$2
case $os_id in
"ubuntu")
[[ "$os_version" =~ ^(24\.04|22\.04|20\.04)$ ]]
;;
"debian")
[[ "$os_version" =~ ^(13|12|11)$ ]]
;;
"almalinux")
[[ "$os_version" =~ ^(10|9|8)$ ]]
;;
"rocky")
[[ "$os_version" =~ ^(9|8)$ ]]
;;
"rhel")
[[ "$os_version" =~ ^(9|8)$ ]]
;;
"cloudlinux")
[[ "$os_version" =~ ^(9|8)$ ]]
;;
"centos")
[[ "$os_version" =~ ^(7|9)$ ]]
;;
*)
return 1
;;
esac
}
# Function to run pre-installation tests
run_pre_install_tests() {
print_status "INFO" "Running pre-installation tests..."
local test_results=()
# Test 1: System requirements
print_status "INFO" "Testing system requirements..."
# Check architecture
ARCH=$(uname -m)
if [ "$ARCH" = "x86_64" ]; then
print_status "SUCCESS" "Architecture check passed: $ARCH"
test_results+=("arch:pass")
else
print_status "ERROR" "Unsupported architecture: $ARCH (only x86_64 supported)"
test_results+=("arch:fail")
return 1
fi
# Check memory
MEMORY_GB=$(free -g | awk '/^Mem:/{print $2}')
if [ "$MEMORY_GB" -ge 1 ]; then
print_status "SUCCESS" "Memory check passed: ${MEMORY_GB}GB"
test_results+=("memory:pass")
else
print_status "WARNING" "Low memory: ${MEMORY_GB}GB (recommended: 2GB+)"
test_results+=("memory:warning")
fi
# Check disk space
DISK_GB=$(df / | awk 'NR==2{print int($4/1024/1024)}')
if [ "$DISK_GB" -ge 10 ]; then
print_status "SUCCESS" "Disk space check passed: ${DISK_GB}GB"
test_results+=("disk:pass")
else
print_status "ERROR" "Insufficient disk space: ${DISK_GB}GB (minimum: 10GB)"
test_results+=("disk:fail")
return 1
fi
# Test 2: Network connectivity
print_status "INFO" "Testing network connectivity..."
if ping -c 1 google.com >/dev/null 2>&1; then
print_status "SUCCESS" "Network connectivity check passed"
test_results+=("network:pass")
else
print_status "ERROR" "Network connectivity check failed"
test_results+=("network:fail")
return 1
fi
# Test 3: Required commands
print_status "INFO" "Testing required commands..."
local missing_commands=()
for cmd in curl wget python3 git; do
if command -v $cmd >/dev/null 2>&1; then
print_status "SUCCESS" "Command '$cmd' found: $(which $cmd)"
test_results+=("cmd_$cmd:pass")
else
print_status "WARNING" "Command '$cmd' not found"
missing_commands+=($cmd)
test_results+=("cmd_$cmd:missing")
fi
done
# Test 4: Package manager
print_status "INFO" "Testing package manager..."
case $ID in
"ubuntu"|"debian")
if apt update >/dev/null 2>&1; then
print_status "SUCCESS" "APT package manager working"
test_results+=("pkg_mgr:pass")
else
print_status "ERROR" "APT package manager failed"
test_results+=("pkg_mgr:fail")
return 1
fi
;;
"almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux")
if command -v dnf >/dev/null 2>&1; then
if dnf repolist >/dev/null 2>&1; then
print_status "SUCCESS" "DNF package manager working"
test_results+=("pkg_mgr:pass")
else
print_status "ERROR" "DNF package manager failed"
test_results+=("pkg_mgr:fail")
return 1
fi
elif command -v yum >/dev/null 2>&1; then
if yum repolist >/dev/null 2>&1; then
print_status "SUCCESS" "YUM package manager working"
test_results+=("pkg_mgr:pass")
else
print_status "ERROR" "YUM package manager failed"
test_results+=("pkg_mgr:fail")
return 1
fi
else
print_status "ERROR" "No package manager found"
test_results+=("pkg_mgr:fail")
return 1
fi
;;
*)
print_status "WARNING" "Unknown package manager for $OS"
test_results+=("pkg_mgr:unknown")
;;
esac
# Test 5: Python compatibility
print_status "INFO" "Testing Python compatibility..."
PYTHON_VERSION=$(python3 --version 2>&1 | cut -d' ' -f2)
PYTHON_MAJOR=$(echo $PYTHON_VERSION | cut -d'.' -f1)
PYTHON_MINOR=$(echo $PYTHON_VERSION | cut -d'.' -f2)
if [ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -ge 8 ]; then
print_status "SUCCESS" "Python version compatible: $PYTHON_VERSION"
test_results+=("python:pass")
else
print_status "ERROR" "Python version incompatible: $PYTHON_VERSION (requires 3.8+)"
test_results+=("python:fail")
return 1
fi
# Test 6: CyberPanel URLs
print_status "INFO" "Testing CyberPanel URLs..."
local urls=(
"https://cyberpanel.net/install.sh"
"https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/preUpgrade.sh"
"https://github.com/usmannasir/cyberpanel"
)
for url in "${urls[@]}"; do
if curl -I "$url" >/dev/null 2>&1; then
print_status "SUCCESS" "URL accessible: $url"
test_results+=("url_$(echo $url | sed 's/[^a-zA-Z0-9]/_/g'):pass")
else
print_status "ERROR" "URL not accessible: $url"
test_results+=("url_$(echo $url | sed 's/[^a-zA-Z0-9]/_/g'):fail")
return 1
fi
done
# Save test results
printf '%s\n' "${test_results[@]}" > "$TEST_LOG_DIR/pre_install_tests.txt"
print_status "SUCCESS" "Pre-installation tests completed"
return 0
}
# Function to run installation test
run_installation_test() {
print_status "INFO" "Running CyberPanel installation test..."
# Create installation log
local install_log="$TEST_LOG_DIR/installation.log"
# Run installation with logging
print_status "INFO" "Starting CyberPanel installation..."
print_status "INFO" "Version: $TEST_VERSION"
print_status "INFO" "Installation log: $install_log"
# Run the installer
if timeout 1800 bash -c "
sh <(curl https://cyberpanel.net/install.sh || wget -O - https://cyberpanel.net/install.sh) 2>&1 | tee '$install_log'
"; then
print_status "SUCCESS" "Installation completed successfully"
return 0
else
print_status "ERROR" "Installation failed or timed out"
return 1
fi
}
# Function to run post-installation tests
run_post_install_tests() {
print_status "INFO" "Running post-installation tests..."
local test_results=()
# Test 1: Service status
print_status "INFO" "Testing service status..."
# Check LiteSpeed service
if systemctl is-active --quiet lsws; then
print_status "SUCCESS" "LiteSpeed service is running"
test_results+=("lsws_service:pass")
else
print_status "ERROR" "LiteSpeed service is not running"
test_results+=("lsws_service:fail")
fi
# Check CyberPanel service
if systemctl is-active --quiet cyberpanel; then
print_status "SUCCESS" "CyberPanel service is running"
test_results+=("cyberpanel_service:pass")
else
print_status "WARNING" "CyberPanel service is not running (may be normal)"
test_results+=("cyberpanel_service:warning")
fi
# Check MariaDB service
if systemctl is-active --quiet mariadb; then
print_status "SUCCESS" "MariaDB service is running"
test_results+=("mariadb_service:pass")
else
print_status "ERROR" "MariaDB service is not running"
test_results+=("mariadb_service:fail")
fi
# Test 2: Web interface accessibility
print_status "INFO" "Testing web interface accessibility..."
if curl -I http://localhost:8090 >/dev/null 2>&1; then
print_status "SUCCESS" "CyberPanel web interface is accessible"
test_results+=("web_interface:pass")
else
print_status "ERROR" "CyberPanel web interface is not accessible"
test_results+=("web_interface:fail")
fi
# Test 3: Database connectivity
print_status "INFO" "Testing database connectivity..."
if mysql -u root -e "SHOW DATABASES;" >/dev/null 2>&1; then
print_status "SUCCESS" "Database connectivity test passed"
test_results+=("database:pass")
else
print_status "ERROR" "Database connectivity test failed"
test_results+=("database:fail")
fi
# Test 4: File permissions
print_status "INFO" "Testing file permissions..."
local critical_paths=(
"/usr/local/CyberCP"
"/usr/local/lsws"
"/etc/cyberpanel"
)
for path in "${critical_paths[@]}"; do
if [ -d "$path" ]; then
print_status "SUCCESS" "Directory exists: $path"
test_results+=("path_$(echo $path | sed 's/[^a-zA-Z0-9]/_/g'):pass")
else
print_status "ERROR" "Directory missing: $path"
test_results+=("path_$(echo $path | sed 's/[^a-zA-Z0-9]/_/g'):fail")
fi
done
# Save test results
printf '%s\n' "${test_results[@]}" > "$TEST_LOG_DIR/post_install_tests.txt"
print_status "SUCCESS" "Post-installation tests completed"
return 0
}
# Function to generate test report
generate_test_report() {
print_status "INFO" "Generating test report..."
local report_file="$TEST_LOG_DIR/test_report.md"
cat > "$report_file" << EOF
# CyberPanel Universal OS Test Report
**Test Date**: $(date)
**OS**: $OS $VER ($ID)
**Test Version**: $TEST_VERSION
**Test Log Directory**: $TEST_LOG_DIR
## Test Summary
### Pre-Installation Tests
EOF
if [ -f "$TEST_LOG_DIR/pre_install_tests.txt" ]; then
while IFS= read -r line; do
echo "- $line" >> "$report_file"
done < "$TEST_LOG_DIR/pre_install_tests.txt"
fi
cat >> "$report_file" << EOF
### Post-Installation Tests
EOF
if [ -f "$TEST_LOG_DIR/post_install_tests.txt" ]; then
while IFS= read -r line; do
echo "- $line" >> "$report_file"
done < "$TEST_LOG_DIR/post_install_tests.txt"
fi
cat >> "$report_file" << EOF
## Installation Log
\`\`\`
EOF
if [ -f "$TEST_LOG_DIR/installation.log" ]; then
tail -100 "$TEST_LOG_DIR/installation.log" >> "$report_file"
fi
cat >> "$report_file" << EOF
\`\`\`
## System Information
- **OS**: $OS $VER
- **Architecture**: $(uname -m)
- **Memory**: $(free -h | awk '/^Mem:/{print $2}')
- **Disk Space**: $(df -h / | awk 'NR==2{print $4}')
- **Python Version**: $(python3 --version 2>&1)
- **Package Manager**: $(command -v dnf || command -v yum || command -v apt)
## Test Files
- **Test Log**: $TEST_LOG_DIR/test.log
- **Installation Log**: $TEST_LOG_DIR/installation.log
- **Pre-Install Tests**: $TEST_LOG_DIR/pre_install_tests.txt
- **Post-Install Tests**: $TEST_LOG_DIR/post_install_tests.txt
---
*Generated by CyberPanel Universal OS Test Script v2.5.5-dev*
EOF
print_status "SUCCESS" "Test report generated: $report_file"
}
# Function to show help
show_help() {
echo "CyberPanel Universal OS Test Script"
echo ""
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " -h, --help Show this help message"
echo " -v, --version Specify CyberPanel version to test (default: $TEST_VERSION)"
echo " -l, --log-dir Specify custom log directory"
echo " -p, --pre-only Run only pre-installation tests"
echo " -i, --install Run full installation test"
echo " -s, --skip-pre Skip pre-installation tests"
echo ""
echo "This script tests CyberPanel installation on the current system."
echo "It performs comprehensive testing including system requirements,"
echo "package availability, network connectivity, and installation verification."
echo ""
echo "Supported OS:"
echo " - Ubuntu 24.04, 22.04, 20.04"
echo " - Debian 13, 12, 11"
echo " - AlmaLinux 10, 9, 8"
echo " - RockyLinux 9, 8"
echo " - RHEL 9, 8"
echo " - CloudLinux 9, 8"
echo " - CentOS 7, 9, Stream 9"
}
# Main execution
main() {
# Parse command line arguments
local run_pre_tests=true
local run_install_test=false
local run_post_tests=true
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-v|--version)
TEST_VERSION="$2"
shift 2
;;
-l|--log-dir)
TEST_LOG_DIR="$2"
mkdir -p "$TEST_LOG_DIR"
shift 2
;;
-p|--pre-only)
run_pre_tests=true
run_install_test=false
run_post_tests=false
shift
;;
-i|--install)
run_install_test=true
shift
;;
-s|--skip-pre)
run_pre_tests=false
shift
;;
*)
echo "Unknown option: $1"
show_help
exit 1
;;
esac
done
# Detect OS
detect_os
print_status "HEADER" "=========================================="
print_status "HEADER" "CyberPanel Universal OS Test Script"
print_status "HEADER" "=========================================="
print_status "INFO" "Detected OS: $OS $VER ($ID)"
print_status "INFO" "Test Version: $TEST_VERSION"
print_status "INFO" "Log Directory: $TEST_LOG_DIR"
# Check OS support
if ! is_os_supported "$ID" "$VER"; then
print_status "ERROR" "OS $OS $VER is not officially supported"
print_status "INFO" "Supported OS: Ubuntu 24.04/22.04/20.04, Debian 13/12/11, AlmaLinux 10/9/8, RockyLinux 9/8, RHEL 9/8, CloudLinux 9/8, CentOS 7/9"
exit 1
fi
print_status "SUCCESS" "OS $OS $VER is supported"
# Run tests
local exit_code=0
if [ "$run_pre_tests" = true ]; then
if ! run_pre_install_tests; then
print_status "ERROR" "Pre-installation tests failed"
exit_code=1
fi
fi
if [ "$run_install_test" = true ]; then
if ! run_installation_test; then
print_status "ERROR" "Installation test failed"
exit_code=1
fi
fi
if [ "$run_post_tests" = true ] && [ "$run_install_test" = true ]; then
if ! run_post_install_tests; then
print_status "ERROR" "Post-installation tests failed"
exit_code=1
fi
fi
# Generate report
generate_test_report
# Print summary
print_status "HEADER" "=========================================="
print_status "HEADER" "Test Summary"
print_status "HEADER" "=========================================="
print_status "INFO" "Test completed for $OS $VER"
print_status "INFO" "Log directory: $TEST_LOG_DIR"
print_status "INFO" "Report file: $TEST_LOG_DIR/test_report.md"
if [ $exit_code -eq 0 ]; then
print_status "SUCCESS" "All tests passed successfully!"
else
print_status "ERROR" "Some tests failed. Check the logs for details."
fi
exit $exit_code
}
# Run main function
main "$@"

View File

@@ -1,96 +0,0 @@
#!/bin/bash
# Test the standalone installer locally
echo "🧪 Testing standalone CyberPanel installer..."
# Test 1: Check if cyberpanel.sh exists and is executable
if [ -f "cyberpanel.sh" ]; then
echo "✅ cyberpanel.sh exists"
if [ -x "cyberpanel.sh" ]; then
echo "✅ cyberpanel.sh is executable"
else
echo "❌ cyberpanel.sh is not executable"
fi
else
echo "❌ cyberpanel.sh missing"
exit 1
fi
# Test 2: Test help function
echo ""
echo "📋 Testing help function..."
if ./cyberpanel.sh --help > /dev/null 2>&1; then
echo "✅ Help function works"
else
echo "❌ Help function failed"
fi
# Test 3: Test dry run (without actually installing)
echo ""
echo "📋 Testing dry run..."
# Create a test script that simulates the installer
cat > test_dry_run.sh << 'EOF'
#!/bin/bash
# Mock the installer functions for testing
detect_os() {
echo "🔍 Detecting operating system..."
echo "✅ OS detected: AlmaLinux 9 (rhel)"
return 0
}
install_dependencies() {
echo "📦 Installing dependencies..."
echo "✅ Dependencies installed successfully"
return 0
}
install_cyberpanel() {
echo "🚀 Installing CyberPanel..."
echo "✅ CyberPanel installed successfully"
return 0
}
apply_fixes() {
echo "🔧 Applying fixes..."
echo "✅ All fixes applied successfully"
return 0
}
show_status_summary() {
echo "📊 Status summary:"
echo "✅ All services running"
echo "✅ All ports listening"
echo "🎉 Installation completed successfully!"
}
# Test the main flow
echo "🚀 Testing CyberPanel installation flow..."
detect_os
install_dependencies
install_cyberpanel
apply_fixes
show_status_summary
echo "✅ All tests passed!"
EOF
chmod +x test_dry_run.sh
if ./test_dry_run.sh; then
echo "✅ Dry run test passed"
else
echo "❌ Dry run test failed"
fi
# Cleanup
rm -f test_dry_run.sh
echo ""
echo "🎉 Standalone installer test completed!"
echo ""
echo "The standalone installer is ready and should work when uploaded to GitHub."
echo "To use it:"
echo " bash <(curl https://raw.githubusercontent.com/usmannasir/cyberpanel/v2.5.5-dev/cyberpanel.sh) --debug"