Установка панели Pterodactyl для игровых серверов

Опубликовано 14 мин. чтения

Panel и Wings — две отдельные программы с двумя разными задачами. Кто это понял, устанавливает Pterodactyl за полчаса. Кто не понял, сутками ищет причину сбоя.

Pterodactyl — самая распространённая свободная панель управления игровыми серверами. Слава сложного в установке продукта почти никогда не связана с самой установкой, причина в одном недоразумении: Pterodactyl — это не одна программа, а две. Это руководство аккуратно разделяет обе части, показывает различия между Debian и Ubuntu, а затем разбирает те сообщения об ошибках, которые потом дословно вбивают в поисковик.

Панель и Wings: две программы, две роли

Панель — это PHP-приложение на базе Laravel. Она отдаёт веб-интерфейс, управляет пользователями, правами, базами данных и расписаниями задач, а всё содержимое хранит в собственной базе MySQL или MariaDB. Сама панель никогда не запускает игровой сервер. Она даже ничего не знает о Docker.

Wings — это одна-единственная программа, написанная на Go. Она работает на каждой машине, где действительно должны крутиться игровые серверы: общается с демоном Docker, запускает контейнеры, транслирует консоль и предоставляет доступ по SFTP. У Wings нет ни веб-интерфейса, ни базы данных. Программа слушает HTTP-порт и ждёт указаний от панели.

Обмен между ними идёт исключительно по HTTP, в обе стороны, с подписанными токенами. Отсюда следуют три вещи, которые стоит принять с самого начала:

  • Панель должна обращаться к узлу по доменному имени, а не по IP. Сертификат привязан к имени.
  • Панель и Wings должны говорить по одному протоколу. Панель на HTTPS плюс Wings на HTTP не работает: браузер заблокирует соединение с консолью.
  • Часы на обеих машинах должны быть верными. Время жизни токенов измеряется несколькими минутами.

Если эти три предложения усвоены, половина типичных проблем с Pterodactyl уже позади.

Требования и выбор системы

Pterodactyl 1.11 и новее требует PHP 8.2 или 8.3. Именно в этом месте большинство руководств теряет точность, потому что дистрибутивы поставляют очень разные версии. По состоянию на июль 2026 года в стандартных репозиториях картина такая:

СистемаPHPБаза данныхnginx
Debian 128.2 (подходит)MariaDB 10.111.22
Debian 138.4 (слишком новая)MariaDB 11.81.26
Ubuntu 24.048.3 (подходит)MySQL 8.0 или MariaDB 10.111.24
Ubuntu 22.048.1 (слишком старая)MySQL 8.0 или MariaDB 10.61.18
Debian 117.4 (слишком старая)MariaDB 10.51.18

Это руководство рассчитано исключительно на Debian и Ubuntu. В AlmaLinux, Rocky Linux и Oracle Linux нет apt, поэтому ни одна из приведённых ниже команд управления пакетами там не применима.

Практический вывод: Debian 12 и Ubuntu 24.04 — те две системы, на которых панель работает без сторонних репозиториев. На Ubuntu 22.04 понадобится PPA от Ondřej Surý, на Debian 13 — его же репозиторий для Debian, потому что там метапакет тянет PHP 8.4, а composer.json панели явно требует ^8.2 || ^8.3. На практике composer под PHP 8.4 отрабатывает до конца, но это непроверенная территория и не то состояние, в котором стоит держать боевой сервер. Кто хочет обойтись без дополнительного репозитория, берёт Debian 12 или Ubuntu 24.04.

Обе устаревшие системы, кстати, спотыкаются не на команде установки пакетов, а лишь двумя шагами позже, и именно это делает их коварными. apt install php на Ubuntu 22.04 (PHP 8.1.2) и на Debian 11 (PHP 7.4.33) отрабатывает с кодом возврата 0, и только запуск composer обрывается: на Ubuntu 22.04 с сообщением brick/math requires php (^8.2) failed, на Debian 11 с aws/aws-sdk-php requires php (>=8.1) failed. Если вам приходится оставаться на одной из этих систем, ставьте из стороннего репозитория явно версионированные пакеты (php8.3, php8.3-cli, php8.3-fpm и так далее) вместо метапакета php, иначе снова подтянется версия из дистрибутива.

Второе отличие, которое регулярно застаёт врасплох: в Debian вообще нет пакета mysql-server. Там штатной базой является MariaDB, и это совершенно нормально, Pterodactyl требует MariaDB 10.2 или новее. Кто наберёт в Debian apt install mysql-server, получит E: Unable to locate package mysql-server и затем будет искать причину совсем не там.

