package config import ( "encoding/base64" "sort" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/registry" "github.com/goccy/go-json" ) type dockerNetworkInterfaces struct { V4 struct { Subnet string `default:"172.18.0.0/16"` Gateway string `default:"172.18.0.1"` } V6 struct { Subnet string `default:"fdba:17c8:6c94::/64"` Gateway string `default:"fdba:17c8:6c94::1011"` } } type DockerNetworkConfiguration struct { // The interface that should be used to create the network. Must not conflict // with any other interfaces in use by Docker or on the system. Interface string `default:"172.18.0.1" json:"interface" yaml:"interface"` // The DNS settings for containers. Dns []string `default:"[\"1.1.1.1\", \"1.0.0.1\"]"` // The name of the network to use. If this network already exists it will not // be created. If it is not found, a new network will be created using the interface // defined. Name string `default:"pterodactyl_nw"` ISPN bool `default:"false" yaml:"ispn"` Driver string `default:"bridge"` Mode string `default:"pterodactyl_nw" yaml:"network_mode"` IsInternal bool `default:"false" yaml:"is_internal"` EnableICC bool `default:"true" yaml:"enable_icc"` NetworkMTU int64 `default:"1500" yaml:"network_mtu"` Interfaces dockerNetworkInterfaces `yaml:"interfaces"` } // DockerConfiguration defines the docker configuration used by the daemon when // interacting with containers and networks on the system. type DockerConfiguration struct { // Network configuration that should be used when creating a new network // for containers run through the daemon. Network DockerNetworkConfiguration `json:"network" yaml:"network"` // Domainname is the Docker domainname for all containers. Domainname string `default:"" json:"domainname" yaml:"domainname"` // Registries . Registries map[string]RegistryConfiguration `json:"registries" yaml:"registries"` // TmpfsSize specifies the size for the /tmp directory mounted into containers. Please be // aware that Docker utilizes the host's system memory for this value, and that we do not // keep track of the space used there, so avoid allocating too much to a server. TmpfsSize uint `default:"100" json:"tmpfs_size" yaml:"tmpfs_size"` // ContainerPidLimit sets the total number of processes that can be active in a container // at any given moment. This is a security concern in shared-hosting environments where a // malicious process could create enough processes to cause the host node to run out of // available pids and crash. ContainerPidLimit int64 `default:"512" json:"container_pid_limit" yaml:"container_pid_limit"` // InstallerLimits defines the limits on the installer containers that prevents a server's // installation process from unintentionally consuming more resources than expected. This // is used in conjunction with the server's defined limits. Whichever value is higher will // take precedence in the installer containers. InstallerLimits struct { Memory int64 `default:"1024" json:"memory" yaml:"memory"` Cpu int64 `default:"100" json:"cpu" yaml:"cpu"` } `json:"installer_limits" yaml:"installer_limits"` // Overhead controls the memory overhead given to all containers to circumvent certain // software such as the JVM not staying below the maximum memory limit. Overhead Overhead `json:"overhead" yaml:"overhead"` UsePerformantInspect bool `default:"true" json:"use_performant_inspect" yaml:"use_performant_inspect"` // Sets the user namespace mode for the container when user namespace remapping option is // enabled. // // If the value is blank, the daemon's user namespace remapping configuration is used, // if the value is "host", then the pterodactyl containers are started with user namespace // remapping disabled UsernsMode string `default:"" json:"userns_mode" yaml:"userns_mode"` LogConfig struct { Type string `default:"local" json:"type" yaml:"type"` Config map[string]string `default:"{\"max-size\":\"5m\",\"max-file\":\"1\",\"compress\":\"false\",\"mode\":\"non-blocking\"}" json:"config" yaml:"config"` } `json:"log_config" yaml:"log_config"` } func (c DockerConfiguration) ContainerLogConfig() container.LogConfig { if c.LogConfig.Type == "" { return container.LogConfig{} } return container.LogConfig{ Type: c.LogConfig.Type, Config: c.LogConfig.Config, } } // RegistryConfiguration defines the authentication credentials for a given // Docker registry. type RegistryConfiguration struct { Username string `yaml:"username"` Password string `yaml:"password"` } // Base64 returns the authentication for a given registry as a base64 encoded // string value. func (c RegistryConfiguration) Base64() (string, error) { b, err := json.Marshal(registry.AuthConfig{ Username: c.Username, Password: c.Password, }) if err != nil { return "", err } return base64.URLEncoding.EncodeToString(b), nil } // Overhead controls the memory overhead given to all containers to circumvent certain // software such as the JVM not staying below the maximum memory limit. type Overhead struct { // Override controls if the overhead limits should be overridden by the values in the config file. Override bool `default:"false" json:"override" yaml:"override"` // DefaultMultiplier sets the default multiplier for if no Multipliers are able to be applied. DefaultMultiplier float64 `default:"1.05" json:"default_multiplier" yaml:"default_multiplier"` // Multipliers allows overriding DefaultMultiplier depending on the amount of memory // configured for a server. // // Default values (used if Override is `false`) // - Less than 2048 MB of memory, multiplier of 1.15 (15%) // - Less than 4096 MB of memory, multiplier of 1.10 (10%) // - Otherwise, multiplier of 1.05 (5%) - specified in DefaultMultiplier // // If the defaults were specified in the config they would look like: // ```yaml // multipliers: // 2048: 1.15 // 4096: 1.10 // ``` Multipliers map[int]float64 `json:"multipliers" yaml:"multipliers"` } func (o Overhead) GetMultiplier(memoryLimit int64) float64 { // Default multiplier values. if !o.Override { if memoryLimit <= 2048 { return 1.15 } else if memoryLimit <= 4096 { return 1.10 } return 1.05 } // This plucks the keys of the Multipliers map, so they can be sorted from // smallest to largest in order to correctly apply the proper multiplier. i := 0 multipliers := make([]int, len(o.Multipliers)) for k := range o.Multipliers { multipliers[i] = k i++ } sort.Ints(multipliers) // Loop through the memory values in order (smallest to largest) for _, m := range multipliers { // If the server's memory limit exceeds the modifier's limit, don't apply it. if memoryLimit > int64(m) { continue } return o.Multipliers[m] } return o.DefaultMultiplier }