Pterodactyl
Join me as we walk through setting up Pterodactyl, a game server hosting platform!
In my group of friends I am usually the one that hosts the server when we play a multiplayer game together. This has gone back for years, since the Minecraft days in 2012, all the way to our Factorio and other servers today. I recently came across a tool called Pterodactyl, which creates a UI for friends and others to login, spin up and maintain game servers, without having to touch the back-end at all. I thought this would be a great way to let my friends provision servers without me having to do it for them, or do other administrative tasks (usually a server restart) on their own.
This guide will be heavily based on the Panel Documentation and Wings Documentation.
Another note for my setup, is that I will be running panel behind a reverse proxy, in my case Nginx Proxy Manager.
Even if I'm the only one who ever uses it, or it never gets used at all, I think it will be a fun project regardless, so let's get started!
Panel
Panel is the Web UI that users will interact with to setup game servers. We will set this up first, and then install Wings later.
Prerequisites
Operating System
The documentation lists a few options for OS's you can use to run Pterodactyl, I am a fan of Debian and Ubuntu, and will be using Ubuntu Server 22.04 VM hosted on one of my Proxmox nodes. I've already done the VM creation, OS install, and setup my SSH keys, but I'll give a quick overview of what I'm using for this VM:
- 16 CPU's (4 Socket x 4 Core)
- 32GB RAM
- 1TB Storage
- Ubuntu Server 22.04
Pterodactyl can be installed on a bare-metal server, or a VM depending on your use case. I happen to have a server with lots of juice, so I chose to virtualize on that server, but as long as you are running Ubuntu or Debian, this guide should apply to you.
Software Dependencies
These are again from the Pterodactyl Documentation.
- PHP
8.0
or8.1
(recommended) with the following extensions:cli
,openssl
,gd
,mysql
,PDO
,mbstring
,tokenizer
,bcmath
,xml
ordom
,curl
,zip
, andfpm
if you are planning to use NGINX. - MySQL
5.7.22
and higher (MySQL8
recommended) or MariaDB10.2
and higher. - Redis (
redis-server
) - A webserver (Apache, NGINX, Caddy, etc.). I will be using NGINX for this guide.
curl
tar
unzip
git
composer
(v2)
These can be installed one at a time, or in bulk using something like below:
(make sure to run as root)
Composer
Composer is a dependency manager for PHP, which Pterodactyl uses to operate to web UI panel. You can install it using the following command:
File Setup
We will want to make a folder where we can install and setup Pterodactyl's web UI, called Panel. First we'll want to make a directory under /var/www/
to hold all our files, and if necessary make our service user the owner.
In my case, I have a user called ptero
that I am making the service user, but you can use whichever user, or leave it as root (though I highly recommend making a separate service user).
Now that we are in the new directory, let's download the files we need from the Pterodactyl Panel official GitHub and unzip the files:
Installation and Config
Now that we have all the prerequisites installed, and a folder with our Panel setup, now we need to install and configure some of the core components for Pterodactyl to work properly.
Database Creation
With mariadb installed as our database, we now need to create a SQL user with security. Enter mariadb's SQL CLI using the following command:
(leave password empty, just press enter)
You should now see a MariaDB CLI
You can now enter this SQL to create a new user with permissions. Make sure to replace 'yourPassword' with an actual password, but keep the single quotes (') around the password itself.
Copy over the default environment settings.
Now use compose to install core dependencies.
(ideally you would not run this next command as root)
Now we'll use a PHP package to create a new encryption key.
ONLY DO THIS FOR FIRST TIME SETUP! IF YOU HAVE ANYTHING SETUP IN PTERODACTYL, IT WILL MAKE YOUR DATA UNREADABLE!
Take note of the APP_KEY
value and store it somewhere safe. This is the encryption key for all your data in Pterodactyl, and is necessary for decryption. Without it, all data will be unreadable. Store it somewhere off-server, like a password manager
Environment Setup
Run this following command to setup your environment
This will ask for information like an email address, a URL, timezone, drivers, etc.
I used the following settings:
Author email: example@n8pete.com
Application URL: example.n8pete.com
Timezone: America/Chicago
Cache Driver: redis
Session Driver: redis
Queue Driver: redis
UI based settings editor?: yes
Anonymous telemetry data?: yes
Redis host: 127.0.0.1 (default)
Redis password: _blank_ (default)
Redits port: 6379 (default)
Now configure the database credentials:
I used the following settings:
(All settings are default except password. To use default, just leave the response blank and press enter)
Database host: 127.0.0.1 (default)
Database port: 3306 (default)
Dasebase name: panel (default)
Database username: pterodactyl (default)
Database password: (PASSWORD SET EARLIER)
These setup scripts will place the values into the .env
file, which contains sensitive information like passwords and encryption keys. TREAT THIS FILE SAFELY!
Database Setup
This command will now setup Pterodactyl using the database you created earlier, and the environment settings we just setup. It may take awhile to run, DO NOT exit the process until it is complete!
First User Setup
Now we will setup our first user, which we will make an admin user. According to Pterodactyl's documentation, the password has the following requirements: 8 characters, mixed case, at least one number.
php artisan p:user:make
Administrator user?: yes
Email address: example@example.com (anonymized)
Username: n8pete (use your own)
First Name: Nathan (use your own)
Last Name: Server (I didn't see a need to use a real last name)
Password: (create own password)
Webserver Permissions
To give the NGINX service the permissions it needs to the folder, we will now set that user to own the folder:
Queue Listeners
Pterodactyl uses queues to handle actions such as sending emails, cleanup, and other scheduled tasks. We will need to setup a queue worker to take care of these tasks.
Crontab
First, we want to create a cronjob that will run every minute to process our Pterodactyl tasks. Run sudo crontab -e
to open the crontab, and then paste the following line at the bottom:
(if it says crontab command is not found, you can install cron by running sudo apt install cron
)
Create Queue Worker
Now let's create a systemd worker to keep the process going in the background.
Create a file called pteroq.service
in /etc/systemd/system
with the following contents:
(Since we configured our environment to use redis, we will keep the line After=redis-server.service
)
Now we will enable the redis server service
And then the pterodactyl service
Now our databases and the Pterodactyl service are running! Next we need to configure the webserver.
Webserver Configuration
For our webserver, we will be using NGINX. Since I am running this behind a reverse Proxy, I only need to use a self-signed certificate on the back-end NGINX instance to facilitate communication between it and the Proxy Manager. The Proxy Manager will handle TLS certificates for the public web.
First, let's generate the self-signed certificate for the NGINX instance. This will create a new folder called certs
in our pterodactyl folder, and then generate the self-signed certificate there.
It will ask some questions, your answers are not super important, but you should still answer them fairly reasonably so you can identify the certs later if needed. The cert that is generated will last for 10 years.
Now we will want to remove the default configuration
Now we want to make a new config file at the location /etc/nginx/sites-available/pterodactyl.conf
. Use the following config, but replace <domain> with either the domain name (server.website.com) if you are routing directly to this server, or the IP address if you are only using Pterodactyl internally, or using a reverse proxy.
Once you've saved the file, we've told nginx that this site is available, but now we need to enable it by creating a sym-link in the enabled-sites folder:
Now we can restart nginx to start up the panel website by running sudo systemctl restart nginx
At this point, you should be able to navigate to the IP address of the server and get to the Web UI / Panel. It will complain about the certificate, since we are just using a self-signed certificate, this is fine for the time being.
Other Config
Reverse Proxy
There are some other things you might need to take care of to get this running properly. As mentioned, I am running a reverse proxy to handle all web requests, so I need to make a change in my .env
file to allow the proxied requests.
I will not be covering how to setup or use Nginx Proxy Manager in this guide, but look for a future blog post on it!
Adding the line TRUSTED_PROXIES=<IP>
will allow a target IP to make proxy requests to the server. I am hosting a reverse proxy server, so I will need to add that IP to the trusted list:
(Use whatever IP your Nginx Proxy Manager instance is hosted on)
I also need to setup the proxy on my Nginx Proxy Manager. Login to the UI, click Hosts > Proxy Hosts > Add Proxy Host
and fill in the appropriate info. Pay special attention to the following details for best security practices:
- Set scheme to
https
and forward port to443
- On SSL page, make sure to select
Request a new SSL certificate
, and checkForce SSL
Additionally, for nginx reverse proxy, we have to add some Advanced
config:
Mail Server
If you want to send emails for you Pterodactyl Server, you need to setup a mail sending service. I will be using the Gmail SMTP server to do this.
You will not want to login to Gmail SMTP using your regular password, create an App Password instead.
You can use several different ports, which correspond to different Encryption Methods. I highly recommend using TLS, or at least SSL.
- TLS = 587
- SSL = 465
- (none) = 25
To setup mailing, on your Panel Web UI go to Admin > Settings > Mail
- SMTP Host: smtp.gmail.com
- SMTP Port: 587
- Encryption: TLS
- Username: gmail username
- Password: App Password you used earlier
- Mail From (Name): Whatever email address and name you want on the "From"
Wings
Wings is the engine that runs the servers. You could have multiple nodes or machines running wings, and Panel will be the central control that uses all the nodes that run wings.
In this case, I will be running Wings on the same server as Panel, but you might in other instances install them on separate machines.
Prerequisites
Operating System
Wings has basically the same requirements as Panel, the big thing it needs is the capability to run Docker. In our case, the Ubuntu 22.04 server will work great.
Dependencies
The only dependencies here are curl
(which we installed earlier) and Docker
, which we will install now:
Now let's set Docker to start on boot
To help prevent Out-Of-Memory errors on our servers, we will enable Docker to use memory swap. This setting is found in the grub settings at /etc/default/grub
. We need to make the following changes:
- Add the value
swapaccount=1
in theGRUB_CMDLINE_LINUX_DEFAULT
setting. - Add the value
systemd.unified_cgroup_hierarchy=1
in theGRUB_CMDLINE_LINUX
setting. (This will allow Panel to see container's CPU and RAM usage)
Then we can update grub with sudo update-grub
and then reboot using sudo reboot
Installing Wings
File Directory Setup
First we need to make a directory for Pterodactyl Wings to run, and then clone down the official GitHub repository, then setup the file permissions to make Wings executable.
Adding Wings Node
To create a node, first we need to create a Location
.
After you make a Location, go to Nodes and chose Add Node. You can customize most of these options, but one thing of note here is that to use SSL between Panel and Wings, you need a FQDN to point to the Wings node. Since my Wings and Panel are running on the same server, I used the same FQDN. Once you put in your settings and create the wings node, you'll want to copy the configuration file, and create a new file on the server at /etc/pterodactyl/config.yml
and paste it in there.
SSL
Since I am using Nginx Reverse Proxy, I am already generating SSL certificates for this domain name. I just need to copy the certificate files from the Nginx Reverse Proxy server to the Wings server, which I am doing using SSH
on a monthly cronjob
.
Testing Connection
Once you get the configuration file and SSL certificate files in place, test the connection to panel by running sudo wings --debug
. If there are any errors, it will tell you what they are, otherwise everything will look good.
Daemonizing Wings
We will want to setup wings to run in the background, and start on boot. Create a new file called wings.service
in /etc/systemd/system
with the following contents:
Now enable it:
To verify it is working, go to the Nodes
tab in Panel, and check that the node has a green heart, and displays a version number when you hover over it:
If you see this, there is an error you need to resolve. Check that the wings service is running, or try running the debug command again to see why it is not connecting.
Networking Considerations
These two Daemon ports need to be open between the Wings Node and Panel, whether that's through internal networking, or external.
Creating a Server
Creating a server is really easy once you have everything setup. I won't go into detail here since the UI is so straightforward if you are using a pre-configured egg.
Custom Nest+Egg Example
There are some great options already built in, but there are many cases where you might want to create a server that doesn't already exist. With some docker knowledge, you can get nearly any server to work. For this example, we will use Mindustry.
Since Pterodactyl runs Docker under the hood, you can mess around on your local machine using Docker to figure a lot of these things out. This is what I did to figure out how to run Mindustry properly, and it took a lot of trial and error. If you are not up to this, you might stick with the official nest/eggs, or use community pre-configured ones, but you should be extra wary using community configurations, as you never know what people might have put in them.
Go to the Nests screen on the left menu. If you are using a community-created egg, you can import it using the green "Import Egg" button, otherwise you can use the "Create New" button to make a completely new, custom egg.
Next, give your nest a name and description. An egg is a specific implementation of a server, and a nest is a group of egg. Mindustry doesn't fix any of the existing nests, so we will make a new one. Once you create your nest, then we can click "New Egg"
Even though you may have entered this screen from a Nest, you still need to specify which nest this new Egg belongs in:
Give it a name and a description, in this case we will do Mindustry. Description doesn't matter, but pick a good one to help you and your users.
Now we will need an understanding of how the server runs in order to properly create our egg. By looking at the Mindustry GitHub, we can tell that the server is a Java application, and needs specifically Java 16 or 17. Luckily there are already plenty of Java optimized docker images for us. In this case we will use Pterodactyl's provided Java image, which they use for Minecraft: ghcr.io/pterodactyl/yolks:java_17
For 'Startup Command', we need to choose which command will be run in the container to start the Mindustry server. We will use the typical command to start a Java application, java -jar "jar-name.jar"
The other config settings will vary widely depending on the server. It takes a decent understanding of each game server and how it works to get these settings right.
- For 'Stop Command", Mindustry uses
exit
to shut down the server. - I couldn't figure out where logs were stored, so you can just leave
{}
to represent empty JSON - Mindustry doesn't use a configuration file, such as a
server.properties
orconfig.json
or anything like that so we will leave it empty with{}
as well. - Start configuration can take several values, but the most important one is the "done" key, which is what tells Pterodactyl that the server started up successfully. Use this JSON block for Mindustry:
{ "done": "Server loaded. Type 'help' for help." }
After you set these settings, go ahead and click Create. If there are any issues, they will be in red at the top of the screen, go ahead and address them before moving on.
Once the Egg is created, we have two choices for creating servers:
- Configure them manually
- Automate the installation and configuration
First I will show you how to manually get a server up and running, then I will show you how we can automate it.
Manual Creation
With an egg created, we can go ahead to the Servers
menu option, and click Create New
. Set the Name and Description for the server, in the Owner box start typing your email address in the Owner box and select your name when it drops down.
You can configure your resource management to your liking (you must set Memory and Disk usage, but you can just choose 0
and move on), and then in the Nest Configuration
Box, make sure to select your new Nest and Egg. Then click Create Server
.
Once you create the egg, click the little box with an arrow to the right of Delete
to open the server console page.
This new server is running a container image with Java ready to go, but we still need to supply the server jar file. We can go to Files
, and Upload
the server-release.jar
file, which you can download from the official GitHub releases page.
Once you upload the file, you can go back to Console
and click Start
, and watch the server start up. If all goes well, you'll see the message: Server loaded. Type 'help' for help.
Which tells us that the server is running!
Mindustry requires you to start hosting by running the command host
in the console before we can connect. Now you can connect from any Mindustry game client on the local network, and if you set up Port Forwarding, you can even access it externally as well!
Automatic Creation
Uploading the server.jar file isn't too difficult, but we can even automate that process away so that if our less-informed friends can also spin up a server with ease.
If you created a server the manual way, go ahead and stop that server, and then delete the server.
Now go back to the Egg you created (Nests > Mindustry > Your Egg
), and go into the Variables
. We will want to make some changes here to follow best practices and allow modulation in our server creations. Add the following variables:
The description isn't necessary, but it is helpful to tell other users (and your future self) how to use this correctly.
Now we can go to Install Script
. This section is where you can put commands to initialize the server before running anything else. It will do it using a Docker image of your choosing, so you will probably want to pick a basic Linux one like Alpine, which is what we will use.
This will require some Bash knowledge, so I'll go ahead and show you the script that I'm using, and then a bulleted summary of what is going on inside.
Make sure that the Script Container is alpine
and the entrypoint is ash
Hopefully the comments helped explain things on their own, but here's the jist of it:
- Use the Ash console
- Setup the directory and put us there
- Add openssl so we can download the server file from GitHub
- Check if the file already exists
- If it does, back it up
- Check the version specified in the server's environment variables
- If using latest, get the latest version from GitHub
- If using another version, get that version from GitHub
- The download will include the client and the server .jar, so we can remove the client one.
Now that we have an install script setup, we can create a new server just like we did before. If you hop over to the console quick enough (there's a 2 second delay added to the script to help with this), you can see the install happening on the console:
Now if you head over to the files
tab, you should see the server jar already there, without the need to upload it!
We are now safe to start the server just like normal!
If you made it to the end, congrats! This was no small feat, and you deserve a pat on the back. Hopefully you learned a lot along the way, and now have an easy way to create game servers, or let your friends create them on their own!
If you have any questions, or see any corrections needed, please leave a comment below, or reach me at contact@n8pete.com.
Other Resources
Here are some other resources you might find helpful during your setup.
YouTube video from lilciv:
https://www.youtube.com/watch?v=cbr8tddvAWw
Official Pterodactyl Panel Documentation:
https://pterodactyl.io/panel/1.0/getting_started.html
Nginx Proxy Manager:
https://nginxproxymanager.com