Backup System v2 - SteamServerUI/StationeersServerUI GitHub Wiki

Stationeers Server UI - Backup System v2 Documentation

The Backup System has been completely overhauled in version 4.x, introducing "Backup System v2", or, just "Backup system" now. This new system offers improved performance, a cleaner architecture, and enhanced features. This system is designed to manage game save backups with advanced retention policies and secure storage.

Table of Contents

  1. Architecture Overview
  2. Core Components
  3. Backup Process
  4. Retention Policy
  5. API Reference
  6. Integration Guide
  7. Configuration

Architecture Overview

The Backup System v2 is built with a modular architecture that separates concerns into distinct components:

  • BackupManager: The central component that coordinates all backup operations.
  • File Watcher: Monitors backup directories for changes and triggers backup processing.
  • Retention Manager: Applies backup retention policies to manage disk space.
  • HTTP API: Provides RESTful endpoints for backup management.

The system handles two types of backup directories:

  • Backup Directory: Where the game saves backups initially.
  • Safe Backup Directory: Where copies are stored with retention policies applied.

New Stationeers Terrain System:

The Backup manager supports the new .save system since SSUI v5.5.X. It follows the same principles with backup groups generally, so all documentation for the save file trio here applies to .save files aswell

Core Components

BackupManager

The BackupManager is the central controller for backup operations. It:

  • Initializes the backup system with appropriate configuration
  • Starts and manages background monitoring processes
  • Coordinates backup and restore operations
  • Applies retention policies through the cleanup process
type BackupManager struct {
    config  BackupConfig
    mu      sync.Mutex
    watcher *fsWatcher
    ctx     context.Context
    cancel  context.CancelFunc
}

Each BackupManager instance is independent with its own configuration, making it possible to manage multiple game worlds (or games..Am I onto something?!) in the future.

File Watcher

The system uses fsnotify to monitor for new backup files. When a new backup file is detected, it:

  1. Validates the file format
  2. Waits a configurable delay to ensure the file is fully written
  3. Copies the file to the safe backup directory
func (m *BackupManager) watchBackups() {
    // Monitors for new backup files and processes them
}

Retention Policy

For configuration details, see the Configuration page.

The retention policy is highly configurable and follows industry best practices:

type RetentionPolicy struct {
    KeepLastN       int           // Keep last N backups regardless of age
    KeepDailyFor    time.Duration // Keep daily backups for this duration
    KeepWeeklyFor   time.Duration // Keep weekly backups for this duration
    KeepMonthlyFor  time.Duration // Keep monthly backups for this duration
    CleanupInterval time.Duration // How often to run cleanup
}

This provides granular control over backup retention to balance disk space with recovery options.

Backup Process

The backup process follows this workflow:

  1. Game creates backup files in the primary backup directory
  2. File watcher detects new backup files
  3. After a delay (default: 30 seconds), files are copied to the safe backup directory
  4. Periodic cleanup runs based on retention policy
  5. Regular backups are kept for 24 hours
  6. Safe backups are managed with the hierarchical retention policy

Backup File Grouping

Backup files are grouped by their index to maintain data consistency. A complete backup consists of:

  • world(N).xml - World data
  • world_meta(N).xml - World metadata
  • world(N).bin - Binary world data

The system ensures all three files are present when listing or restoring backups.

Retention Policy

The retention strategy is hierarchical and intelligent:

  1. Always keep the most recent N backups (configurable)
  2. Daily backups are kept for a configurable period (default: 30 days)
  3. Weekly backups are retained for a longer period (default: 90 days)
  4. Monthly backups are preserved for extended periods (default: 365 days)

This strategy provides a balance between immediate recovery needs and long-term archival.

Cleanup Algorithm

The cleanup algorithm:

  1. Groups backup files by index
  2. Sorts groups by modification time (newest first)
  3. Keeps the most recent N backups
  4. Applies the daily/weekly/monthly retention logic to older backups
  5. Deletes backup groups that don't meet retention criteria

API Reference

The backup system exposes RESTful API endpoints for management:

Endpoints

List Backups

GET /api/v2/backups?limit={limit}
  • Description: Returns a list of available backups
  • Parameters:
    • limit (optional): Maximum number of backups to return
  • Response: JSON array of backup groups with metadata

Restore Backup

GET /api/v2/backups/restore?index={index}
  • Description: Restores a backup with the specified index
  • Parameters:
    • index (required): Index of the backup to restore
  • Response: Success/error message

Authentication

All API endpoints are protected by JWT Cookie authentication. Clients must:

  1. Authenticate using /auth/login
  2. Include the JWT Cookie in subsequent requests

Integration Guide

Using the Global Backup Manager

The system provides a global singleton instance for easy integration:

// Initialize the manager
backupConfig := backupsv2.GetBackupConfig()
err := backupsv2.InitGlobalBackupManager(backupConfig)

// Use the manager throughout your application
backups, err := backupsv2.GlobalBackupManager.ListBackups(10)

Creating Custom Backup Managers

This is not needed and not used the the current state of this Software. For more advanced use cases, we can create custom instances too:

config := backupsv2.BackupConfig{
    WorldName:     "MyWorld",
    BackupDir:     "./saves/MyWorld/Backup",
    SafeBackupDir: "./saves/MyWorld/Safebackups",
    WaitTime:      30 * time.Second,
    RetentionPolicy: backupsv2.RetentionPolicy{
        KeepLastN:       10,
        KeepDailyFor:    30 * 24 * time.Hour,
        KeepWeeklyFor:   90 * 24 * time.Hour,
        KeepMonthlyFor:  365 * 24 * time.Hour,
        CleanupInterval: 1 * time.Hour,
    },
}

manager := backupsv2.NewBackupManager(config)
if err := manager.Initialize(); err != nil {
    // Handle error
}
if err := manager.Start(); err != nil {
    // Handle error
    As Start calls the cleanup go routines too, be careful with "Starting" a new Manager. Initializing it is generally fine.
}

// Don't forget to shut down when done
defer manager.Shutdown()

Configuration

The default configuration can be obtained through GetBackupConfig():

func GetBackupConfig() BackupConfig {
    backupDir := filepath.Join("./saves/" + config.WorldName + "/Backup")
    safeBackupDir := filepath.Join("./saves/" + config.WorldName + "/Safebackups")

    return BackupConfig{
        WorldName:     config.WorldName,
        BackupDir:     backupDir,
        SafeBackupDir: safeBackupDir,
        WaitTime:      30 * time.Second,
        RetentionPolicy: RetentionPolicy{
            KeepLastN:       config.BackupKeepLastN,
            KeepDailyFor:    config.BackupKeepDailyFor,
            KeepWeeklyFor:   config.BackupKeepWeeklyFor,
            KeepMonthlyFor:  config.BackupKeepMonthlyFor,
            CleanupInterval: config.BackupKeepMonthlyFor,
        },
    }
}

Key configuration options:

Option Description Default
WorldName Name of the game world From global config
BackupDir Primary backup directory ./saves/{WorldName}/Backup
SafeBackupDir Safe storage directory ./saves/{WorldName}/Safebackups
WaitTime Delay before processing new backups 30 seconds
KeepLastN Number of recent backups to always keep 10
KeepDailyFor Duration to keep daily backups 30 days
KeepWeeklyFor Duration to keep weekly backups 90 days
KeepMonthlyFor Duration to keep monthly backups 365 days
CleanupInterval Frequency of cleanup operations 1 hour

This documentation is intended for developers. For end-user documentation, please refer to the main wiki.