Skip to content

Sync emeraldhost/wings with Rene-Roscher fork features#1

Merged
Rene-Roscher merged 70 commits into
developfrom
update
May 20, 2026
Merged

Sync emeraldhost/wings with Rene-Roscher fork features#1
Rene-Roscher merged 70 commits into
developfrom
update

Conversation

@Rene-Roscher
Copy link
Copy Markdown
Collaborator

Summary

Bringt den update-Branch (69 Commits ahead von pterodactyl:develop, 0 behind nach dem heutigen upstream-Merge) in emeraldhost/wings:develop.

Inhalt:

  • Echtzeit-Progress-Tracking für Backup/Restore via WebSocket (250ms Intervall)
  • Erweitertes S3-Support (80/20 Progress-Split für Archive/Upload)
  • Neue Server-States backup und restore mit automatischer Recovery
  • Produktions-Härtung: Memory-safe Streaming, Goroutine-Lifecycle-Management, Panic-Recovery
  • Aktivitäts-Logging für SFTP- und Datei-Operationen
  • ZSTD-Kompression für Backups
  • Security: Filename-Sanitization, Max-Download-Size, Path-Traversal-Schutz
  • WebSocket-Progress für Background-Downloads
  • Inklusive Merge von pterodactyl/wings:develop @ ac81409 (clearer download error messaging)
  • CI-Fix: release.yaml Build-Pfad hardcoded auf github.com/Rene-Roscher/wings (Module-Pfad)

Test plan

  • CI Push Workflow: build + test + race auf Go 1.24.11 und 1.25.5, beide GOARCHs
  • CI CodeQL Workflow: keine neuen Security-Findings
  • Nach Merge: Docker-Image wird nach ghcr.io/emeraldhost/wings:develop gepusht
  • Lokaler Smoke-Test: wings --debug --config config.yml startet sauber

- Updated import paths across multiple files to reflect the new module name `github.com/Rene-Roscher/wings`.
- This change affects files in the environment, events, internal, router, server, and sftp packages.
- Ensured consistency in the import statements for better maintainability and clarity.
- Added BackupOperation and BackupOperationRegistry to manage backup and restore operations.
- Implemented methods for registering, cancelling, retrieving, listing, and completing operations.
- Introduced cleanup mechanism for stale operations running longer than a specified duration.
- Added global instance and a background goroutine for periodic cleanup of stale operations.
- Introduced a new `Format` field in the configuration to specify the compression format for backups, supporting "gzip" (default), "zstd", and "none".
- Refactored the archive creation logic to accommodate the new compression format, including methods for creating ZSTD and GZIP writers.
- Implemented automatic format detection during backup restoration, allowing seamless handling of both GZIP and ZSTD compressed backups.
- Updated the `Path()` method to generate appropriate file extensions based on the selected compression format.
- Enhanced S3 backup handling to prevent self-deletion on failure and improved context management.
- Added comprehensive unit tests for compression format detection and decompression functionality.
- Documented the changes and provided a migration strategy to ensure backward compatibility with existing GZIP backups.
…performance

feat(backup): enhance backup state management and context awareness

feat(s3): improve S3 backup handling with context checks and orphaned part cleanup

feat(archive): add security measures for compression format detection and decompression
- Added SftpSecurityConfiguration to manage security settings.
- Introduced SmartSecurityProtector for tracking login attempts and blocking IPs based on thresholds.
- Enhanced SFTP server to utilize smart protection during authentication.
- Updated backup and restore processes to support context-aware operations.
- Improved logging for security events and actions.
- Added comprehensive configuration guide for optimized backup settings.
…and enhancing debug logging for initial and final progress events
- Introduced a detailed WORK.md outlining backup requirements and integrity guarantees.
- Developed a compression package with support for GZIP, ZSTD, TAR, and uncompressed formats, including a registry for extensibility.
- Created extensive unit tests for backup cleanup, progress tracking, retry logic, and queue management to ensure robustness and reliability.
- Implemented logic for handling backup retries with exponential backoff and context management.
- Ensured backward compatibility and minimal invasiveness in changes to the existing backup system.
- Validated progress tracking for S3 uploads with an 80/20 split between archiving and uploading phases.
…rogress tracking and real-time event management
…ved security and consistency

feat(archive): update ZSTD writer and reader to use default settings for maximum compatibility
feat(tests): remove integrity test file as it is no longer needed
…ted compression formats

refactor(archive): eliminate ZSTD support and related functions to prevent binary corruption
refactor(compress): remove system tar extraction logic to streamline decompression process
delete(tests): remove ZSTD compression tests as the feature is no longer supported
…phase to prevent written bytes exceeding total
…wnload size to prevent path traversal and DoS attacks
Pulls in upstream commit ac81409 ("clearer error messaging on downloads,
don't log as a 500-level error"). Brings our update branch fully in sync
with pterodactyl/wings:develop (0 commits behind).

Conflict resolution:
- router/downloader/downloader.go: kept our redirect-loop refactor;
  IsDownloadError() and the 30s dialer / 2h client timeouts from upstream
  applied cleanly outside the conflict zone.
- router/router_server_files.go: adopted upstream's IsDownloadError-gated
  error logging and the 400+JSON response for download errors; preserved
  our SaveActivity() call so file-download activity logging remains intact.
The release workflow built `github.com/${{ github.repository_owner }}/wings`,
which on the emeraldhost/wings fork mirror resolves to
`github.com/emeraldhost/wings` — but go.mod declares
`github.com/Rene-Roscher/wings` as the module path. Building against a
non-matching import path fails. Hardcode to the actual module path so
release builds succeed on any mirror.
// If not found as Local backup, check if it's an S3 backup file that exists locally
// S3 backups may leave local files behind after failed uploads or for debugging
s3Backup := backup.NewS3(client, backupID, "")
if _, err := os.Stat(s3Backup.Path()); err == nil {
Comment thread server/backup.go
}

// Basic file existence and size check
stat, err := os.Stat(backupPath)
Comment thread server/backup.go
}

// Quick magic bytes check for GZIP
f, err := os.Open(backupPath)
Comment thread server/backup.go
serverChecksum := "unknown"

// Get backup file SHA1 (reuse existing checksum method)
if backupFile, err := os.Open(backupPath); err == nil {
Comment thread server/backup.go
func (s *Server) countBackupEntries(backupPath string) (*fileStats, error) {
stats := &fileStats{}

f, err := os.Open(backupPath)
if os.IsNotExist(err) {
logger.Debug("backup directory does not exist, nothing to clean up")
return nil
}
failedRemovals = append(failedRemovals, fileName)
} else {
logger.WithField("file", fileName).Info("removed backup file")
removedFiles = append(removedFiles, fileName)
}()

// Check if backup archive already exists (S3 two-phase backup)
if _, err := os.Stat(s.Path()); os.IsNotExist(err) {
Comment thread server/server.go
})

// List all files in backup directory
files, err := os.ReadDir(backupDir)
Comment thread server/server.go

logger.WithField("file", fileName).Debug("found backup file, attempting removal")

if err := os.Remove(filePath); err != nil {
@Rene-Roscher Rene-Roscher merged commit 9eab572 into develop May 20, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants