config = new backups_c(); self::setBucket('backups'); // Change the bucket to backups self::validateBucket(); } /** * @inheritDoc */ public function validateBucket(): void { // Check if the bucket exists if (!self::getS3Client()->doesBucketExist(self::getBucket())) { // throw an exception throw new Exception('The bucket does not exist in the S3 service! Missing: ' . self::getBucket()); } } /** * @inheritDoc */ public function backup_exists(string $backup_uuid): bool { // Check if the file exists $objects = self::getS3Client()->listObjects([ 'Bucket' => self::getBucket(), 'Prefix' => self::backup_s3_prefix . 'backup_' . $backup_uuid . '.zip' ]); return count($objects['Contents'] ?? []) > 0; } /** * @inheritDoc */ public function getBackupDownloadUrl(string $backup_uuid): string { // Get the presigned URL for the backup return self::getPresignedUrl('backup_' . $backup_uuid . '.zip'); } /** * @inheritDoc */ public function download(string $backup_uuid): string { // Download the backup $path = self::local_backup_path . 'backup_' . $backup_uuid . '.zip'; $result = self::getS3Client()->getObject([ 'Bucket' => self::getBucket(), 'Key' => self::backup_s3_prefix . 'backup_' . $backup_uuid . '.zip', 'SaveAs' => $path ]); return $path; } /** * @inheritDoc * @throws Exception */ public function createBackup($backup_name = null, $backup_description = null): string { // Check if the backup name is set if (!$backup_name) { $backup_name = 'Backup ' . date('Y-m-d H:i:s'); } // Check if the backup description is set if (!$backup_description) { $backup_description = 'Backup created on ' . date('Y-m-d H:i:s'); } echo "[" . date('Y-m-d H:i:s') . "][BACKUP] Creating backup: " . $backup_name . "\n"; echo "[" . date('Y-m-d H:i:s') . "][BACKUP] Description: " . $backup_description . "\n"; echo "[" . date('Y-m-d H:i:s') . "][BACKUP] Generating backup file...\n"; // Generate the backup file $backup_uuid = self::generateBackupFile(); echo "[" . date('Y-m-d H:i:s') . "][BACKUP] Backup file generated: backup_" . $backup_uuid . ".zip\n"; echo "[" . date('Y-m-d H:i:s') . "][BACKUP] Uploading backup file to S3...\n"; // Upload the backup file self::getS3Client()->putObject([ 'Bucket' => self::getBucket(), 'Key' => self::backup_s3_prefix . 'backup_' . $backup_uuid . '.zip', 'SourceFile' => self::local_backup_path . 'backup_' . $backup_uuid . '.zip' ]); echo "[" . date('Y-m-d H:i:s') . "][BACKUP] Backup file uploaded to S3\n"; // Update the metadata echo "[" . date('Y-m-d H:i:s') . "][BACKUP] Creating backup metadata...\n"; self::createBackupMetadata($backup_uuid, $backup_name, $backup_description); echo "[" . date('Y-m-d H:i:s') . "][BACKUP] Backup metadata created and uploaded to S3\n"; // Clean up the backup file echo "[" . date('Y-m-d H:i:s') . "][BACKUP] Cleaning up local backup files...\n"; self::cleanUpBackupFile($backup_uuid); echo "[" . date('Y-m-d H:i:s') . "][BACKUP] Local backup files cleaned up\n"; // Return the backup UUID return $backup_uuid; } /** * @inheritDoc */ public function generateBackupFile(): string { // Generate a UUID for the backup $backup_uuid = uniqid(); // Prepare the backup directories if (!is_dir(self::local_backup_path)) { mkdir(self::local_backup_path); if (!is_dir(self::local_backup_path)) { throw new Exception('Failed to create local backup path: ' . self::local_backup_path); } } if (!is_dir(self::local_backup_path . 'backup_' . $backup_uuid)) { mkdir(self::local_backup_path . 'backup_' . $backup_uuid); if (!is_dir(self::local_backup_path . 'backup_' . $backup_uuid)) { throw new Exception('Failed to create local backup directory: ' . self::local_backup_path . 'backup_' . $backup_uuid); } } // Backup the database $database_path = self::backupDatabase($backup_uuid); // Web server files $webserver_files_path = self::backupServerFiles($backup_uuid); // Environment variables $env_path = self::backupEnvironmentVariables($backup_uuid); // Create the backup path $backup_path = self::local_backup_path . 'backup_' . $backup_uuid . '.zip'; // Create the backups directory if (!is_dir(self::local_backup_path)) { mkdir(self::local_backup_path); } // Create the backup directory if (!is_dir(self::local_backup_path . 'backup_' . $backup_uuid)) { mkdir(self::local_backup_path . 'backup_' . $backup_uuid); } // Add the database backup to the backup directory copy($database_path, self::local_backup_path . 'backup_' . $backup_uuid . '/database.sql'); // Add the web server files to the backup directory copy($webserver_files_path, self::local_backup_path . 'backup_' . $backup_uuid . '/www.zip'); // Add the environment variables to the backup directory copy($env_path, self::local_backup_path . 'backup_' . $backup_uuid . '/environment_variables.json'); // Zip the backup directory exec('zip -r ' . $backup_path . ' ' . self::local_backup_path . 'backup_' . $backup_uuid); // Return the backup UUID return $backup_uuid; } /** * @inheritDoc * @throws Exception */ public function backupDatabase(string $backup_uuid): string { global /** @var db $db */ $db; // Backup the database $path = self::local_backup_path . 'backup_' . $backup_uuid . '/database.sql'; $result = $db->backupDatabase($path); if (!$result) { throw new Exception('Failed to backup the database!'); } return $path; } /** * @inheritDoc */ public function backupServerFiles(string $backup_uuid): string { // Backup the server files from the /var/www/html directory $path = self::local_backup_path . 'backup_' . $backup_uuid . '/www.zip'; exec('zip -r ' . $path . ' /var/www/html'); return $path; } /** * @inheritDoc */ public function backupEnvironmentVariables(string $backup_uuid): string { // Backup the config variables $path = self::local_backup_path . 'backup_' . $backup_uuid . '/environment_variables.json'; file_put_contents($path, json_encode($_ENV)); return $path; } /** * @inheritDoc */ public function createBackupMetadata(string $backup_uuid, string $backup_name, string $backup_description): void { // Create the metadata file $metadata = [ 'backup_name' => $backup_name, 'backup_description' => $backup_description, 'backup_date' => date('Y-m-d H:i:s'), 'backup_size' => filesize(self::local_backup_path . 'backup_' . $backup_uuid . '.zip'), 'hash' => md5_file(self::local_backup_path . 'backup_' . $backup_uuid . '.zip') ]; file_put_contents( self::local_backup_path . 'backup_' . $backup_uuid . '.json', json_encode($metadata) ); // Upload the metadata file self::getS3Client()->putObject([ 'Bucket' => self::getBucket(), 'Key' => self::metadata_s3_prefix . 'backup_' . $backup_uuid . '.json', 'SourceFile' => self::local_backup_path . 'backup_' . $backup_uuid . '.json' ]); } /** * @inheritDoc */ public function cleanupBackupFile(string $backup_uuid): void { /** Clean up the backup files, and remove the temporary directories and files */ // Remove the backup directory unlink(self::local_backup_path . 'backup_' . $backup_uuid . '.zip'); // Remove the metadata file unlink(self::local_backup_path . 'backup_' . $backup_uuid . '.json'); // Remove the database backup unlink(self::local_backup_path . 'backup_' . $backup_uuid . '/database.sql'); // Remove the web server files backup unlink(self::local_backup_path . 'backup_' . $backup_uuid . '/www.zip'); // Remove the environment variables backup unlink(self::local_backup_path . 'backup_' . $backup_uuid . '/environment_variables.json'); // Remove the backup directory rmdir(self::local_backup_path . 'backup_' . $backup_uuid); } /** * @inheritDoc */ public function listBackups(): array { // List the backups $backups = []; $objects = self::getS3Client()->listObjects([ 'Bucket' => self::getBucket(), 'Prefix' => self::metadata_s3_prefix ]); // Check if there are any backups if (!isset($objects['Contents'])) { return []; } foreach ( $objects['Contents'] as $object ) { $backup_uuid = str_replace( self::metadata_s3_prefix . 'backup_', '', str_replace('.json', '', $object['Key']) ); $backups[] = $this->getBackupMetadata($backup_uuid); } return $backups; } /** * @inheritDoc */ public function getBackupMetadata(string $backup_uuid): array { // Get the metadata file $metadata = self::getS3Client()->getObject([ 'Bucket' => self::getBucket(), 'Key' => self::metadata_s3_prefix . 'backup_' . $backup_uuid . '.json' ]); return json_decode($metadata['Body'], true); } }