Для узла с Wings эти правила по PHP, кстати, не действуют вовсе. Wings — это статически слинкованная программа на Go, ей нужны только Docker и более-менее свежее ядро. Узел спокойно может работать на Debian 13, пока панель крутится на Debian 12.

Установка панели

Все команды ниже выполняются от root. Сначала базовые пакеты. Проследите, чтобы расширения PHP были установлены полностью: отсутствие php-bcmath обнаружится только на этапе composer.

apt update
apt -y install curl ca-certificates gnupg lsb-release tar unzip git
apt -y install mariadb-server nginx redis-server
apt -y install php php-cli php-common php-gd php-mysql php-mbstring php-bcmath php-xml php-fpm php-curl php-zip

Сразу проверьте, что версия подходит, прежде чем идти дальше:

php -v
php -m | grep -E "bcmath|mbstring|curl|zip|gd|xml"

Затем composer и файлы панели:

curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php
php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
mkdir -p /var/www/pterodactyl
curl -Lo /var/www/pterodactyl/panel.tar.gz https://github.com/pterodactyl/panel/releases/latest/download/panel.tar.gz
tar -xzf /var/www/pterodactyl/panel.tar.gz -C /var/www/pterodactyl

Теперь база данных. Создавайте пользователя на 127.0.0.1, а не на localhost, иначе сработает доступ через сокет и Laravel позже получит отказ в доступе, хотя пароль верный. Как развести эти два случая, описано в нашей статье про Access denied for user.

mariadb -u root -e "CREATE DATABASE panel;"
mariadb -u root -e "CREATE USER 'pterodactyl'@'127.0.0.1' IDENTIFIED BY 'ЗдесьДлинныйПароль';"
mariadb -u root -e "GRANT ALL PRIVILEGES ON panel.* TO 'pterodactyl'@'127.0.0.1' WITH GRANT OPTION;"
mariadb -u root -e "FLUSH PRIVILEGES;"

После этого базу данных стоит защитить, этому у нас посвящена отдельная статья про защиту MariaDB и MySQL.

Теперь собственно настройка. Команды p:environment интерактивные, они спрашивают URL панели, часовой пояс, драйвер кеша и доступ к базе данных:

