
Pterodactyl's guides switch between two names, the Panel and Wings, each with its own list: PHP, MariaDB and Redis for one, Docker, a node domain and ports 8080 and 2022 for the other. Which machine needs what, is one VPS enough, and why does your browser have to reach the node? This guide answers all three, plus what to size, from the docs and the source of Panel 1.15.2 and Wings 1.13.4, the stable releases on 30 October 2026.
Quick answer: The Panel is a PHP web app with a MySQL or MariaDB database, Redis, a queue worker and a cron job. It stores users, servers, nodes and schedules, and runs no game servers. Wings is a Go daemon on every node: it runs each game server in a Docker container, keeps the server files, and listens on 8080 for its API and 2022 for SFTP. Your browser talks to the Panel for pages and straight to Wings for the console, uploads and downloads, so each node needs its own DNS name and, behind an HTTPS panel, its own certificate. One VPS can run both for a few servers; separate machines keep game load off the panel and let you add nodes.
The Two Halves at a Glance
| Panel | Wings | |
|---|---|---|
| What it is | A PHP (Laravel) web app in /var/www/pterodactyl | One Go binary, /usr/local/bin/wings |
| Runs as | www-data, behind a web server such as Nginx, with PHP-FPM | root, as wings.service, which requires Docker |
| Also needs | PHP 8.2 or 8.3, MySQL 5.7.22 or newer or MariaDB 10.2 or newer, Redis, pteroq.service, a cron line | Docker on Linux |
| Stores | Users, servers, nodes, allocations, eggs, schedules | Server files in /var/lib/pterodactyl/volumes/<uuid>, local backups, config.yml |
| Listens on | 443, and 80 to redirect to HTTPS | 8080 (API), 2022 (SFTP), plus each server's ports through Docker |
| How many | One per installation | One per node |
On the panel server, Nginx redirects port 80 to 443 and passes PHP requests to PHP-FPM (webserver configuration). The database and Redis serve only the panel and stay on localhost: the MySQL guide creates the panel's user for 127.0.0.1, and Redis's default config binds to 127.0.0.1 -::1. The install guide adds pteroq.service, a queue worker for "sending emails and handling many other background tasks", and a root cron line that runs artisan schedule:run every minute for tasks "such as session cleanup and sending scheduled tasks to daemons". So server schedules live in the panel: it checks them every minute and its queue sends each power action or command to Wings (Kernel.php, RunTaskJob.php).
On a node, Wings runs one container per server, named after the server's UUID, with the server's folder mounted at /home/container (container.go, settings.go). Install scripts run in a separate <uuid>_installer container. SFTP is built into Wings, not the machine's SSH server, and the node form warns: "Do not use the same port that you have assigned for your physical server's SSH process." Backups stay on the node, in /var/lib/pterodactyl/backups (config.go), unless you set up S3: "By default, Pterodactyl Panel uses local storage via Wings for backups" (additional configuration). Our Pterodactyl backup guide covers what to save on both halves.
Who Connects to Whom
Not everything goes through the panel. A working setup makes these connections, on default ports:
| From | To | Port | Used for |
|---|---|---|---|
| Browser | Panel | 443 | Pages, the client API, file listings and edits |
| Browser | Wings | 8080 | Console and power buttons, uploads, downloads, the heartbeat on the admin Nodes page |
| Panel | Wings | 8080 | Creating and deleting servers, file actions, backups, scheduled tasks |
| Wings | Panel | 443 | Server list at startup, install scripts, SFTP logins, install and backup results, activity logs |
| SFTP client | Wings | 2022 | File transfers |
| Players | Game server | Allocation ports, TCP and UDP | The game |
| Old node | New node | 8080 | Server transfers |
For the console, the panel only hands out a token: its websocket controller returns a wss:// address on the node's FQDN and daemon port with a token valid for 10 minutes, and the power buttons use that socket. Uploads and downloads get signed links to /upload/file and /download/file on the node, valid for 15 minutes (FileUploadController.php, FileController.php). The panel calls Wings with the node's secret token (DaemonRepository.php), and Wings calls the panel's /api/remote routes (api-remote.php) at the address saved as remote in its config.yml. That includes every SFTP login: Wings forwards the username and the password or key, and waits for the panel's verdict (sftp/server.go).
Game traffic touches neither service. Wings publishes every allocation port for TCP and UDP on the allocation's IP (allocations.go), and Docker forwards it into the container ahead of UFW: such packets "are routed before the firewall rules can be applied" (Docker firewall docs). Our Docker and UFW guide covers what that means for your rules.
DNS Names and Ports Each Needs
The panel needs one name, such as panel.example.com. Open 443 to its users and to every node, and 80 for the redirect and for Let's Encrypt's HTTP challenge, which "requires you to expose port 80" (SSL guide). Keep 3306 and 6379 closed to the internet. A new panel domain means editing remote in every node's config.yml by hand, because the panel cannot push that key (Node.php, router_system.go); our node offline guide shows how.
Each node needs its own name, such as node1.example.com, entered as its FQDN. The node form accepts an IP address "only if you are not using SSL for this node", and behind an HTTPS panel it disables HTTP: "In order for browsers to connect to your node it must use a SSL connection." Wings expects the certificate in /etc/letsencrypt/live/<fqdn>/. Open 8080 and 2022 to all your users, not only to the panel server, because browsers and SFTP clients connect directly. Keep the record DNS only in Cloudflare (see the FAQ).
Players connect to the allocation's IP and port on the node. The Wings install guide says to use your network interface's IP: "Do not use 127.0.0.1 for allocations." So a hostname for players, such as play.example.com, points at the node, not at the panel.
If you add a database host, open its port 3306 to the panel and the nodes: per the MySQL guide, the panel creates per-server databases on it, and game servers connect to them.
See What Runs Where
On the panel server:
systemctl list-units --type=service --state=running | grep -E 'nginx|php|mariadb|mysql|redis|pteroq'
sudo crontab -l | grep schedule:run
sudo ss -ltnp
With the defaults, ss shows Nginx on 80 and 443, and the database and Redis on localhost only. On a node:
systemctl status wings docker --no-pager
sudo ss -ltnp | grep wings
sudo docker ps --format 'table {{.Names}}\t{{.Ports}}'
Wings listens on 0.0.0.0:8080 and 0.0.0.0:2022 by default. Each container name is a server's UUID, and the Ports column lists its allocations. Then test both directions:
curl -i https://node1.example.com:8080/api/system # on the panel server
curl -sS -o /dev/null -w '%{http_code}\n' https://panel.example.com # on the node
The first should return 401 with The required authorization heads were not present in the request. (the typo is Wings' own, in middleware.go), which proves the connection and the certificate work. The second should print an HTTP status code; a curl error instead means the node cannot reach the panel.
When One Half Goes Down
- Panel offline. Running game servers keep running and players keep connecting. The 2.0 upgrade guide says: "Game servers keep running; only the Panel goes offline." The console, file manager, SFTP logins and schedules stop, and Wings cannot start: it fetches its server list from the panel first and otherwise exits with
failed to load server configurations(root.go, manager.go). - Wings stopped. The containers keep running. Wings' source says "We never want to stop an instance that is currently running external from Wings", and on the next start it logs
detected server is running, re-attaching to process.... The upgrade guide says the same about a restart: "Your running servers will not be affected." Until Wings is back, that node has no console, file manager or SFTP. - Node machine down. Its game servers are down; the panel and other nodes carry on.
One VPS or Separate Machines
| One VPS for both | Panel and nodes apart | |
|---|---|---|
| DNS names | Panel and node name on one IP | One name per machine |
| RAM and CPU | The panel stack and game servers share them | The panel has its own; nodes are sized for games |
| Reboots and outages | Panel and games go down together | Only that machine is affected |
| Growth | Add a node later and move servers to it | Add nodes as you need them |
On one VPS, three things need care.
A certificate per name. The panel's Nginx config reads /etc/letsencrypt/live/<domain>/ and Wings reads /etc/letsencrypt/live/<node FQDN>/. Nginx already holds port 80, and the SSL guide keeps standalone mode for "Wings-only machines that don't need a web server", so issue the node's certificate through the Nginx plugin:
sudo apt install -y python3-certbot-nginx
sudo certbot certonly --nginx -d node1.example.com
Restart Wings after each renewal; the node offline guide has a deploy hook for that.
Room for the panel. Set the node's Total Memory to what game servers may use after the OS and the panel stack. The node docs warn: "Don't forget to account for OS overhead and other software requirements on machines."
Reaching itself. If the two cannot reach each other's public names, the troubleshooting page suggests /etc/hosts entries that point the names back at the server.
Splitting later is built in. A server's admin Manage tab has Transfer Server, which "requires more than one node to be configured on your panel" (manage.blade.php). The old node's Wings then uploads the server straight to the new node's Wings port (DaemonTransferRepository.php), so nodes must reach each other on 8080. A Space-Node VPS is KVM with full root access, the virtualization the Wings install guide calls "guaranteed to work", so either layout runs on it.
What to Size for Each
The panel. Pterodactyl's install page lists software but gives no RAM or CPU figure. The panel's load follows people and API calls, not players: page views, schedules every minute, SFTP logins, activity that Wings sends every 60 seconds, and each node's server list when Wings starts. Wings fetches that list 50 servers at a time, and its config.go warns that bigger pages "will likely encounter memory limits on your Panel instance". To list the processes using the most memory, in KiB:
ps -eo rss,comm --sort=-rss | head -n 12
A node. Start from the sum of what you assign your servers, then add what Wings adds (config_docker.go, settings.go):
- Memory. Each container's hard limit is 15% above its assigned memory up to 2,048 MiB, 10% up to 4,096 MiB and 5% above that, so a 4,096 MiB server may use about 4,506 MiB. Each container also gets a 100 MB
/tmpin host memory that Wings does "not keep track of", and an install container may use 1,024 MiB, or the server's limit if that is higher (Wings configuration). - The panel's check adds up only assigned memory against Total Memory plus over-allocation (Node.php). The node docs give the example: "if you have set a 10GB memory limit, with a 20% overallocation, the Panel will allocate up to 12GB". Leave the overhead outside Total Memory.
- CPU limits count 100 per thread: "A value of 200% represents complete utilization of two cores." 0 means no limit.
- Disk holds the server folders, local backups, install logs in
/var/log/pterodactyland Docker's images: in/var/lib/containerdon a fresh install of Docker Engine 29 or later, in/var/lib/dockeron an upgraded one (Docker daemon docs).
sudo docker stats --no-stream --format 'table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}'
sudo du -sh /var/lib/pterodactyl/volumes /var/lib/pterodactyl/backups /var/lib/docker /var/lib/containerd
docker stats shows each container's usage next to what it may use, which is the limit with the Wings overhead included.
Which One Fits
- One VPS fits testing and a handful of servers for your own community, if you accept that a reboot or a busy server affects the panel too.
- A separate panel with one or more nodes fits hosting for other people, nodes in more than one place, and growing game capacity without touching the panel. Our reseller setup guide covers eggs and billing.
- Neither fits if you want a game server rather than two services to maintain. Space-Node's Minecraft hosting uses the Pterodactyl panel, so you get its console and file manager without running Panel or Wings yourself.
FAQ
Can Wings run without the Panel? No. Wings has no web interface, needs the panel's server list to start and asks the panel to check each SFTP login. Servers that are already running keep running while the panel is down.
Can one panel manage nodes at different providers? Yes. The panel and each node must reach each other over HTTPS, and your users must reach every node's daemon and SFTP ports. The node docs say locations "simply act as categories for nodes and serve no other purpose at this time."
Can I put a node behind Cloudflare's proxy? You can, but it gains little. The Wings configuration page says proxying Wings "isn't beneficial since users will be connecting to the machine directly", the daemon port must move to a Cloudflare HTTPS port such as 8443, and SFTP cannot be proxied without Cloudflare's enterprise plan. Our node offline guide covers that setup.
Does Pelican or Pterodactyl 2.0 change this split?
No. Pelican pairs its panel with its own Wings, configured in /etc/pelican/config.yml, with the same rule: "If your Panel is using SSL, then Wings must also use SSL" (Pelican docs). Pterodactyl's 2.0 upgrade guide says "Wings 1.13.2 and 1.13.3 work with the 2.0 Panel", and the 2.0 beta release notes say to keep production panels on 1.x for now. See our Pterodactyl vs Pelican comparison.
Sources
All opened on 30 October 2026:
- Pterodactyl docs: Panel getting started, Webserver configuration, Additional configuration, Troubleshooting, Installing Wings, Wings configuration, Upgrading Wings, Creating a node, SSL certificates, Setting up MySQL, Upgrading from 1.x to 2.0
- Pterodactyl releases: Panel, Wings
- Panel 1.15.2 source: Node.php, node form, Nodes list, api-remote.php, RouteServiceProvider.php, DaemonRepository.php, WebsocketController.php, FileUploadController.php, FileController.php, PowerButtons.tsx, Kernel.php, RunTaskJob.php, backups.php, server Manage tab, DaemonTransferRepository.php
- Wings 1.13.4 source: config.go, config_docker.go, settings.go, allocations.go, container.go, install.go, root.go, manager.go, router.go, router_system.go, middleware.go, remote/http.go, remote/servers.go, sftp/server.go, backup.go, router_server_transfer.go, transfer/source.go
- Pelican: Installing Wings
- Docker: Packet filtering and firewalls, docker ps, docker stats, Docker daemon
- Redis: redis.conf (7.0)
- Certbot: user guide, nginx HTTP-01 source
- Man pages: ss(8), ps(1), du(1), systemctl(1), crontab(1), curl