How to Install and Optimize Pterodactyl Panel on Your Dedicated Server

Running a game hosting company, an esports community, or simply hosting servers for friends requires robust management software. Pterodactyl Panel has become the absolute industry standard. It is a free, open-source game server management panel built with PHP, React, and Go, utilizing Docker to isolate every single game server instance for maximum security and performance.

However, installing Pterodactyl is not a one-click process. It requires configuring web servers, databases, caching mechanisms, and containerization daemons. Furthermore, running it on a bare-metal dedicated server gives you immense raw power, but to get the best out of your hardware, you need to optimize it.

In this comprehensive guide, we will walk you through a manual, production-ready installation of the latest Pterodactyl Panel (v1.12+) and its daemon (Wings) on a fresh Ubuntu 24.04 or Ubuntu 22.04 dedicated server here at FitServers. We will also include advanced optimization tweaks that standard guides leave out.

📋 Prerequisites

Before you SSH into your server, ensure you have the following ready:

  • A bare-metal dedicated server running a fresh installation of Ubuntu 24.04 LTS or 22.04 LTS.
  • Root access to your server.
  • A fully qualified domain name (FQDN). For this tutorial, we will assume you are using panel.yourdomain.com.
  • DNS 'A' records pointing panel.yourdomain.com to your dedicated server's public IPv4 address.

Step 1: Install Core Dependencies

First, log in to your server via SSH as the root user. Update your system packages to ensure everything is current:

Bash
apt update && apt upgrade -y

Next, we need to install essential software, including MariaDB (database), Redis (caching), Nginx (web server), and Composer (PHP dependency manager).

Pterodactyl v1.12+ requires PHP 8.3. Add the necessary repository and install the dependencies:

Bash
apt -y install software-properties-common curl apt-transport-https ca-certificates gnupg
LC_ALL=C.UTF-8 add-apt-repository -y ppa:ondrej/php
curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash

apt update
apt -y install php8.3 php8.3-{cli,gd,mysql,pdo,mbstring,tokenizer,bcmath,xml,fpm,curl,zip} mariadb-server nginx tar unzip git redis-server

Install Composer:

Bash
curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer

Step 2: Configure the Database

Secure your MariaDB installation and create a database and user for the Pterodactyl Panel.

Log into MariaDB:

Bash
mariadb -u root -p

(Press Enter when prompted for a password if this is a fresh install).

Run the following SQL commands to create the database (panel), user (pterodactyl), and grant permissions. Make sure to change YOUR_SECURE_PASSWORD to a strong password:

SQL
CREATE DATABASE panel;
CREATE USER 'pterodactyl'@'127.0.0.1' IDENTIFIED BY 'YOUR_SECURE_PASSWORD';
GRANT ALL PRIVILEGES ON panel.* TO 'pterodactyl'@'127.0.0.1' WITH GRANT OPTION;
FLUSH PRIVILEGES;
exit;

Step 3: Download and Install the Panel

Create the directory for the panel and download the latest release files.

