#!/bin/bash ####################################### # WordPress Platform Installation Script # Allows anonymous users to create WP sites in random subfolders # For Amazon Linux 2023 / Amazon Linux 2 ####################################### set -e # Exit on any error # Color codes for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Function to print colored messages print_message() { echo -e "${GREEN}[INFO]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } # Check if running as root if [ "$EUID" -ne 0 ]; then print_error "Please run this script as root or with sudo" exit 1 fi # Get server's public IP address SERVER_IP=$(curl -s http://checkip.amazonaws.com || curl -s http://ifconfig.me || curl -s http://icanhazip.com) if [ -z "$SERVER_IP" ]; then print_error "Could not detect public IP address" exit 1 fi # Configuration variables DB_ROOT_PASSWORD=$(openssl rand -base64 16) PLATFORM_DIR="/var/www/html" SITES_DATA_DIR="/var/wp-sites-data" print_message "Starting WordPress Platform installation..." print_message "This script will install Apache, MariaDB, PHP, and create a WordPress platform" print_message "Detected server public IP: ${SERVER_IP}" # Update system packages print_message "Updating system packages..." yum update -y # Install Apache print_message "Installing Apache web server..." yum install -y httpd # Start and enable Apache systemctl start httpd systemctl enable httpd # Install MariaDB (MySQL alternative) print_message "Installing MariaDB server..." yum install -y mariadb105-server # Start and enable MariaDB systemctl start mariadb systemctl enable mariadb # Secure MariaDB installation print_message "Securing MariaDB installation..." mysql -u root < ${SITES_DATA_DIR}/db-root-password.txt chmod 640 ${SITES_DATA_DIR}/db-root-password.txt chown root:apache ${SITES_DATA_DIR}/db-root-password.txt # Create the main platform landing page print_message "Creating platform landing page..." cat > ${PLATFORM_DIR}/index.php <<'PHPEOF' WordPress Platform

🚀 WordPress Platform

Create your own WordPress website instantly. Click the button below to get started!

