Pterodactyl Database Hosts: Setup and Connection Fixes

Published on

Add a MariaDB or MySQL database host to Pterodactyl: the account and grants, bind-address, firewall, the Host field, TLS, and what each error means.

Overview page of a VPS control panel with disk usage, bandwidth, CPU and network speed graphs and a Firewall item in the side menu

A plugin needs MySQL, but your Pterodactyl panel's Databases tab says "Databases cannot be created for this server", or adding a database host under Admin, Databases fails with SQLSTATE[HY000] [2002] Connection refused. A database host needs an account the panel can use, a database server that listens on the network, a firewall that admits the right machines, and a Host value that works for the panel and every game server. Here is each one on Ubuntu 24.04 and Debian 12, checked against the source of Panel 1.15.2, the stable release on 30 October 2026.

Quick answer: On the database server, create an account for the panel's IP with ALL PRIVILEGES ON *.* and WITH GRANT OPTION. Debian and Ubuntu packages listen on 127.0.0.1 only, so set bind-address = 0.0.0.0, restart MariaDB, and allow port 3306 only from the panel and your nodes. Add the host under Admin, Databases with an address game servers can reach too, since it becomes their endpoint, and give each server a Database Limit above 0. Error 2002 points at the network; 1130, 1045 and 1044 point at the account.

What the Panel Does With a Database Host

The panel logs in to the host with your account and the mysql database selected (DynamicDatabaseConnection.php). For each new database, it runs (DatabaseRepository.php, DatabaseManagementService.php):

  • CREATE DATABASE IF NOT EXISTS for s<server id>_<name>, at most 48 characters
  • CREATE USER for u<server id>_ plus 10 random characters, at the address in Connections From, with a random 24-character password
  • GRANT of 18 privileges, from SELECT to TRIGGER, on that database only
  • FLUSH PRIVILEGES

Users see the host's address and port as their Endpoint (DatabaseTransformer.php, DatabaseRow.tsx). Game servers connect to it directly, so the Host field must work from the panel and from every game server's container:

Database runs onHost fieldPanel account's host partAllow port 3306 from
Its own server, or a nodeThat server's IPThe panel's IPThe panel and every node
The panel server, nodes elsewhereThe panel server's public IPThe panel server's public IPEvery node
One VPS with panel, Wings and database172.18.0.1172.18.0.1172.18.0.0/16

Wings runs game servers on the Docker network pterodactyl_nw (bridge pterodactyl0, subnet 172.18.0.0/16, host address 172.18.0.1) and creates it when it starts (config_docker.go, docker.go). On a single VPS, add the host after Wings has run once; your firewall then opens 3306 to the Wings network only, not to the internet. Never enter 127.0.0.1 or localhost: game servers get the same value, and inside a container 127.0.0.1 is "the container's own loopback address" (Docker networking). A Space-Node VPS has full root access, so MariaDB can run next to Wings or on a VPS of its own.

Step 1: Create the Panel's Account

sudo apt install -y mariadb-server installs MariaDB on Ubuntu 24.04 and Debian 12; a panel server already has it from the panel install. These packages give root@localhost unix_socket authentication (MariaDB on Debian and Ubuntu), so sudo mariadb opens a root prompt. Run the two statements from the Pterodactyl MySQL guide, with the address from the table:

CREATE USER 'pterodactyluser'@'203.0.113.10' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON *.* TO 'pterodactyluser'@'203.0.113.10' WITH GRANT OPTION;

Why so broad? GRANT needs "the privileges that you are granting" plus "the GRANT OPTION privilege", which ALL PRIVILEGES "does not grant", and CREATE USER needs the global CREATE USER privilege. A narrower grant without rights on the mysql database fails at login with error 1044. *.* covers every database on that server, including the panel's own when both share one MariaDB. Never reuse the panel's pterodactyl account; the form says "Do not use the same account details for MySQL that you have defined for this panel."

Step 2: Make MariaDB Listen on the Network

The packaged 50-server.cnf sets bind-address = 127.0.0.1 on both Debian 12 and Ubuntu 24.04. Files in /etc/mysql/mariadb.conf.d/ are read "in the byte order of their file names", and "the value from the file read last takes effect" (option files), so a 99- file wins:

printf '[mysqld]\nbind-address = 0.0.0.0\n' | sudo tee /etc/mysql/mariadb.conf.d/99-pterodactyl.cnf
sudo systemctl restart mariadb
sudo mariadb -e 'SELECT @@bind_address'
sudo ss -ltnp | grep 3306