Bash
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 -xzvf panel.tar.gz
chmod -R 755 storage/* bootstrap/cache/

Set up the environment file and install the PHP dependencies:

Bash
cp .env.example .env
composer install --no-dev --optimize-autoloader
php artisan key:generate --force

Step 4: Environment Configuration

Now, we will configure the panel's environment variables (Database credentials, Redis, Mail). Run the interactive setup command:

Bash
php artisan p:environment:setup
  • Author Email: Enter your admin email.
  • Panel URL: https://panel.yourdomain.com
  • Timezone: e.g., Europe/Amsterdam or America/New_York
  • Cache/Session/Queue Driver: Select Redis for all three.

Configure the database connection:

Bash
php artisan p:environment:database

Enter the database details you created in Step 2 (Host: 127.0.0.1, Port: 3306, Database: panel, User: pterodactyl, Password: YOUR_SECURE_PASSWORD).

Set up database schemas and create your first Admin user:

Bash
php artisan migrate --seed --force
php artisan p:user:make

Follow the prompts to set your admin username, email, and password.

Step 5: File Permissions, Cron, and Workers

To ensure the panel runs smoothly, we must give Nginx ownership of the files:

Bash
chown -R www-data:www-data /var/www/pterodactyl/*

Pterodactyl requires a cronjob to run scheduled tasks every minute:

Bash
crontab -e

Add the following line to the bottom of the file:

Plaintext
* * * * * php /var/www/pterodactyl/artisan schedule:run >> /dev/null 2>&1

Next, create a Systemd service for the queue worker to process background tasks.

Bash
nano /etc/systemd/system/pteroq.service

Paste the following:

INI
[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
StartLimitInterval=180
StartLimitBurst=30
RestartSec=5s

[Install]
WantedBy=multi-user.target

Enable and start the worker and Redis:

Bash
systemctl enable --now pteroq.service
systemctl enable --now redis-server

Step 6: Web Server Configuration (Nginx & SSL)

Delete the default Nginx config and create one for Pterodactyl:

Bash
rm /etc/nginx/sites-enabled/default
nano /etc/nginx/sites-available/pterodactyl.conf

We will grab the official configuration layout. Be sure to replace <domain> with your actual domain (panel.yourdomain.com) and ensure the PHP version matches (php8.3-fpm):

Nginx
server {
    listen 80;
    server_name <domain>;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name <domain>;

    root /var/www/pterodactyl/public;
    index index.html index.htm index.php;
    charset utf-8;

    # SSL Certs (We will generate these with Certbot shortly)
    ssl_certificate /etc/letsencrypt/live/<domain>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<domain>/privkey.pem;
    ssl_session_cache shared:SSL:10m;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384";
    ssl_prefer_server_ciphers on;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param PHP_VALUE "upload_max_filesize = 100M \n post_max_size=100M";
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTP_PROXY "";
        fastcgi_intercept_errors off;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
    }

    location ~ /\.ht {
        deny all;
    }
}

Enable the configuration:

Bash
ln -s /etc/nginx/sites-available/pterodactyl.conf /etc/nginx/sites-enabled/pterodactyl.conf

Now, request a free SSL certificate from Let's Encrypt using Certbot:

Bash
apt install -y certbot python3-certbot-nginx
certbot certonly --nginx -d panel.yourdomain.com

Once generated, restart Nginx:

Bash
systemctl restart nginx

Your Pterodactyl Panel is now live! You can log in via your domain using the admin credentials you created.

Step 7: Installing Wings (The Daemon)

Wings is Pterodactyl's server control daemon, written in Go. It manages the Docker containers where your game servers run. You can run Wings on the same server as the Panel or on a separate dedicated server.

First, install Docker:

Bash
curl -sSL https://get.docker.com/ | CHANNEL=stable bash
systemctl enable --now docker

Enable Swap in GRUB (Crucial for Docker memory limits):

Bash
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/GRUB_CMDLINE_LINUX_DEFAULT="swapaccount=1 /' /etc/default/grub
update-grub

(You should reboot your server after the installation is complete to apply this).

Install the Wings binary:

Bash
mkdir -p /etc/pterodactyl
curl -L -o /usr/local/bin/wings "https://github.com/pterodactyl/wings/releases/latest/download/wings_linux_$([[ "$(uname -m)" == "x86_64" ]] && echo "amd64" || echo "arm64")"
chmod u+x /usr/local/bin/wings

Now, log in to your Pterodactyl Panel web interface:

  1. Go to the Admin control panel.
  2. Navigate to Locations and create a new location (e.g., "FitServers-EU").
  3. Navigate to Nodes and click Create New.
  4. Fill in the details:
    • Name: Main Node
    • Location: Select your location.
    • FQDN: Enter panel.yourdomain.com (or the IP if running Wings on a separate server).
    • Total Memory: Enter your server's RAM in MB.
    • Total Disk Space: Enter your server's storage in MB.
  5. Save the Node, then go to the Configuration tab for that Node. Click Generate Token.
  6. Copy the configuration command (it looks like cd /etc/pterodactyl && sudo wings configure ...).
  7. Paste that configuration command into your server's SSH terminal.

Finally, create a Systemd service for Wings:

Bash
nano /etc/systemd/system/wings.service

Paste the following:

INI
[Unit]
Description=Pterodactyl Wings Daemon
After=docker.service
Requires=docker.service
PartOf=docker.service

[Service]
User=root
WorkingDirectory=/etc/pterodactyl
LimitNOFILE=4096
PIDFile=/var/run/wings/daemon.pid
ExecStart=/usr/local/bin/wings
Restart=on-failure
StartLimitInterval=180
StartLimitBurst=30
RestartSec=5s

[Install]
WantedBy=multi-user.target

Enable and start Wings:

Bash
systemctl enable --now wings

If you check your Panel now, the Node should show a green heart, meaning it is successfully connected!

⚡ Optimization Secrets for FitServers Dedicated Hardware

A standard installation works well, but to extract enterprise-grade performance from your bare-metal server, apply these optimizations:

  • 1. MariaDB Performance Tuning

    Game servers running on Pterodactyl (especially large Minecraft networks or FiveM servers) query the database constantly.

    Open /etc/mysql/mariadb.conf.d/50-server.cnf and adjust the InnoDB buffer pool based on your server RAM. If you have a 64GB dedicated server, you can safely allocate 4GB to the database:

    INI
    innodb_buffer_pool_size = 4G
    innodb_log_file_size = 1G
    innodb_flush_log_at_trx_commit = 2

    Restart MariaDB: systemctl restart mariadb.

  • 2. Nginx File Upload Limits

    By default, Nginx limits uploads to 1MB. If a user tries to upload a custom game map via the Panel web interface, it will fail.

    Open /etc/nginx/nginx.conf and add/modify this inside the http {} block:

    Nginx
    client_max_body_size 1024M;
    client_body_buffer_size 128k;

    Restart Nginx: systemctl restart nginx.

  • 3. Docker Overlay2 and IOPS Limits

    If you are running IO-heavy games (like Rust), you must ensure your Docker storage driver is using overlay2. Furthermore, if you are using NVMe drives provided by FitServers, you can modify specific server containers in the Pterodactyl Panel settings to have unmetered IOPS limits (Set Block IO Weight to 1000).

  • 4. Bypassing Cloudflare for Wings Traffic

    If you put your Panel behind Cloudflare to hide the IP, make sure your Node (Wings) traffic bypasses the proxy. Routing game server SFTP (Port 2022) or Wings communication (Port 8080) through Cloudflare's HTTP proxy will cause connections to time out and break the console. Create a separate subdomain (e.g., node.yourdomain.com), turn off the orange Cloudflare proxy cloud (DNS only), and assign that to your Node FQDN in the Panel.

Ready for Deployment

Your dedicated server is now running a highly optimized, secure, and production-ready Pterodactyl Panel. You are ready to start creating game servers, allocating resources, and assigning users!