| 
									
										
										
										
											2025-09-13 19:07:03 +02:00
										 |  |  | #!/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 | 
					
						
							| 
									
										
										
										
											2025-09-15 12:07:15 +05:00
										 |  |  | import socket | 
					
						
							|  |  |  | import urllib.request | 
					
						
							|  |  |  | import re | 
					
						
							| 
									
										
										
										
											2025-09-13 19:07:03 +02:00
										 |  |  | 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 | 
					
						
							| 
									
										
										
										
											2025-09-15 12:07:15 +05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-13 19:07:03 +02:00
										 |  |  |     Args: | 
					
						
							|  |  |  |         length: Length of the secret key to generate (default 64) | 
					
						
							| 
									
										
										
										
											2025-09-15 12:07:15 +05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-13 19:07:03 +02:00
										 |  |  |     Returns: | 
					
						
							|  |  |  |         str: Random secret key | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     chars = string.ascii_letters + string.digits + '!@#$%^&*(-_=+)' | 
					
						
							|  |  |  |     return ''.join(secrets.choice(chars) for _ in range(length)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-15 12:07:15 +05:00
										 |  |  | 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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-13 19:07:03 +02:00
										 |  |  | 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) | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2025-09-15 12:07:15 +05:00
										 |  |  |     # Auto-detect IP addresses for ALLOWED_HOSTS | 
					
						
							|  |  |  |     print("🔍 Auto-detecting server IP addresses...") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Get hostname and local hostname resolution | 
					
						
							| 
									
										
										
										
											2025-09-13 19:07:03 +02:00
										 |  |  |     try: | 
					
						
							|  |  |  |         hostname = socket.gethostname() | 
					
						
							| 
									
										
										
										
											2025-09-15 12:07:15 +05:00
										 |  |  |         hostname_ip = socket.gethostbyname(hostname) | 
					
						
							| 
									
										
										
										
											2025-09-13 19:07:03 +02:00
										 |  |  |     except: | 
					
						
							|  |  |  |         hostname = 'localhost' | 
					
						
							| 
									
										
										
										
											2025-09-15 12:07:15 +05:00
										 |  |  |         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}") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-13 19:07:03 +02:00
										 |  |  |     # 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 | 
					
						
							| 
									
										
										
										
											2025-09-15 12:07:15 +05:00
										 |  |  | ALLOWED_HOSTS={allowed_hosts_str} | 
					
						
							| 
									
										
										
										
											2025-09-13 19:07:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | # 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) |