The query should print 0.0.0.0, and ss should list 0.0.0.0:3306. The Pterodactyl guide appends the same lines to my.cnf, which also works on Debian and Ubuntu: my.cnf points to mariadb.cnf, whose !includedir lines come first. From MariaDB 10.11 (Ubuntu 24.04 ships 10.11.14, Debian 12 ships 10.11.18), a list such as 127.0.0.1,10.0.0.5 listens on loopback and one private address only.

On MySQL, change bind-address in /etc/mysql/mysql.conf.d/mysqld.cnf and run sudo systemctl restart mysql.service (Ubuntu's MySQL guide).

Step 3: Allow Port 3306 From the Panel and Nodes Only

With UFW, add one rule per panel or node address:

sudo ufw allow proto tcp from 203.0.113.10 to any port 3306
sudo ufw allow proto tcp from 203.0.113.21 to any port 3306
sudo ufw status numbered

If game servers run on the database's own machine, allow the Wings network too:

sudo ufw allow proto tcp from 172.18.0.0/16 to any port 3306

Docker sends traffic for published ports past "the INPUT and OUTPUT chains that ufw uses" (Docker docs, see our Docker and UFW guide), but a game server reaching MariaDB on its own node connects to the host itself, so UFW's default input policy, DROP in its defaults file, blocks it. deny ignores packets while reject lets the sender know (ufw(8)), so a blocked connection times out instead of being refused. Keep 3306 closed to everyone else, as our Panel vs Wings guide advises. UFW is disabled on installation, so these rules only apply after sudo ufw enable; allow SSH (sudo ufw allow 22/tcp) and the panel's or node's ports from that guide first.

Step 4: Add the Host in the Panel

In the admin area, open Databases, Create New (form):

  • Name: any label, such as db-node1.
  • Host: "The IP address or FQDN that should be used when attempting to connect to this MySQL host from the panel to add new databases." Only letters, digits, dots, hyphens and underscores pass validation (DatabaseHost.php), so an IPv6 address is refused.
  • Port: 3306 by default.
  • Username and Password: the account from step 1.
  • Linked Node: the node whose servers should use this host.

On Create, the panel saves the host and runs SELECT 1 FROM dual in one transaction, so a failed test saves nothing (HostCreationService.php). The red alert starts with "There was an error while trying to connect to the host or while executing a query:", then the database error, with the connection and the query in brackets (DatabaseController.php, QueryException.php). Edits run the same test, and an empty Password field keeps the stored one (HostUpdateService.php).

New databases go to a host linked to the server's node, otherwise to a random host unless PTERODACTYL_CLIENT_DATABASES_ALLOW_RANDOM is false in .env (DeployServerDatabaseService.php, config/pterodactyl.php), so link each host to a node.

Step 5: Let Servers Create Databases

Servers created in the admin area start with Database Limit 0 (new server form), and their Databases tab then shows "Databases cannot be created for this server." (DatabasesContainer.tsx). Raise it under Admin, Servers, the server, Build Configuration. The user then clicks New Database:

  • Database Name: 3 to 48 characters; the panel adds s<server id>_ and cuts the result at 48.
  • Connections From: "Where connections should be allowed from. Leave blank to allow connections from anywhere." Blank means % (CreateDatabaseButton.tsx). MariaDB host patterns work (CREATE USER): a node's IP, 172.18.0.%, or 172.18.0.0/255.255.0.0 for the whole Wings network.

Game servers on other nodes arrive from their node's IP, since Docker masquerades container traffic to other hosts (Docker docs); those on the database's own machine arrive from the Wings network. The value can't be edited later: a database only offers Delete and Rotate Password, which recreates the user with the same value (DatabasePasswordService.php). With 3306 firewalled, blank is the simplest choice.

TLS Notes

  • The panel connects without TLS. Its own database connection reads TLS settings such as MYSQL_ATTR_SSL_CA from .env (config/database.php), but the connection to a database host passes no TLS options, and PHP's PDO only starts TLS when one is set (mysql_driver.c). That link carries CREATE USER ... IDENTIFIED BY with each new password in plain text, so keep it on one machine, a private network or a WireGuard tunnel, as in our private access guide.
  • Don't require TLS from the panel. With require_secure_transport on, MariaDB rejects "connections attempted using insecure transport" (server variables), and REQUIRE SSL on the panel's account means "The account must use TLS". Either way the panel can't log in, while a local sudo mariadb keeps working, because Unix sockets count as secure.
  • Defaults. Before MariaDB 11.4, so also on the 10.11 of Ubuntu 24.04 and Debian 12, data travels unencrypted by default (secure connections). TLS rules added by hand to a panel-made user vanish at the next Rotate Password.

Errors and What They Mean

PHP puts the MariaDB error number in brackets (pdo_dbh.c, mysqlnd_vio.c):

ErrorCauseFix
SQLSTATE[HY000] [2002] Connection refusedNothing listens there: bind-address still 127.0.0.1, MariaDB stopped or a wrong portStep 2
SQLSTATE[HY000] [2002] Connection timed outA firewall drops the packets, or the IP is wrongStep 3
SQLSTATE[HY000] [1130] Host '203.0.113.10' is not allowed to connect to this MariaDB serverNo account matches that address (error 1130)Create the account for exactly that address
SQLSTATE[HY000] [1045] Access denied for user 'pterodactyluser'@'203.0.113.10' (using password: YES)A wrong password, or the account exists only for another address (error 1045)Check with the queries below
SQLSTATE[HY000] [1044] Access denied for user 'pterodactyluser'@'203.0.113.10' to database 'mysql'No rights on the mysql database (error 1044)Grant as in step 1
Error 1045 for 'pterodactyluser'@'localhost', or a 2002 errorHost field localhost: PHP then uses the Unix socket (PDO_MYSQL DSN), and MariaDB sees the client as localhost, which an account for an IP address doesn't matchEnter an IP
"No database host was found that meets the requirements for this server."No host exists, or none is linked to the node while random hosts are offStep 4
"An unexpected error was encountered while processing this request, please try again."The host refused a statement or was unreachable; users only see this (Handler.php)Read the panel log

On MySQL, error 1130 ends in "this MySQL server" (MySQL error reference). In the panel log, error 1044 or 1227 on CREATE DATABASE, CREATE USER or GRANT means missing privileges. Plugins report the same numbers: 1130, or 1045 with the right password, naming a node IP or a 172.18.0.x address means Connections From doesn't cover it, and a timeout means a missing firewall rule.

If It Still Fails

From the panel server, repeat the panel's login without TLS (--disable-ssl; a MySQL client takes --ssl-mode=DISABLED):

mariadb -h 203.0.113.30 -P 3306 -u pterodactyluser -p --disable-ssl -D mysql -e 'SELECT 1'

From a node, test the port with bash's /dev/tcp:

timeout 5 bash -c '</dev/tcp/203.0.113.30/3306' && echo open

open means MariaDB answers. "Connection refused" points to step 2, and silence for 5 seconds to step 3. Then check the logs and the accounts:

sudo tail -n 100 /var/www/pterodactyl/storage/logs/laravel-$(date +%F).log
sudo journalctl -u mariadb -n 50 --no-pager
sudo mariadb -e "SELECT User, Host FROM mysql.user"
sudo mariadb -e "SELECT user, host, db FROM information_schema.PROCESSLIST"

The first command (troubleshooting page) runs on the panel server and shows the real error behind the generic message. MariaDB on Debian and Ubuntu logs Access denied for user warnings to the journal. The last query lists connected clients by address and port (PROCESSLIST), showing whether game servers arrive from a node IP or 172.18.0.x.

FAQ

Can the database host be the MariaDB that holds the panel's database? Yes, the second row of the table. The panel's account then reaches the panel database too, and nodes need port 3306 on your panel server. A separate MariaDB on a node or its own VPS keeps game data apart from the panel.

Are server databases part of Pterodactyl's backups? No. A backup holds the server's files, and the databases live on the host. Dump them there as in step 6 of our Pterodactyl backup guide; our MariaDB backup guide adds nightly dumps and restore tests.

What happens to the databases when I delete a server? The panel drops each database and its user on the host first. If the host can't be reached, the deletion stops; a forced delete goes ahead and leaves the database behind (ServerDeletionService.php). A host that still has databases can't be deleted: "Cannot delete a database host server that has active databases linked to it."

Does it work with MySQL instead of MariaDB? Yes. The Pterodactyl guide uses the same statements for both, and the panel needs "MySQL 5.7.22 and higher (MySQL 8 recommended) or MariaDB 10.2 and higher" (requirements). The config file and the service name differ, as in step 2.

Sources

All opened on 31 October 2026: