diff --git a/k8s/games/minecraft/configmaps.yaml b/k8s/games/minecraft/configmaps.yaml new file mode 100644 index 0000000..627538a --- /dev/null +++ b/k8s/games/minecraft/configmaps.yaml @@ -0,0 +1,451 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: nginx-config + namespace: minecraft +data: + nginx.conf: | + user nginx; + worker_processes 1; + error_log /var/log/nginx/error.log warn; + pid /var/run/nginx.pid; + + events { + worker_connections 1024; + } + + http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + server { + listen 80; + + # Custom 502 error page with auto-refresh + error_page 502 /502.html; + location = /502.html { + internal; + return 200 'Server Loading

Server is loading probably...

Please wait a moment and try refreshing the page.

'; + add_header Content-Type text/html; + } + + # Main location - proxy to Minecraft Dynmap + location / { + # Proxy configuration for Dynmap server + proxy_pass http://localhost:8123; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Inject user authentication meta tag into HTML head + sub_filter '' ''; + + # Replace default Dynmap title with custom server name + sub_filter 'Minecraft Dynamic Map' "Hexor's MC server"; + + # Inject all custom content before closing body tag (single replacement) + sub_filter "" '

GEYMERSKIY SOYUZ Server
Get Prism Launcher and client.zip for this server. Server address minecraft.hexor.cy:30565
Requires Java 8

Windows Install Script

'; + + # Apply sub_filter replacements globally (not just once) + sub_filter_once off; + } + + # Static file serving for client downloads + location /clients/ { + alias /mc/clients/; + sendfile on; # Enable efficient file serving + add_header Content-Disposition "attachment"; # Force download + autoindex on; # Enable directory listing + gzip off; # Disable compression for downloads + chunked_transfer_encoding off; # Disable chunked encoding + } + } + } + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: win-install-script + namespace: minecraft +data: + win-install.ps1: | + # Game Setup Script for PrismLauncher and Minecraft Client + # This script downloads and configures PrismLauncher with Hexor client + + param( + [string]$Username = "", + [string]$InstallPath = "$env:USERPROFILE\Games\PrismLauncher" + ) + + # Enable TLS 1.2 for downloads + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + + # Function to write colored log messages + function Write-Log { + param( + [string]$Message, + [string]$Level = "INFO" + ) + + switch ($Level) { + "INFO" { + Write-Host "[" -NoNewline + Write-Host "INFO" -ForegroundColor Blue -NoNewline + Write-Host "] $Message" + } + "WARN" { + Write-Host "[" -NoNewline + Write-Host "WARN" -ForegroundColor Yellow -NoNewline + Write-Host "] $Message" + } + "ERROR" { + Write-Host "[" -NoNewline + Write-Host "ERROR" -ForegroundColor Red -NoNewline + Write-Host "] $Message" + } + "SUCCESS" { + Write-Host "[" -NoNewline + Write-Host "SUCCESS" -ForegroundColor Green -NoNewline + Write-Host "] $Message" + } + } + } + + # Function to download file with progress + function Download-File { + param( + [string]$Url, + [string]$OutputPath + ) + + try { + Write-Log "Downloading from: $Url" + Write-Log "Saving to: $OutputPath" + + if (Test-Path $OutputPath) { + Remove-Item $OutputPath -Force + Write-Log "Removed existing file to avoid corruption" "WARN" + } + + $webClient = New-Object System.Net.WebClient + $webClient.DownloadFile($Url, $OutputPath) + + if (Test-Path $OutputPath) { + $fileSize = (Get-Item $OutputPath).Length + Write-Log "Download completed successfully ($fileSize bytes)" "SUCCESS" + return $true + } else { + Write-Log "Download failed - file not found" "ERROR" + return $false + } + } + catch { + Write-Log "Download failed: $($_.Exception.Message)" "ERROR" + return $false + } + } + + # Function to extract ZIP archive + function Extract-Archive { + param( + [string]$ArchivePath, + [string]$DestinationPath + ) + + try { + Write-Log "Extracting archive: $ArchivePath" + Write-Log "Destination: $DestinationPath" + + if (!(Test-Path $ArchivePath)) { + Write-Log "Archive file not found: $ArchivePath" "ERROR" + return $false + } + + $fileSize = (Get-Item $ArchivePath).Length + if ($fileSize -lt 1000) { + Write-Log "Archive file too small ($fileSize bytes), probably corrupted" "ERROR" + return $false + } + + if (!(Test-Path $DestinationPath)) { + New-Item -ItemType Directory -Path $DestinationPath -Force | Out-Null + } + + $existingFiles = Get-ChildItem -Path $DestinationPath -File | Where-Object { $_.Extension -ne ".zip" } + $existingDirs = Get-ChildItem -Path $DestinationPath -Directory + + if ($existingFiles.Count -gt 0 -or $existingDirs.Count -gt 0) { + Write-Log "Clearing existing files in destination directory" "WARN" + $existingFiles | Remove-Item -Force -ErrorAction SilentlyContinue + $existingDirs | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue + } + + Add-Type -AssemblyName System.IO.Compression.FileSystem + + try { + $zip = [System.IO.Compression.ZipFile]::OpenRead($ArchivePath) + $entryCount = $zip.Entries.Count + $zip.Dispose() + Write-Log "ZIP file validated ($entryCount entries)" "SUCCESS" + } + catch { + Write-Log "ZIP file validation failed: $($_.Exception.Message)" "ERROR" + return $false + } + + [System.IO.Compression.ZipFile]::ExtractToDirectory($ArchivePath, $DestinationPath) + + Write-Log "Archive extracted successfully" "SUCCESS" + return $true + } + catch { + Write-Log "Archive extraction failed: $($_.Exception.Message)" "ERROR" + + if (Test-Path $ArchivePath) { + Write-Log "Removing potentially corrupted archive file" "WARN" + Remove-Item $ArchivePath -Force -ErrorAction SilentlyContinue + } + + return $false + } + } + + # Function to check Java installation + function Check-JavaInstallation { + try { + $javaVersion = java -version 2>&1 | Select-String "version" + if ($javaVersion) { + Write-Log "Java is installed: $($javaVersion.ToString().Trim())" "SUCCESS" + return $true + } + } + catch { + Write-Log "Java is not installed or not in PATH" "WARN" + Write-Log "Please download Java from: https://www.java.com/en/download/manual.jsp" "WARN" + Write-Log "Look for 'Windows Offline (64-bit)' version" "WARN" + + $response = Read-Host "Do you want to continue without Java? (y/n)" + if ($response -eq 'y' -or $response -eq 'Y') { + Write-Log "Continuing without Java verification" "WARN" + return $true + } else { + Write-Log "Installation cancelled. Please install Java first." "ERROR" + return $false + } + } + } + + # Function to generate a random hex string (UUID-like without dashes) + function New-RandomHexId { + param([int]$Length = 32) + $bytes = New-Object byte[] ($Length / 2) + $rng = [System.Security.Cryptography.RandomNumberGenerator]::Create() + $rng.GetBytes($bytes) + $rng.Dispose() + return ($bytes | ForEach-Object { $_.ToString("x2") }) -join '' + } + + # Function to create accounts.json file with offline account + function Create-AccountsFile { + param( + [string]$TargetPath, + [string]$PlayerName + ) + + $accountsPath = Join-Path $TargetPath "accounts.json" + $profileId = New-RandomHexId -Length 32 + $clientToken = New-RandomHexId -Length 32 + $iat = [int][double]::Parse((Get-Date -UFormat %s)) + + $accountsObj = @{ + accounts = @( + @{ + entitlement = @{ + canPlayMinecraft = $true + ownsMinecraft = $true + } + "msa-client-id" = "" + type = "MSA" + }, + @{ + active = $true + entitlement = @{ + canPlayMinecraft = $true + ownsMinecraft = $true + } + profile = @{ + capes = @() + id = $profileId + name = $PlayerName + skin = @{ + id = "" + url = "" + variant = "" + } + } + type = "Offline" + ygg = @{ + extra = @{ + clientToken = $clientToken + userName = $PlayerName + } + iat = $iat + token = "0" + } + } + ) + formatVersion = 3 + } + + try { + $accountsObj | ConvertTo-Json -Depth 10 | Out-File -FilePath $accountsPath -Encoding UTF8 + Write-Log "Created accounts.json at: $accountsPath" "SUCCESS" + Write-Log "Player name: $PlayerName" "SUCCESS" + return $true + } + catch { + Write-Log "Failed to create accounts.json: $($_.Exception.Message)" "ERROR" + return $false + } + } + + # Main installation process + Write-Log "Starting PrismLauncher and Minecraft client setup" + Write-Log "Player name: $Username" + Write-Log "Installation path: $InstallPath" + + # Create installation directory and clear if exists (but keep ZIP files) + if (Test-Path $InstallPath) { + Write-Log "Installation directory exists, clearing contents" "WARN" + $existingFiles = Get-ChildItem -Path $InstallPath -File | Where-Object { $_.Extension -ne ".zip" } + $existingDirs = Get-ChildItem -Path $InstallPath -Directory + + $existingFiles | Remove-Item -Force -ErrorAction SilentlyContinue + $existingDirs | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue + } else { + New-Item -ItemType Directory -Path $InstallPath -Force | Out-Null + Write-Log "Created installation directory: $InstallPath" + } + + # Step 1: Download PrismLauncher + Write-Log "Step 1: Downloading PrismLauncher..." + $launcherUrl = "https://github.com/PrismLauncher/PrismLauncher/releases/download/8.4/PrismLauncher-Windows-MSVC-Portable-8.4.zip" + $launcherZip = Join-Path $InstallPath "PrismLauncher-8.4.zip" + $launcherExtractPath = Join-Path $InstallPath "PrismLauncher-Windows-MSVC-Portable-8.4" + + if (!(Download-File -Url $launcherUrl -OutputPath $launcherZip)) { + Write-Log "Failed to download PrismLauncher. Exiting." "ERROR" + exit 1 + } + + # Step 2: Extract PrismLauncher + Write-Log "Step 2: Extracting PrismLauncher..." + if (!(Extract-Archive -ArchivePath $launcherZip -DestinationPath $InstallPath)) { + Write-Log "Failed to extract PrismLauncher. Exiting." "ERROR" + exit 1 + } + + # Find the actual extracted directory + $extractedDirs = Get-ChildItem -Path $InstallPath -Directory | Where-Object { $_.Name -like "*PrismLauncher*" } + if ($extractedDirs.Count -gt 0) { + $launcherExtractPath = $extractedDirs[0].FullName + Write-Log "Found PrismLauncher directory: $launcherExtractPath" "SUCCESS" + } else { + Write-Log "Could not find extracted PrismLauncher directory. Checking for direct extraction..." "WARN" + $prismExe = Join-Path $InstallPath "prismlauncher.exe" + if (Test-Path $prismExe) { + $launcherExtractPath = $InstallPath + Write-Log "PrismLauncher extracted directly to: $launcherExtractPath" "SUCCESS" + } else { + Write-Log "Failed to locate PrismLauncher files. Exiting." "ERROR" + exit 1 + } + } + + # Step 3: Create accounts.json in InstallPath (only if username provided) + if ($Username -and $Username -ne "web-user") { + Write-Log "Step 3: Creating accounts configuration for $Username..." + if (!(Create-AccountsFile -TargetPath $InstallPath -PlayerName $Username)) { + Write-Log "Failed to create accounts.json. Exiting." "ERROR" + exit 1 + } + } else { + Write-Log "Step 3: No username provided, skipping accounts.json creation" "WARN" + } + + # Step 4: Check Java installation + Write-Log "Step 4: Checking Java installation..." + if (!(Check-JavaInstallation)) { + Write-Log "Java check failed. Exiting." "ERROR" + exit 1 + } + + # Step 5: Download Minecraft client + Write-Log "Step 5: Downloading Minecraft client..." + $minecraftUrl = "https://minecraft.hexor.cy/clients/1.12.2.zip" + $minecraftZip = Join-Path $InstallPath "minecraft-1.12.2.zip" + $instancesPath = Join-Path $launcherExtractPath "instances" + $hexorPath = Join-Path $instancesPath "Hexor" + + if (!(Download-File -Url $minecraftUrl -OutputPath $minecraftZip)) { + Write-Log "Failed to download Minecraft client. Exiting." "ERROR" + exit 1 + } + + # Step 6: Create instances directory and extract Minecraft client + Write-Log "Step 6: Setting up Minecraft client..." + if (!(Test-Path $instancesPath)) { + New-Item -ItemType Directory -Path $instancesPath -Force | Out-Null + Write-Log "Created instances directory" + } + + if (!(Test-Path $hexorPath)) { + New-Item -ItemType Directory -Path $hexorPath -Force | Out-Null + Write-Log "Created Hexor instance directory" + } + + if (!(Extract-Archive -ArchivePath $minecraftZip -DestinationPath $hexorPath)) { + Write-Log "Failed to extract Minecraft client. Exiting." "ERROR" + exit 1 + } + + # Step 7: Cleanup temporary files + Write-Log "Step 7: Cleaning up temporary files..." + try { + Remove-Item $launcherZip -Force + Remove-Item $minecraftZip -Force + Write-Log "Temporary files cleaned up" "SUCCESS" + } + catch { + Write-Log "Could not remove temporary files: $($_.Exception.Message)" "WARN" + } + + # Final success message + Write-Log "=== INSTALLATION COMPLETED SUCCESSFULLY ===" "SUCCESS" + Write-Log "PrismLauncher location: $launcherExtractPath" "SUCCESS" + Write-Log "Executable: $(Join-Path $launcherExtractPath 'prismlauncher.exe')" "SUCCESS" + Write-Log "Minecraft client installed in: $hexorPath" "SUCCESS" + if ($Username -and $Username -ne "web-user") { + Write-Log "Player name configured: $Username" "SUCCESS" + Write-Log "Accounts file: $(Join-Path $InstallPath 'accounts.json')" "SUCCESS" + } + Write-Log "" + Write-Log "You can now run PrismLauncher and the Hexor instance should be available!" + Write-Log "If Java was not installed, please download it from: https://www.java.com/en/download/manual.jsp" + + # Ask if user wants to launch the game + $launchResponse = Read-Host "Do you want to launch PrismLauncher now? (y/n)" + if ($launchResponse -eq 'y' -or $launchResponse -eq 'Y') { + $launcherExe = Join-Path $launcherExtractPath "prismlauncher.exe" + if (Test-Path $launcherExe) { + Write-Log "Launching PrismLauncher..." "INFO" + Start-Process -FilePath $launcherExe -WorkingDirectory $launcherExtractPath + } else { + Write-Log "Launcher executable not found!" "ERROR" + } + } + + diff --git a/k8s/games/minecraft/deployments.yaml b/k8s/games/minecraft/deployments.yaml index 2958d60..21dca75 100644 --- a/k8s/games/minecraft/deployments.yaml +++ b/k8s/games/minecraft/deployments.yaml @@ -1,69 +1,3 @@ ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: nginx-config - namespace: minecraft -data: - nginx.conf: | - user nginx; - worker_processes 1; - error_log /var/log/nginx/error.log warn; - pid /var/run/nginx.pid; - - events { - worker_connections 1024; - } - - http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - server { - listen 80; - - # Custom 502 error page with auto-refresh - error_page 502 /502.html; - location = /502.html { - internal; - return 200 'Server Loading

Server is loading probably...

Please wait a moment and try refreshing the page.

'; - add_header Content-Type text/html; - } - - # Main location - proxy to Minecraft Dynmap - location / { - # Proxy configuration for Dynmap server - proxy_pass http://localhost:8123; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - - # Inject user authentication meta tag into HTML head - sub_filter '' ''; - - # Replace default Dynmap title with custom server name - sub_filter 'Minecraft Dynamic Map' "Hexor's MC server"; - - # Inject all custom content before closing body tag (single replacement) - sub_filter "" '

GEYMERSKIY SOYUZ Server
Get Prism Launcher and client.zip for this server. Server address minecraft.hexor.cy:30565
Requires Java 8

Windows Install Script

'; - - # Apply sub_filter replacements globally (not just once) - sub_filter_once off; - } - - # Static file serving for client downloads - location /clients/ { - alias /mc/clients/; - sendfile on; # Enable efficient file serving - add_header Content-Disposition "attachment"; # Force download - autoindex on; # Enable directory listing - gzip off; # Disable compression for downloads - chunked_transfer_encoding off; # Disable chunked encoding - } - } - } - --- apiVersion: apps/v1 kind: Deployment @@ -94,6 +28,9 @@ spec: - name: nginx-config configMap: name: nginx-config + - name: win-install-script + configMap: + name: win-install-script terminationGracePeriodSeconds: 10 containers: @@ -178,6 +115,9 @@ spec: subPath: nginx.conf - name: storage mountPath: /mc + - name: win-install-script + mountPath: /mc/clients/win-install.ps1 + subPath: win-install.ps1 --- apiVersion: v1 diff --git a/k8s/games/minecraft/kustomization.yaml b/k8s/games/minecraft/kustomization.yaml index 7aa0734..7ceb8a3 100644 --- a/k8s/games/minecraft/kustomization.yaml +++ b/k8s/games/minecraft/kustomization.yaml @@ -5,4 +5,4 @@ resources: - app.yaml - deployments.yaml - services.yaml - #- ingress.yaml + - configmaps.yaml