Pterodactyl Wings

repository·develop·Indexed 21 days ago

https://github.com/pterodactyl/wings

A high-performance control plane for Pterodactyl that manages server instances, provides an HTTP API for lifecycle control, and hosts a built-in SFTP server for file management. It acts as the bridge between the Pterodactyl Panel and running game server instances, featuring automated configuration, diagnostics tools, and integrated SSL management via Let's Encrypt.

Tokens
3.6K
Snippets
16
Records
26
Agent score
76%

What's inside Wings

  1. What is Pterodactyl Wings

    develop

    Wings is the server control plane for Pterodactyl. It is designed to be highly performant and secure, acting as the bridge between the Pterodactyl Panel and the actual running game server instances.

    Key capabilities include:

    • HTTP API: Provides a direct interface to manage server lifecycles, fetch logs, and generate backups.
    • Built-in SFTP Server: Allows users to manage files using the same credentials used for the Pterodactyl Panel, eliminating the need for external SFTP dependencies.
  2. SFTP Username Format Requirement

    develop

    The SFTP server enforces a specific username format via a regular expression before attempting to validate credentials against the API. This acts as a basic protection against bot floods.

    Expected format: [username].[8-character-alphanumeric-suffix] (case-insensitive).

  3. How Server state and crash detection work

    develop

    The Server struct manages the lifecycle and state of a server process.

    State Tracking State is tracked via OnStateChange(), which is called when the underlying environment (e.g., Docker) reports a change. This method:

    1. Updates the internal resources.State.
    2. Publishes a StatusEvent to the server's event bus if the state has changed.
    3. Resets resource usage to 0 if the state becomes environment.ProcessOfflineState.

    Crash Detection If a server transitions from a running/starting state directly to an offline state, Wings detects this as a crash. It then triggers a background handleServerCrash() routine. This routine manages automatic restarts based on configured thresholds to prevent infinite restart loops if a server is crashing too frequently.

  4. How automatic TLS works in Wings

    develop

    When running Wings with the --auto-tls flag, the application uses autocert to manage SSL certificates via Let's Encrypt.

    Requirements:

    • You must provide a --tls-hostname (e.g., my.example.com).
    • Wings will attempt to solve ACME challenges via HTTP-01. It starts a separate HTTP server on port 80 to handle these challenges.
    • Certificates are cached in the system's root directory under /.tls-cache.

    Example usage:

    ./wings --auto-tls --tls-hostname my.example.com
  5. Run the Wings API server

    develop
    The primary command for Wings is the root command, which starts the API server. This server allows the Pterodactyl Panel to programmatically control game servers. When running, Wings initializes the system environment, manages Docker containers, handles SFTP connections, and runs a cron scheduler for scheduled tasks.
    ./wings
  6. Initialize a new Server instance with New()

    develop

    To create a new high-level server instance, use the New function. This initializes the server with a background context, default values, and necessary synchronization primitives (like powerLock and sinks). You must provide a remote.Client which is used for communicating with the Pterodactyl Panel.

    Note that New sets up the initial state, but you may still need to call CreateEnvironment() to ensure the filesystem and necessary directories are prepared.

    // client is an implementation of remote.Client
    server, err := server.New(client)
    if err != nil {
    	return err
    }
  7. Prepare the server environment with CreateEnvironment()

    develop

    Before a server can run, you must call CreateEnvironment(). This method ensures the server's data directory exists and initializes the process environment.

    If MachineID.Enable is set in the global configuration, this method will also write a machine-id file (the server's UUID without dashes) to the configured machine-id directory. This is used for encrypting tokens.

    err := server.CreateEnvironment()
    if err != nil {
    	return err
    }
  8. Convert Server to APIResponse for Panel communication

    develop

    To provide the Pterodactyl Panel with the current status and resource usage of a server, use ToAPIResponse(). This converts the internal Server struct into an APIResponse object containing:

    • state: The current process state (e.g., running, offline).
    • is_suspended: Whether the server is suspended.
    • utilization: Current resource usage (CPU, Memory, etc.).
    • configuration: The server's configuration settings.
    response := server.ToAPIResponse()
    // response is an APIResponse struct used in JSON responses
  9. Manage the Server lifecycle with CleanupForDestroy()

    develop

    When a server is being removed or the application is shutting down, call CleanupForDestroy(). This method performs a comprehensive cleanup by:

    • Canceling the server's internal context (stopping background tasks like installations).
    • Destroying all registered events.
    • Destroying all active sinks.
    • Canceling all open Websocket connections.
    • Destroying the powerLock.
    server.CleanupForDestroy()
  10. Initialize and run the SFTP server

    develop

    The SFTPServer manages the lifecycle of the SFTP service, including host key generation, listening for inbound SSH connections, and authenticating users via the Wings API.

    To use it, initialize it with a *server.Manager using New(). Calling Run() will start a blocking loop that listens on the configured address and port. It automatically handles the generation of an ED25519 host key if one is not present at the path returned by PrivateKeyPath().

    // Assuming m is an existing *server.Manager
    sftpServer := sftp.New(m)
    if err := sftpServer.Run(); err != nil {
    	// Handle error
    }
  11. Sync server state from the Panel with Sync()

    develop

    The Sync() method ensures that the local Wings server instance is perfectly aligned with the state defined on the Pterodactyl Panel. This is critical for handling mass actions performed on the Panel that need to be reflected on the node.

    Sync() performs the following:

    1. Fetches the latest server configuration from the Panel via the remote.Client.
    2. Updates the local Configuration and ProcessConfiguration using SyncWithConfiguration().
    3. Updates the local filesystem disk limits based on the new configuration.
    4. Synchronizes the environment variables.
    5. If the server is currently suspended, it forces the disconnection of all active Websockets and SFTP clients.
    err := server.Sync()
    if err != nil {
    	// handle error
    }
  12. Get server environment variables with GetEnvironmentVariables()

    develop

    The GetEnvironmentVariables() method returns a slice of strings in KEY=VALUE format that should be assigned to the running server process.

    It automatically includes:

    • TZ: The system timezone.
    • STARTUP: The server's invocation command.
    • SERVER_MEMORY: The memory limit.
    • SERVER_IP: The default IP mapping.
    • SERVER_PORT: The default port mapping.
    • Any additional environment variables defined in the server's configuration (provided they don't conflict with the defaults above).