Deploy Pelican Panel on a VPS
Modern open-source game server management platform — the spiritual successor to Pterodactyl with a polished UI and Wings daemon.
Prerequisites
- 2 vCPU cores minimum (4 recommended if co-locating Wings)
- 2 GB RAM minimum for the panel (4 GB+ if running Wings on the same server)
- 20 GB SSD storage minimum
- Ubuntu 22.04 LTS
- A domain or subdomain pointed at your VPS IP
- Root or sudo access
Architecture note: The panel and Wings (the daemon that runs game servers) are separate components. For production, run Wings on a dedicated node. This guide covers both panel installation and Wings setup.
Prepare the Server
apt update && apt upgrade -yapt install -y curl wget git unzip tar software-properties-commonInstall PHP 8.3
add-apt-repository ppa:ondrej/php -y
apt update
apt install -y php8.3 php8.3-fpm php8.3-cli php8.3-mysql php8.3-pgsql \
php8.3-mbstring php8.3-tokenizer php8.3-bcmath php8.3-xml php8.3-curl \
php8.3-zip php8.3-gd php8.3-intl php8.3-redisInstall Composer
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
composer --versionInstall MariaDB
apt install -y mariadb-server
systemctl enable mariadb
systemctl start mariadb
mysql_secure_installationInstall Redis & Nginx
apt install -y redis-server
systemctl enable redis-server
systemctl start redis-server
apt install -y nginx
systemctl enable nginx
systemctl start nginxCreate the Database
mysql -u root -pCREATE DATABASE pelican;
CREATE USER 'pelican'@'127.0.0.1' IDENTIFIED BY 'your_strong_password_here';
GRANT ALL PRIVILEGES ON pelican.* TO 'pelican'@'127.0.0.1';
FLUSH PRIVILEGES;
EXIT;Download and Install Pelican Panel
mkdir -p /var/www/pelican
cd /var/www/pelican
curl -Lo panel.tar.gz https://github.com/pelican-dev/panel/releases/latest/download/panel.tar.gz
tar -xzvf panel.tar.gz
chmod -R 755 storage/* bootstrap/cache/composer install --no-dev --optimize-autoloadercp .env.example .env
php artisan key:generate --forceConfigure the Environment
nano .envAPP_URL=https://panel.yourdomain.com
APP_TIMEZONE=UTC
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=pelican
DB_USERNAME=pelican
DB_PASSWORD=your_strong_password_here
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379php artisan migrate --seed --force
chown -R www-data:www-data /var/www/pelicanConfigure Nginx
rm /etc/nginx/sites-enabled/default
nano /etc/nginx/sites-available/pelicanserver {
listen 80;
server_name panel.yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name panel.yourdomain.com;
root /var/www/pelican/public;
index index.php;
access_log /var/log/nginx/pelican.access.log;
error_log /var/log/nginx/pelican.error.log error;
client_max_body_size 100m;
client_body_timeout 120s;
sendfile off;
ssl_certificate /etc/letsencrypt/live/panel.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/panel.yourdomain.com/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;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header Content-Security-Policy "frame-ancestors 'self'";
add_header X-Frame-Options DENY;
add_header Referrer-Policy same-origin;
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;
}
}ln -s /etc/nginx/sites-available/pelican /etc/nginx/sites-enabled/Issue an SSL Certificate
apt install -y certbot python3-certbot-nginx
certbot certonly --nginx -d panel.yourdomain.comnginx -t
systemctl reload nginxConfigure the Queue Worker
Pelican uses Laravel's queue system for background tasks. Create a systemd service:
[Unit]
Description=Pelican Panel Queue Worker
After=redis-server.service
[Service]
User=www-data
Group=www-data
Restart=always
ExecStart=/usr/bin/php /var/www/pelican/artisan queue:work --queue=high,standard,low --sleep=3 --tries=3
StartLimitInterval=180
StartLimitBurst=30
RestartSec=5s
[Install]
WantedBy=multi-user.targetsystemctl enable --now pelican.service
systemctl status pelican.serviceSet Up the Cron Job
crontab -e -u www-data* * * * * php /var/www/pelican/artisan schedule:run >> /dev/null 2>&1Create the Admin User
php artisan p:user:makeYou will be prompted for email, username, name, password, and whether the user should be an admin (enter yes).
Log In and Configure the Panel
Navigate to https://panel.yourdomain.com and log in with your admin credentials.
Create a Location
Go to Admin → Locations → Create New. Give it a short name (e.g., us-east).
Create a Node
Go to Admin → Nodes → Create New. Set the FQDN, memory, disk limits, and daemon port. After saving, click the Configuration tab to get the Wings YAML.
Install Wings (Game Server Daemon)
Wings runs on the node that hosts your game servers. This can be the same VPS or a separate one.
Install Docker
curl -sSL https://get.docker.com/ | CHANNEL=stable bash
systemctl enable --now dockerDownload Wings
mkdir -p /etc/pelican
curl -L -o /usr/local/bin/wings "https://github.com/pelican-dev/wings/releases/latest/download/wings_linux_amd64"
chmod u+x /usr/local/bin/wingsConfigure Wings
Copy the configuration YAML from the panel's node Configuration tab:
nano /etc/pelican/config.ymlCreate Wings systemd service
[Unit]
Description=Pelican Wings Daemon
After=docker.service
Requires=docker.service
PartOf=docker.service
[Service]
User=root
WorkingDirectory=/etc/pelican
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.targetsystemctl enable --now wings
systemctl status wingsIn the panel, refresh the node page. The status indicator should turn green.
Open Required Firewall Ports
Panel server
ufw allow 80/tcp
ufw allow 443/tcp
ufw enableWings node
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 8080/tcp # Wings daemon (use 443 if configured for SSL)
ufw allow 2022/tcp # SFTP for file management
ufw enableGame server ports
ufw allow 25565:25575/tcp
ufw allow 25565:25575/udpTroubleshooting
Panel shows 500 error
tail -n 50 /var/www/pelican/storage/logs/laravel.logQueue worker is not running
systemctl status pelican.service
journalctl -u pelican.service -n 50Wings node shows offline
Verify Wings is running, the FQDN resolves correctly, and required ports are open.
systemctl status wingsPermission errors
chown -R www-data:www-data /var/www/pelican
chmod -R 755 /var/www/pelican/storage /var/www/pelican/bootstrap/cacheCertbot fails
Ensure DNS A record is pointing to your VPS IP:
dig +short panel.yourdomain.com