The architecture
Pterodactyl is made of two components: the panel (a PHP web application for managing game servers) and Wings (a Go daemon that runs the servers inside Docker containers). On a single VPS both coexist — plan for 4 GB of RAM for the panel, Wings and a first game server.
Prerequisites
An Ubuntu 24.04 VPS, two domain names (panel.example.com and node.example.com) pointing to the IP, and root access. The panel requires PHP 8.3, MariaDB, Redis and Composer — all available in Ubuntu's repositories.
Step 1 — Panel dependencies
apt update && apt install -y mariadb-server redis-server nginx composer \
php8.3-fpm php8.3-cli php8.3-common php8.3-mysql php8.3-zip \
php8.3-gd php8.3-mbstring php8.3-curl php8.3-xml php8.3-bcmath
systemctl enable --now mariadb redis-server php8.3-fpmStep 2 — Database
mariadbCREATE DATABASE panel;
CREATE USER 'pterodactyl'@'127.0.0.1' IDENTIFIED BY 'AVeryStrongPassword!';
GRANT ALL PRIVILEGES ON panel.* TO 'pterodactyl'@'127.0.0.1' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;Step 3 — Download the panel
mkdir -p /var/www/pterodactyl && cd /var/www/pterodactyl
curl -Lo panel.tar.gz https://github.com/pterodactyl/panel/releases/latest/download/panel.tar.gz
tar -xzf panel.tar.gz
chmod -R 755 storage/* bootstrap/cache/
cp .env.example .env
composer install --no-dev --optimize-autoloader
php artisan key:generate --forceStep 4 — Configure and initialize
php artisan p:environment:setup
php artisan p:environment:database
php artisan migrate --seed --force
php artisan p:user:makeThe first command asks for the panel URL (https://panel.example.com), timezone and cache driver (redis). The second configures MariaDB. The last one creates the administrator account — answer yes to "Is this user an administrator".
Step 5 — Cron and queue worker
Schedule the Laravel scheduler:
crontab -u www-data -e* * * * * php /var/www/pterodactyl/artisan schedule:run >> /dev/null 2>&1Create the worker /etc/systemd/system/pteroq.service:
[Unit]
Description=Pterodactyl Queue Worker
After=redis-server.service
[Service]
User=www-data
Group=www-data
Restart=always
ExecStart=/usr/bin/php /var/www/pterodactyl/artisan queue:work --queue=high,standard,low --sleep=3 --tries=3
[Install]
WantedBy=multi-user.targetchown -R www-data:www-data /var/www/pterodactyl
systemctl daemon-reload
systemctl enable --now pteroqStep 6 — Nginx and HTTPS
Create /etc/nginx/sites-available/pterodactyl.conf:
server {
listen 80;
server_name panel.example.com;
root /var/www/pterodactyl/public;
index index.php;
client_max_body_size 100M;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}ln -s /etc/nginx/sites-available/pterodactyl.conf /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
apt install -y certbot python3-certbot-nginx
certbot --nginx -d panel.example.comStep 7 — Install Wings
Wings runs game servers inside Docker — install the engine first (see our guide "Install Docker on Ubuntu 24.04"), then the daemon:
mkdir -p /etc/pterodactyl
curl -L -o /usr/local/bin/wings https://github.com/pterodactyl/wings/releases/latest/download/wings_linux_amd64
chmod u+x /usr/local/bin/wingsIn the panel: Administration → Nodes → Create New. Fill in the FQDN node.example.com, the allocatable RAM and disk. Then open the node's Configuration tab and click Generate Token: the panel shows a complete wings configure command — copy it and run it on the VPS:
cd /etc/pterodactyl
wings configure --panel-url https://panel.example.com --token <generated-token> --node <node-id>Create the service /etc/systemd/system/wings.service:
[Unit]
Description=Pterodactyl Wings Daemon
After=docker.service
Requires=docker.service
[Service]
User=root
WorkingDirectory=/etc/pterodactyl
LimitNOFILE=4096
ExecStart=/usr/local/bin/wings
Restart=on-failure
StartLimitInterval=600
[Install]
WantedBy=multi-user.targetsystemctl daemon-reload
systemctl enable --now wingsStep 8 — Port allocations and firewall
In the node's Allocations tab, create an allocation on the public IP with a port range (e.g. 25565-25575 for Minecraft, 27015-27020 for Source-engine games). Each game server consumes one port. If UFW is active:
ufw allow 8080/tcp
ufw allow 2022/tcp
ufw allow 25565:25575/tcp
ufw allow 25565:25575/udpPort 8080 serves the Wings API (the panel connects to it), 2022 the built-in SFTP. Reminder: Docker inserts its own iptables rules — game ports published by Wings get through anyway; UFW mostly protects the rest of the server.
Verification
- The node shows a green heart in the panel (it reaches the Wings API).
- Create a server (the "Minecraft Paper" egg for instance): the install runs in Wings,
docker psshows the container, the web console responds. wings diagnosticsvalidates the network and Docker configuration.
Troubleshooting
- Red heart: Wings can't reach the panel — check the FQDN, the certificate, and re-run
wings configure. - Servers won't start:
journalctl -u wings -fand the install logs under/var/log/pterodactyl/install/. - Docker error when Wings starts:
systemctl status docker— Wings runs as root but requires a live Docker daemon. - Emails not sent: configure SMTP under Administration → Settings → Mail, then
php artisan queue:restarton the worker.