PHPEOF # Create the site creation PHP script print_message "Creating site creation backend..." cat > ${PLATFORM_DIR}/create-site.php <<'PHPEOF' false, 'message' => 'Server capacity reached. Cannot create new sites at this time. (Available: ' . round($freeSpaceGB, 2) . ' GB)' ]); exit; } // Function to generate random 4-character string function generateRandomString() { $characters = 'abcdefghijklmnopqrstuvwxyz'; $randomString = ''; for ($i = 0; $i < 4; $i++) { $randomString .= $characters[rand(0, strlen($characters) - 1)]; } return $randomString; } // Function to generate random password function generatePassword($length = 12) { return substr(base64_encode(random_bytes($length)), 0, $length); } // Generate unique site identifier $maxAttempts = 100; $attempt = 0; do { $siteId = generateRandomString(); $sitePath = "/var/www/html/$siteId"; $attempt++; } while (file_exists($sitePath) && $attempt < $maxAttempts); if ($attempt >= $maxAttempts) { echo json_encode(['success' => false, 'message' => 'Could not generate unique site ID']); exit; } // Database credentials $dbName = "wp_" . $siteId; $dbUser = "user_" . $siteId; $dbPassword = generatePassword(16); $dbRootPassword = file_get_contents('/var/wp-sites-data/db-root-password.txt'); try { // Create database and user $conn = new mysqli('localhost', 'root', trim($dbRootPassword)); if ($conn->connect_error) { throw new Exception("Database connection failed"); } $dbName = $conn->real_escape_string($dbName); $dbUser = $conn->real_escape_string($dbUser); $conn->query("CREATE DATABASE IF NOT EXISTS `$dbName` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); $conn->query("CREATE USER IF NOT EXISTS '$dbUser'@'localhost' IDENTIFIED BY '$dbPassword'"); $conn->query("GRANT ALL PRIVILEGES ON `$dbName`.* TO '$dbUser'@'localhost'"); $conn->query("FLUSH PRIVILEGES"); $conn->close(); // Download and extract WordPress $wpZip = "/tmp/wordpress-$siteId.tar.gz"; file_put_contents($wpZip, file_get_contents('https://wordpress.org/latest.tar.gz')); // Extract to site directory mkdir($sitePath, 0755, true); exec("tar -xzf $wpZip -C /tmp/"); exec("cp -r /tmp/wordpress/* $sitePath/"); exec("rm -rf /tmp/wordpress $wpZip"); // Create wp-config.php $wpConfig = file_get_contents("$sitePath/wp-config-sample.php"); $wpConfig = str_replace('database_name_here', $dbName, $wpConfig); $wpConfig = str_replace('username_here', $dbUser, $wpConfig); $wpConfig = str_replace('password_here', $dbPassword, $wpConfig); // Get security keys $salts = file_get_contents('https://api.wordpress.org/secret-key/1.1/salt/'); $wpConfig = preg_replace( '/put your unique phrase here/i', '', $wpConfig ); $wpConfig = str_replace( "define( 'AUTH_KEY', 'put your unique phrase here' );", $salts, $wpConfig ); file_put_contents("$sitePath/wp-config.php", $wpConfig); // Set proper permissions exec("chown -R apache:apache $sitePath"); exec("find $sitePath -type d -exec chmod 755 {} \;"); exec("find $sitePath -type f -exec chmod 644 {} \;"); // Save site info $siteInfo = [ 'site_id' => $siteId, 'created' => date('Y-m-d H:i:s'), 'db_name' => $dbName, 'db_user' => $dbUser, 'db_password' => $dbPassword, 'path' => $sitePath ]; file_put_contents("/var/wp-sites-data/$siteId.json", json_encode($siteInfo, JSON_PRETTY_PRINT)); // Get server IP from the HTTP request (which will be the public IP the user is accessing) $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http'; $serverIp = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME']; echo json_encode([ 'success' => true, 'site_id' => $siteId, 'url' => "$protocol://$serverIp/$siteId", 'db_name' => $dbName, 'db_user' => $dbUser, 'db_password' => $dbPassword ]); } catch (Exception $e) { // Clean up on error if (isset($sitePath) && file_exists($sitePath)) { exec("rm -rf $sitePath"); } if (isset($conn)) { $conn->query("DROP DATABASE IF EXISTS `$dbName`"); $conn->query("DROP USER IF EXISTS '$dbUser'@'localhost'"); } echo json_encode(['success' => false, 'message' => $e->getMessage()]); } ?> PHPEOF # Create the disk space check script print_message "Creating disk space check script..." cat > ${PLATFORM_DIR}/check-space.php <<'PHPEOF' $freeSpaceGB >= 5, 'free_space_gb' => round($freeSpaceGB, 2) ]); ?> PHPEOF # Set proper permissions print_message "Setting file permissions..." chown -R apache:apache ${PLATFORM_DIR} chmod 755 ${PLATFORM_DIR}/index.php chmod 755 ${PLATFORM_DIR}/create-site.php chmod 755 ${PLATFORM_DIR}/check-space.php # Configure Apache print_message "Configuring Apache..." cat > /etc/httpd/conf.d/wordpress-platform.conf < ServerAdmin admin@example.com ServerName ${SERVER_IP} DocumentRoot ${PLATFORM_DIR} Options FollowSymLinks AllowOverride All Require all granted DirectoryIndex index.php index.html # Allow access to all subdirectories Options FollowSymLinks AllowOverride All Require all granted ErrorLog /var/log/httpd/platform_error.log CustomLog /var/log/httpd/platform_access.log combined EOF # Update main Apache config to allow .htaccess overrides sed -i '//,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/httpd/conf/httpd.conf # Restart Apache print_message "Restarting Apache..." systemctl restart httpd # Save credentials to file CREDS_FILE="/root/wordpress-platform-credentials.txt" cat > ${CREDS_FILE} < Security Groups > Edit Inbound Rules" echo " Add rule: Type: HTTP, Port: 80, Source: 0.0.0.0/0" echo "" print_warning "Important Notes:" echo " - Each WordPress site is completely independent" echo " - Monitor disk space - each site takes ~50MB" echo " - Site credentials are shown on creation and saved to ${SITES_DATA_DIR}" echo " - Consider implementing rate limiting for production" echo "" print_message "Installation log: /var/log/httpd/platform_*.log" print_message "=========================================="