Additional Configuration
These are advanced configurations for Wings. You risk breaking Wings and making containers unusable if you misconfigure something. Proceed only if you know what each configuration value does.
You must apply all changes to your Wings config.yml file located at /etc/pelican and restart wings.
Verify your config file using Yaml Lint should you receive errors related to YAML parsing.
Managed by the Panel
Some values are managed by the Panel and appear in the Configuration File tab of the Node.
Most of them are sent to Wings whenever you save a Node, so if you change one of those by hand in config.yml, the Panel overwrites it on the next save. Set them in the Panel instead.
The values marked ✗ in the Sent on save column are the exception. Wings doesn't accept them from Panel updates or from the auto deploy command, so changing them in the Panel doesn't change them on the node. Update them in config.yml by hand, and keep the Panel setting in sync so the two agree.
| Setting Key | Where to set it in the Panel | Sent on save |
|---|---|---|
uuid, token_id, token | Generated by the Panel (Configuration File tab) | ✓ |
api.port | Basic Settings → Port / Listen Port | ✓ |
api.ssl.enabled | Basic Settings → SSL | ✓ |
api.ssl.cert, api.ssl.key | Extra Configuration → SSL Certificate (defaults to the Let's Encrypt paths for the node FQDN) | ✓ |
api.upload_limit | Advanced Settings → Upload Limit | ✓ |
system.sftp.bind_port | Advanced Settings → SFTP Port | ✓ |
system.data | Advanced Settings → Daemon Base Directory | ✗ |
allowed_mounts | Mounts (see the note below) | ✗ |
remote | The Panel URL (APP_URL). The auto deploy command sets it with --panel-url | ✗ |
The collapsed Extra Configuration section at the bottom of the Advanced Settings tab on the Edit Node page can also set the options marked with ✓ in the Panel column of the tables below.
A field left empty in the Panel is not sent, and Wings keeps its own value. Clearing a field in the Panel does not reset a value Wings already applied. To reset it, edit config.yml by hand.
Options marked with ✗ can only be changed by editing config.yml on the node.
Wings doesn't accept allowed_mounts from the Panel's config updates, so extra mount paths must be added to config.yml by hand. The list in the Configuration File tab only includes the Mounts assigned to the node.
Custom SSL certificate paths are applied when you save the Node. Wings ignores Let's Encrypt paths sent by the Panel and keeps the paths it already has, so clearing a custom path in the Panel won't switch Wings back. Edit api.ssl.cert and api.ssl.key in config.yml to do that.
Wings applies Panel updates by merging them into its current configuration. Options that Wings reads under a different name from the Panel's JSON payload can't be set from the Panel, which is why some options are config.yml only.
If you want Wings to ignore everything the Panel sends, set ignore_panel_config_updates: true.
Private Registries
You can use these settings to authenticate against (private) docker registries when pulling images.
Available Keys
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| name | null | ✗ | Registry address |
| username | null | ✗ | Registry username |
| password | null | ✗ | Registry password |
Example of usage
docker:
registries:
registry.example.com:
username: "registryusername"
password: "registrypassword"
Custom Network Interfaces
You can change the network interface that Wings uses for all containers by editing the network name; it is by default set to pelican_nw. For example, to enable Docker host mode change the network name to host.
Changing network mode to host grants Pelican direct access to all machine interfaces and Panel users can bind to any IP or Port even if it's not allocated to their container. You will lose all benefits of Docker network isolation. It is not recommended for public installations that are hosting other users' servers.
Example of usage
docker:
network:
name: host
network_mode: host
After making changes, the following commands will stop the Wings, remove the Pelican network, and start the Wings again. Run at your own risk.
systemctl stop wings && docker network rm pelican_nw && systemctl start wings
All Docker Network Keys
All of these keys live under docker.network.
Containers use network_mode, which can only be set in config.yml. If you change name (in the Panel or in config.yml), set network_mode to the same value, then remove the old network and restart Wings as shown above. Otherwise containers keep using the old network mode.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| name | pelican_nw | ✓ | Name of the Docker network. It is created if it doesn't exist |
| network_mode | pelican_nw | ✗ | Docker network mode for containers, e.g. host |
| driver | bridge | ✓ | Docker network driver |
| interface | 172.18.0.1 | ✓ | Interface used to create the network. Must not conflict with other Docker networks |
| dns | 1.1.1.1, 1.0.0.1 | ✓ | DNS servers used by containers |
| ispn | false | ✓ | Use the ISPN network option |
| IPv6 | true | ✓ | Enable IPv6 on the network |
| is_internal | false | ✗ | Create the network as internal, with no outbound access |
| enable_icc | true | ✗ | Allow inter-container communication on the network |
| network_mtu | 1500 | ✗ | MTU of the network |
| interfaces.v4.subnet | 172.18.0.0/16 | ✓ | IPv4 subnet of the network |
| interfaces.v4.gateway | 172.18.0.1 | ✓ | IPv4 gateway of the network |
| interfaces.v6.subnet | fdba:17c8:6c94::/64 | ✓ | IPv6 subnet of the network |
| interfaces.v6.gateway | fdba:17c8:6c94::1011 | ✓ | IPv6 gateway of the network |
docker:
network:
interface: 172.18.0.1
dns:
- 1.1.1.1
- 1.0.0.1
name: pelican_nw
ispn: false
IPv6: true
driver: bridge
network_mode: pelican_nw
is_internal: false
enable_icc: true
network_mtu: 1500
interfaces:
v4:
subnet: 172.18.0.0/16
gateway: 172.18.0.1
v6:
subnet: fdba:17c8:6c94::/64
gateway: fdba:17c8:6c94::1011
Enabling Cloudflare proxy
Cloudflare proxying of the Wings isn't beneficial since users will be connecting to the machine directly and bypassing any Cloudflare protection. As such, your Node machine IP will still be exposed.
To enable Cloudflare proxy, you must change the Wings port to one of the Cloudflare HTTPS ports with caching enabled (more info here), such as 8443, because Cloudflare only supports HTTP on port 8080. Select your Node in the Admin Panel, and on the settings tab, change the port. Make sure that you set "Not Behind Proxy" when using Full SSL settings in Cloudflare. Then on Cloudflare dashboard, your FQDN must have an orange cloud enabled beside it.
You are unable to proxy the SFTP port through Cloudflare unless you have their enterprise plan. Server transfers will most likely not work either due to Cloudflare's request body limits.
Container PID Limit
You can change the total number of processes that can be active in a container at any given moment by changing the container_pid_limit value. The default value is 512, and it can also be set in the Panel.
You can set it to 0 to disable the limit completely. However, this is not recommended as the limit prevents malicious overloading of the node.
Restart wings and your game server to apply the new limit.
Example of usage
docker:
...
container_pid_limit: 512
...
Other Docker Settings
All of these keys live under docker.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| domainname | empty | ✓ | Docker domain name for all containers |
| tmpfs_size | 100 | ✓ | Size of the /tmp directory in MiB mounted into containers. Docker uses host memory for this, and it isn't counted against the server |
| userns_mode | empty | ✓ | User namespace mode for containers when Docker user namespace remapping is enabled. Set to host to disable remapping for Pelican containers |
| system_ips | [] | ✓ | IP addresses that users are allowed to bind to |
| use_performant_inspect | true | ✓ | Use a faster container inspect call |
| overhead.override | false | ✓ | Use the values below instead of the built-in memory overhead tiers |
| overhead.default_multiplier | 1.05 | ✓ | Memory multiplier given to containers when overriding, so software such as the JVM stays below its limit |
| overhead.multipliers | empty | ✗ | Map of memory size (MiB) to multiplier, used instead of default_multiplier for servers at or below that size |
| log_config.type | local | ✓ | Docker log driver for containers |
| log_config.config | see below | ✗ | Options passed to the log driver |
When overhead.override is false, Wings gives servers with 2048 MiB of memory or less 15% extra, servers with 4096 MiB or less 10% extra, and all other servers 5% extra.
docker:
domainname: ""
tmpfs_size: 100
userns_mode: ""
system_ips: []
use_performant_inspect: true
overhead:
override: false
default_multiplier: 1.05
multipliers:
2048: 1.15
4096: 1.10
log_config:
type: local
config:
compress: "false"
max-file: "1"
max-size: 5m
mode: non-blocking
Throttles Limits
You can use these settings to adjust or completely disable console throttling.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| enabled | true | ✓ | Whether or not the throttler is enabled |
| lines | 2000 | ✓ | Total lines that can be output in a given line_reset_interval period |
| line_reset_interval | 100 | ✓ | The amount of time in milliseconds after which the number of lines processed is reset to 0 |
Example of usage
throttles:
enabled: true
lines: 2000
line_reset_interval: 100
Backups Limits
These keys live under system.backups.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| write_limit | 0 | ✗ | Impose I/O write limit for backups to the disk, 0 = unlimited. Value greater than 0 throttles write speed to the set value in MiB/s |
| compression_level | best_speed | ✗ | none for no compression, best_speed for gzip level 1, or best_compression for gzip level 9 |
| restore_host_allowlist | [] | ✗ | Hostnames, IP addresses or CIDR ranges that backup restores may download from even though they are private or internal |
| remove_backups_on_server_delete | true | ✗ | Delete a server's local backups when the server is deleted |
Example of usage
system:
backups:
write_limit: 0
compression_level: best_speed
restore_host_allowlist: []
remove_backups_on_server_delete: true
Transfers Limits
These keys live under system.transfers.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| download_limit | 0 | ✗ | Impose a Network I/O read limit for archives, 0 = unlimited. Value greater than 0 throttles read speed to the set value in MiB/s |
| storage_pool.enabled | false | ✗ | Signals that this node shares a common data volume with other nodes |
| storage_pool.pool_name | empty | ✗ | Identifier used to check whether two nodes are in the same shared storage pool |
Example of usage
system:
transfers:
download_limit: 0
storage_pool:
enabled: false
pool_name: ""
Installer Limits
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 install containers.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| memory | 1024 | ✓ | The maximum amount of memory install container can use unless server memory limit is higher than this value |
| cpu | 100 | ✓ | The maximum amount of cpu install container can use unless server cpu limit is higher than this value |
Example of usage
docker:
installer_limits:
memory: 1024
cpu: 100
Crash Detection
These keys live under system.crash_detection, except crash_detection_activity_lines, which lives directly under system.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| enabled | true | ✗ | Enable crash detection for all servers on this node |
| detect_clean_exit_as_crash | true | ✗ | Mark server as crashed if it's stopped without user interaction, e.g., not pressing stop button |
| timeout | 60 | ✗ | Seconds between crashes that won't cause the server to be restarted again. Prevents boot loops |
| crash_detection_activity_lines | 2 | ✗ | Number of console lines added to the activity log when a server crashes |
Example of usage
system:
crash_detection:
enabled: true
detect_clean_exit_as_crash: true
timeout: 60
crash_detection_activity_lines: 2
SFTP
These keys live under system.sftp. bind_port is managed by the Panel.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| bind_address | 0.0.0.0 | ✓ | Address the SFTP server listens on |
| read_only | false | ✗ | Block all write actions over SFTP |
| key_only | false | ✗ | Only allow SSH key logins, so passwords can't be used |
Example of usage
system:
sftp:
bind_address: 0.0.0.0
bind_port: 2022
read_only: false
key_only: false
System Directories
These keys live under system. data is managed by the Panel.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| root_directory | /var/lib/pelican | ✗ | Root directory where all Pelican data is stored |
| log_directory | /var/log/pelican | ✗ | Directory for server installation logs and other Wings logs |
| archive_directory | /var/lib/pelican/archives | ✗ | Directory where server transfer archives are stored |
| backup_directory | /var/lib/pelican/backups | ✗ | Directory where local backups are stored |
| tmp_directory | /tmp/pelican | ✗ | Directory for temporary files during installs. Useful for docker-in-docker environments |
Example of usage
system:
root_directory: /var/lib/pelican
log_directory: /var/log/pelican
data: /var/lib/pelican/volumes
archive_directory: /var/lib/pelican/archives
backup_directory: /var/lib/pelican/backups
tmp_directory: /tmp/pelican
System User and Rootless Docker
These keys live under system.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| username | pelican | ✓ | System user that owns server files and is used inside containers |
| timezone | auto-detected | ✓ | Timezone passed into all containers. Wings detects it, falling back to UTC |
| user.uid / user.gid | set by Wings | ✗ | UID and GID of the system user. Wings fills these in when it boots |
| user.rootless.enabled | false | ✓ | Enable when Docker runs in rootless mode |
| user.rootless.container_uid | 0 | ✗ | UID of the user inside the container. Usually 0, so the container runs as the Wings user |
| user.rootless.container_gid | 0 | ✗ | GID of the user inside the container. Usually 0, so the container runs as the Wings user |
| user.passwd.enable | true | ✓ | Mount a generated passwd and group file into containers to fix missing user and group errors |
| user.passwd.directory | /etc/pelican | ✗ | Directory where the passwd and group files are generated |
| machine_id.enable | true | ✓ | Generate and mount a machine-id file into containers. Some games, such as Hytale, need it |
| machine_id.directory | /etc/pelican/machine-id | ✗ | Directory where the machine-id files are generated |
Example of usage
system:
username: pelican
timezone: UTC
user:
rootless:
enabled: false
container_uid: 0
container_gid: 0
passwd:
enable: true
directory: /etc/pelican
machine_id:
enable: true
directory: /etc/pelican/machine-id
Disk Usage and Quotas
These keys live under system.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| disk_check_interval | 150 | ✗ | Seconds before a server's disk usage is recalculated. Low values can cause heavy I/O and CPU load. 0 disables disk checking, so disk usage always shows 0 |
| quotas.enabled | false | ✓ | Enable quota management on the data directory. See Disk Quotas |
Example of usage
system:
disk_check_interval: 150
quotas:
enabled: false
Activity and Logging
These keys live under system. For container log settings, see log_config in Other Docker Settings.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| activity_send_interval | 60 | ✗ | Seconds between sending batches of server activity to the Panel |
| activity_send_count | 100 | ✗ | Number of activity events sent per batch |
| websocket_log_count | 150 | ✗ | Number of console lines sent when someone connects to a server's console |
| enable_log_rotate | true | ✗ | Write a logrotate configuration for Wings when it boots and none exists |
Example of usage
system:
activity_send_interval: 60
activity_send_count: 100
websocket_log_count: 150
enable_log_rotate: true
API
These keys live under api. host, port, ssl and upload_limit are managed by the Panel.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| disable_remote_download | false | ✗ | Disable downloading files from a URL into server directories |
| remote_download.max_redirects | 10 | ✓ | Maximum HTTP redirects followed during a remote download |
| trusted_proxies | [] | ✓ | IP addresses of proxies allowed to set the X-Forwarded-For header |
Example of usage
api:
disable_remote_download: false
remote_download:
max_redirects: 10
trusted_proxies:
- 10.0.0.1
Panel Connection
These keys live under remote_query.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| timeout | 30 | ✓ | Seconds Wings waits for a Panel API request before marking it failed |
| boot_servers_per_page | 50 | ✗ | Servers requested per page when Wings boots. Raising it isn't recommended, as it can hit memory limits on the Panel |
| custom_headers | empty | ✗ | Extra headers sent with every request to the Panel, e.g. to get past Cloudflare Access |
Example of usage
remote_query:
timeout: 30
boot_servers_per_page: 50
custom_headers:
CF-Access-Client-Id: "client-id"
CF-Access-Client-Secret: "client-secret"
CORS
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| allowed_origins | [] | ✓ | Extra request origins to allow. The Panel URL is always allowed |
| allow_cors_private_network | false | ✓ | Sends the Access-Control-Request-Private-Network header. Only needed when connecting to Wings over HTTP on an internal IP address. Most users should leave this off |
Example of usage
allowed_origins:
- https://panel.example.com
allow_cors_private_network: false
File Search
These keys live under Search. Note the capital S.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| blacklisted_dirs | node_modules, .git, .wine, appcache, depotcache, vendor | ✗ | Directory names skipped when searching files |
| max_recursion_depth | 8 | ✗ | Maximum directory depth searched |
Example of usage
Search:
blacklisted_dirs:
- node_modules
- .git
- .wine
- appcache
- depotcache
- vendor
max_recursion_depth: 8
Other values
More commonly discussed values.
| Setting Key | Default Value | Panel | Notes |
|---|---|---|---|
| debug | false | ✓ | Force Wings to run in debug mode |
| quiet | false | ✗ | Run Wings with minimal logging. Ignored in debug mode |
| app_name | pelican | ✓ | Application name used by Wings |
| system.check_permissions_on_boot | true | ✗ | Check all file permissions on each boot. Disable this when you have a very large amount of files and the server startup is hanging on checking permissions |
| system.openat_mode | auto | ✗ | Controls whether Wings uses the newer openat2 syscall for server file access. Leave on auto unless you are troubleshooting file access issues |
| BlockBaseDirMount | true | ✗ | Block mounts that target /home/container. Note the capitalization |
| ignore_panel_config_updates | false | ✗ | Ignore configuration updates sent by the Panel. Values set in the Panel then have no effect on this node |
Example of usage
debug: false
quiet: false
app_name: pelican
system:
check_permissions_on_boot: true
openat_mode: auto
BlockBaseDirMount: true
ignore_panel_config_updates: false
Running on Podman
Wings can use rootful Podman in place of Docker through Podman's Docker-compatible API. Wings runs as root, so it uses the system Podman socket. These steps assume a Fedora, RHEL, or Alma/Rocky Linux host with SELinux enforcing.
-
Install Podman's Docker compatibility package and enable the socket. This makes
/var/run/docker.sockpoint at Podman, so skip the Docker install step.sudo dnf install podman podman-docker policycoreutils-python-utilssudo systemctl enable --now podman.socket -
Install and configure Wings as described in Installing Wings, but in
wings.servicereplace the three lines that referencedocker.servicewith the following, otherwise systemd refuses to start it (Unit docker.service not found):/etc/systemd/system/wings.serviceAfter=podman.socketRequires=podman.socket -
Podman doesn't support Docker's
locallog driver, so server installs fail withinvalid log driver. Wings also mounts its temporary directory into install containers, and SELinux blocks containers from reading/tmp/pelican. In/etc/pelican/config.yml, change these two values:/etc/pelican/config.ymlsystem:tmp_directory: /var/lib/pelican/tmpdocker:log_config:type: k8s-file -
Allow containers to use the Wings data directories under SELinux, then restart Wings:
sudo mkdir -p /var/lib/pelican/tmpsudo semanage fcontext -a -t container_file_t "/var/lib/pelican(/.*)?"sudo restorecon -R /var/lib/pelicansudo systemctl daemon-reloadsudo systemctl restart wings
Keep the OOM killer enabled on every server. Podman uses cgroup v2, which can't disable it, so a server with the OOM killer disabled fails to install or start with cannot disable OOM killer with cgroupv2.