cd /var/www/pterodactyl
cp .env.example .env
COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev --optimize-autoloader
php artisan key:generate --force
php artisan p:environment:setup
php artisan p:environment:database
php artisan migrate --seed --force
php artisan p:user:make
chown -R www-data:www-data /var/www/pterodactyl/*

В p:environment:setup выбирайте Redis в качестве драйвера сессий и кеша, тогда описанная ниже очередь заработает как надо. И указывайте URL панели вместе с https://. Указанный здесь http:// позже приводит к смешанному содержимому и к консоли, которая бесконечно ждёт соединения.

nginx и ловушка версий

Основы настройки веб-сервера описаны в нашей статье про установку nginx. Для Pterodactyl важны две детали, на которых регулярно спотыкаются готовые шаблоны из сети.

Во-первых, сокет PHP-FPM. Имя файла содержит версию PHP и отличается от системы к системе. Посмотрите его, а не угадывайте:

systemctl status php8.2-fpm
ls /run/php/

В Debian 12 сокет называется php8.2-fpm.sock, в Ubuntu 24.04 — php8.3-fpm.sock. Неверный путь здесь даёт ровно ту самую страницу 502 Bad Gateway, которую потом так усердно ищут. Запрос статуса стоит перед этим намеренно: файл сокета появляется только тогда, когда служба FPM запущена. Если она не стартовала, каталог /run/php/ пуст, и путь ошибочно кажется неправильным. Если служба ещё не работает, поможет systemctl enable --now php8.2-fpm с номером версии, подходящим для вашей установки.

Во-вторых, написание HTTP/2. Новая директива http2 on; появилась только в nginx 1.25.1. В Debian 12 (1.22), Ubuntu 22.04 (1.18) и даже в Ubuntu 24.04 (1.24) придётся использовать старую форму listen 443 ssl http2;, иначе запуск оборвётся с ошибкой nginx: [emerg] unknown directive "http2". Только Debian 13 с nginx 1.26 понимает обе формы.

server {
    listen 443 ssl http2;
    server_name panel.example.com;
    root /var/www/pterodactyl/public;
    index index.php;
    client_max_body_size 100m;

    ssl_certificate /etc/letsencrypt/live/panel.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/panel.example.com/privkey.pem;

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

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTP_PROXY "";
    }
}

Очередь и планировщик

Без этих двух составляющих панель выглядит работоспособной, но не отправляет письма и не выполняет запланированные задачи. Устройство unit-файла подробно разобрано в нашей статье про создание службы systemd, здесь готовый вариант:

[Unit]
Description=Pterodactyl Queue Worker
After=redis-server.service

[Service]
User=www-data
Group=www-data
Restart=always
RestartSec=5s
ExecStart=/usr/bin/php /var/www/pterodactyl/artisan queue:work --queue=high,standard,low --sleep=3 --tries=3

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now redis-server
systemctl enable --now pteroq.service

Плюс запись в crontab пользователя root, подробности синтаксиса есть в статье Настройка cron-задания в Linux:

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

Установка Wings на узле

Дальше вы работаете на машине, которая должна выполнять игровые серверы. Это может быть тот же самый сервер, но не обязательно. Обязательное условие — Docker, его установку мы описали в статье Установка Docker в Debian и Ubuntu.

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/wings
wings version

На ARM-серверах файл называется wings_linux_arm64. Если скачать не тот пакет, оболочка просто ответит cannot execute binary file: Exec format error. Не удивляйтесь выводу последней строки: wings version отвечает с удвоенной буквой v, то есть примерно wings vv1.13.1. Так это приходит от разработчика и не является признаком сломанной установки.

Файл /etc/pterodactyl/config.yml вы не пишете сами. Он появится автоматически чуть позже. Пока создайте только службу:

[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

Пока не запускайте. Без конфигурации Wings сразу завершится с сообщением, которое по смыслу указывает на отсутствующий файл конфигурации /etc/pterodactyl/config.yml. На этом этапе это совершенно нормально и не является ошибкой.

Пара слов о файле подкачки: многие старые руководства требуют swapaccount=1 в /etc/default/grub. Это касается исключительно систем с cgroup v1. Debian 12 и 13, а также Ubuntu 22.04 и 24.04 по умолчанию используют cgroup v2, там такая запись избыточна. Проверить можно командой docker info. Если в выводе появляется WARNING: No swap limit support, ограничение памяти для подкачки не действует. О том, как вообще разумно рассчитывать объём подкачки, написано в статье Настройка swap.

Сертификат для узла, а не только для панели

Самое частое заблуждение: человек получает сертификат для panel.example.com и удивляется, что узел не работает. Wings нужен собственный сертификат для собственного доменного имени, например node1.example.com. Оба имени могут указывать на один и тот же IP, но это два разных имени.

На чистом узле веб-сервер не работает, поэтому проще всего использовать автономный режим Certbot. Для этого порт 80 должен быть ненадолго доступен извне:

apt -y install certbot
certbot certonly --standalone -d node1.example.com

Кто держит много узлов, тому удобнее подстановочный сертификат, о нём мы пишем в статье Wildcard-сертификат Let's Encrypt.

Два подводных камня, которые стоят много времени:

  • Wings считывает файлы сертификата при запуске. После обновления сертификата службу нужно перезапустить. Положите в /etc/letsencrypt/renewal-hooks/deploy/ небольшой скрипт с systemctl restart wings. Без этого узел 90 дней работает безупречно, а потом отваливается будто бы без причины.
  • Отключите проксирование Cloudflare для имени узла. Оранжевое облако разрывает TLS-соединение и подменяет сертификат. Панель получает сертификат, который не соответствует ожидаемому издателю, и соединение с консолью через WebSocket начинает вести себя непредсказуемо. A-запись для узла должна быть серой.

Создание узла и подключение

В панели в разделе Admin, Locations сначала создайте локацию, затем в Nodes сам узел. Поля, которые действительно важны:

  • FQDN: node1.example.com, ровно то имя, что и в сертификате.
  • Communicate over SSL: включено, если панель работает по HTTPS. Иначе и начинать не стоит.
  • Behind Proxy: включайте только тогда, когда перед Wings действительно стоит reverse proxy и он терминирует TLS.
  • Daemon Port: 8080. Daemon SFTP Port: 2022.
  • Memory и Disk: границы, которые панель учитывает при распределении серверов.

После сохранения откройте у узла вкладку Configuration. Там панель формирует команду с одноразовым токеном. Выполните её на узле:

cd /etc/pterodactyl
wings configure --panel-url https://panel.example.com --token TOKEN --node 1

Так Wings забирает свою полную конфигурацию и записывает /etc/pterodactyl/config.yml. Проверьте содержимое: если в адресе панели стоит http:// вместо https://, значит команда скопирована из окружения, где URL панели прописан неверно. Исправляйте в корне, командой php artisan p:environment:setup, а не руками в YAML-файле.

Затем на вкладке Allocations внесите IP узла и нужные диапазоны портов, например с 25565 по 25600 для Minecraft. Без хотя бы одного свободного allocation создать сервер не получится.

Только теперь запускаем:

systemctl enable --now wings
systemctl status wings

Порты должны быть открыты в файрволе. С помощью ufw, основы которого мы разбираем в статье Настройка файрвола ufw:

ufw allow 8080/tcp
ufw allow 2022/tcp
ufw allow 25565:25600/tcp
ufw allow 25565:25600/udp

Если Wings не подключается

Панель показывает у узла красный значок или выдаёт ошибку при создании сервера. Разбирайте сообщения по порядку, они на удивление однозначны.

cURL error 7: Failed to connect ... Connection refused

Сервер с панелью не может достучаться до порта. Либо Wings не запущен, либо блокирует файрвол, либо служба слушает не тот адрес. Проверяйте в такой последовательности:

systemctl status wings
ss -tlnp | grep 8080
journalctl -u wings -n 50 --no-pager

И с сервера панели, это решающая проверка:

curl -v https://node1.example.com:8080

Ответ по HTTP, пусть даже 404 с содержимым JSON, здесь означает успех. Он доказывает, что DNS, файрвол, порт и TLS работают вместе.

cURL error 60: SSL certificate problem

Сертификат узла не принимается. При self signed certificate используется самоподписанный сертификат, с ним панель не справляется, потому что нижележащая библиотека не знает исключений. При unable to get local issuer certificate чаще всего не хватает промежуточной цепочки, тогда конфигурация Wings ссылается на cert.pem вместо fullchain.pem. При certificate has expired обновление прошло, но Wings всё ещё держит в памяти старый файл, смотрите пункт про перезапуск выше.

cURL error 28: Operation timed out

Ни ответа, ни сброса соединения. Это похоже на файрвол, который отбрасывает пакеты вместо явного отказа, или на узел за NAT. Особый случай: панель и Wings на одном сервере, и панель обращается к собственному публичному IP. Некоторые сети такую петлю не возвращают. Помогает запись в /etc/hosts на сервере панели, которая указывает имя узла на внутренний адрес.

Cannot connect to the Docker daemon at unix:///var/run/docker.sock

Wings работает, Docker нет. systemctl status docker проясняет это одной строкой. Узел при этом часто всё равно отображается в панели как доступный, потому что опрос состояния проходит, но любой запуск сервера завершается неудачей.

Узел отвечает, но любое действие отклоняется

Не совпадает токен. Так бывает после повторного wings configure со старым токеном или после того, как узел удалили в панели и создали заново. Решение: в панели на вкладке Configuration сгенерировать свежий токен, выполнить команду ещё раз, перезапустить Wings. Не гадайте в YAML-файле.

Во всех случаях, когда сообщение остаётся непонятным, остановите службу и запустите Wings в переднем плане. Вывод заметно разговорчивее журнала:

systemctl stop wings
wings --debug

Не менее полезен встроенный режим отчёта, который собирает конфигурацию, состояние Docker и системные данные:

wings diagnostics

Расхождение времени между панелью и узлом

Эта ошибка коварна, потому что выглядит как проблема сети. Симптомы: узел отображается в панели как доступный, серверы создаются, но консоль зависает на установлении соединения, а доступ по SFTP отклоняет верные учётные данные.

Причина кроется в самой конструкции. Панель подписывает короткоживущие токены, срок действия которых измеряется минутами. Wings проверяет время выпуска и срок окончания по собственным часам. Если две системы расходятся больше чем на пару минут, Wings отбрасывает любой токен как просроченный или как ещё не действительный, хотя он только что создан.

Важно понимать: дело не в часовом поясе. Панель и узел могут стоять в разных часовых поясах, это не имеет значения. Речь об абсолютном моменте времени. Проверьте на обеих машинах:

date -u
timedatectl status

В выводе timedatectl должно стоять System clock synchronized: yes и NTP service: active. Если нет:

timedatectl set-ntp true

В системах без systemd-timesyncd, например после минимальной установки, поставьте chrony и проверьте синхронизацию:

apt -y install chrony
chronyc tracking

Значение у System time должно находиться в пределах миллисекунд. Чаще всего заметные расхождения дают виртуальные машины, клонированные из образа или восстановленные из снимка.

Как понять, что всё действительно работает

Зелёный значок в панели — лишь первое из пяти подтверждений. Пройдите по списку, и тогда будете знать наверняка:

  1. systemctl is-active wings выдаёт active, а journalctl -u wings -n 20 не показывает повторяющихся ошибок.
  2. Узел в обзоре сообщает фактический объём оперативной памяти и накопителя целевого сервера, а не только границы, вписанные в панели. Эти цифры приходят с узла в реальном времени и служат доказательством работающего обмена.
  3. Вы создаёте тестовый сервер. В обзоре он проходит состояние Installing, после чего отображается обычным образом. На узле docker ps -a показывает соответствующий контейнер.
  4. Вы запускаете сервер и видите в браузере живой вывод консоли. Это доказательство соединения по WebSocket, а значит, сразу и сертификата, и времени.
  5. Вы подключаетесь по SFTP на порт 2022 со своими учётными данными от панели и видите файлы сервера. Тем самым подтверждён и второй порт Wings.

Установка завершена только тогда, когда сходятся все пять пунктов. Опыт показывает, что чаще всего не проходят четвёртый и пятый, хотя до этого момента панель выглядит совершенно исправной.

Панель и Wings вместе или раздельно

Возможны оба варианта. На одном сервере нужно учесть всего две вещи: используйте два разных доменных имени на одном IP, одно для панели на порту 443 и одно для узла на порту 8080. И рассчитывайте на то, что аппетит игровых серверов к памяти притормозит заодно и панель, когда станет тесно.

Начиная со второго узла раздельная схема и так становится обычным делом, и у неё есть приятный побочный эффект: перегруженный или атакуемый игровой сервер не утянет за собой интерфейс управления. Для базовой защиты обеих машин стоит заглянуть в наш чек-лист для нового root-сервера, а также в статьи про защиту SSH и fail2ban.

Напоследок практическое замечание для эксплуатации: образы Docker для игровых серверов приносят собственную среду Java с собой. Устанавливать Java на узле не нужно. Кто всё же захочет разок протестировать что-то вне Pterodactyl, найдёт подходящие пути в наших статьях про Java 21 в Debian и про сервер Minecraft в Debian. И следите за местом на диске: образы и резервные копии растут быстро, к этому подходит статья Диск заполнен в Linux.

Частые вопросы

Чем отличается Pterodactyl Panel от Wings?
Панель — это веб-интерфейс на PHP с базой данных, который управляет пользователями, правами и конфигурацией. Wings — это отдельная программа на Go, она работает на узле, общается с Docker и фактически запускает игровые серверы. Сама панель никогда не выполняет игровой сервер, а у Wings нет веб-интерфейса. Обмен между ними идёт по HTTP.
Какая версия PHP нужна для Pterodactyl?
Pterodactyl 1.11 и новее требует PHP 8.2 или 8.3. Debian 12 поставляет 8.2, Ubuntu 24.04 поставляет 8.3, там всё работает без сторонних репозиториев. В Ubuntu 22.04 есть только 8.1, а в Debian 13 уже 8.4, и в обоих случаях понадобится дополнительный репозиторий PHP.
Почему Wings не подключается к панели?
Проверяйте в таком порядке: работает ли служба (systemctl status wings), открыт ли порт 8080 (ss -tlnp), достаёт ли сервер панели до узла (curl -v https://node1.example.com:8080), соответствует ли сертификат FQDN и синхронны ли часы на обеих машинах. Для подробностей запустите Wings в переднем плане командой wings --debug.
Какие порты нужно открыть для Pterodactyl?
На сервере с панелью порт 443 для HTTPS и порт 80 для обновления сертификата. На узле порт 8080 для связи с Wings, порт 2022 для SFTP и дополнительно диапазоны портов самих игровых серверов, у Minecraft обычно начиная с 25565.
Нужен ли отдельный SSL-сертификат для каждого узла?
Да. Панель обращается к узлу по его собственному доменному имени, сертификата панели для этого недостаточно. Либо вы получаете отдельный сертификат на каждый узел, либо используете подстановочный сертификат на весь поддомен. После каждого обновления Wings нужно перезапускать.
Почему консоль сервера в браузере зависает на установлении соединения?
Чаще всего дело во времени. Панель подписывает токены с очень коротким сроком жизни, а Wings проверяет их по собственным часам. Если системное время расходится больше чем на пару минут, любой токен отбрасывается. Проверьте на обеих машинах date -u и timedatectl status. Вторая частая причина: панель на HTTPS и узел без SSL.
Нужно ли устанавливать Java на узле?
Нет. Образы Docker для Minecraft и других игр на Java приносят среду выполнения с собой. На узле достаточно Docker. Установленную на хосте Java Pterodactyl не использует.

Pterodactyl Игровые серверы Wings Docker Panel Minecraft Linux Debian Ubuntu