How to Install Pelican Game Panel in Docker (2026)
Install Pelican Panel and Wings with the official Docker images behind Nginx Proxy Manager, then launch and connect to your first Minecraft server.
On this page 9 sections
Over time, the official documentation for running Pelican in Docker has evolved and become simpler, and the maintainers always publish an official Docker image for each release that we can use instead of building the images ourselves.
Assumptions
In order to keep this guide relatively concise, we need to assume a few things about your setup.
- You’re running a Debian-based Linux distro (Ubuntu) with Docker installed and apt packages updated
- You have familiarity with Docker and Docker Compose
- You own a Domain name and have your reverse proxy set up to hand out wildcard SSL certificates. We will use Nginx Proxy Manager (NPM) in this guide, but similar concepts apply to other reverse proxies. It is best if the reverse proxy is running on a different machine or VM on your network than where Pelican will be running.
Getting Started
The first part of this guide will be setting up and configuring the Pelican Panel web interface. The panel is where you will manage your game servers, and it also serves as the central hub for your Wings nodes to connect to. The panel will be running in a Docker container, and we will use Docker Compose to manage the stack. The second part of the guide will be setting up a Wings node, which is the service that actually runs your game servers. Wings will also be running in a Docker container on the same machine as the panel, but it could also be run on a different machine if you wanted to distribute your nodes across multiple servers.
- SSH into your debian-based linux machine on which to install Pelican
- Make a pelican directory in home folder with
mkdir ~/pelican && cd ~/pelican - Create a Docker Compose file in the pelican directory with
touch ~/pelican/docker-compose.ymland paste the following contents, replacing<YOUR_EMAIL_HERE>with your email address,<YOUR_NPM_IP_ADDRESS>(e.g. 192.168.1.100) with the IP address of your reverse proxy, and<YOUR_HTTPS_PANEL_URL_HERE>with the HTTPS URL of your panel (e.g., https://pelican.local.example.com).
services: panel: image: ghcr.io/pelican/panel:latest container_name: pelican_panel restart: always networks: - default ports: - "80:80" extra_hosts: - "host.docker.internal:host-gateway" volumes: - pelican-data:/pelican-data - pelican-logs:/var/www/html/storage/logs - ./Caddyfile:/etc/caddy/Caddyfile environment: XDG_DATA_HOME: /pelican-data APP_URL: "<YOUR_HTTPS_PANEL_URL_HERE>" ADMIN_EMAIL: "<YOUR_EMAIL_HERE>" BEHIND_PROXY: "true" TRUSTED_PROXIES: "<YOUR_NPM_IP_ADDRESS>"
volumes: pelican-data: pelican-logs:
networks: default: ipam: config: - subnet: 172.20.0.0/16Then create a Caddyfile in the same directory ~/pelican/Caddyfile (no file extension) with the following contents, replacing <YOUR_NPM_IP_ADDRESS> with the IP address of your reverse proxy. The Caddyfile is used to configure the web server that serves the Pelican panel. We need to tell Caddy to trust our reverse proxy so that it can properly handle requests and forward them to the panel
{ admin off servers { trusted_proxies static <YOUR_NPM_IP_ADDRESS> }}
:80 { root * /var/www/html/public encode gzip
php_fastcgi 127.0.0.1:9000 { env PHP_VALUE "upload_max_filesize = 512M post_max_size = 512M" } file_server}Accessing the Panel
Start the Docker Compose stack with docker compose up -d. Note: You may need to prefix your docker commands with sudo if your user is not in the docker group
View the logs with docker logs -f pelican_panel to check for errors at any point if you’re having trouble.
Since we are using NPM as a reverse proxy to access our panel at a custom domain, we need to add a “Proxy Host” entry in NPM pointing at our server. As seen in the compose file, we are exposing ports 80 and 443 for HTTP and HTTPS traffic, respectively.
In NPM, add a new Proxy Host with the following settings:
- Domain Names:
<YOUR_HTTPS_PANEL_URL_HERE>(same as the APP_URL in the compose file, without the https:// prefix. e.g.pelican.local.example.com) - Scheme: http
- Forward Hostname/IP: 192.168.1.XXX (IP of your Pelican server)
- Forward Port: 80
- Websockets Support: Enabled
- Block common exploits: Enabled
- SSL Tab -> Select your certificate for the domain and check “Force SSL” and “HTTP/2 Support”


Setup Steps
Then navigate your browser to the domain you set up in NPM with the path /installer appended and you should see the Pelican panel login page (e.g. https://pelican.local.example.com/installer).
Click your way through all of the screens. Most should be self explanatory and not need changing, but I do have a couple notes.
- On the “Environment” step, be sure to enter the same email address you put for
ADMIN_EMAILin the compose file earlier - On the “Eggs” step you choose the ones associated with the game [types] you are interested in creating servers for. For example, under the Minecraft tab I would choose “Fabric”, “Vanilla Bedrock”, and “Vanilla Minecraft”
- After clicking “Finish” on the last step, it will take a couple minutes to set everything up in the background. If you see an error message about creating the admin user, try restarting your Docker compose stack and visiting the panel URL again
Congratulations! You’ve successfully installed the Pelican panel in Docker. You can click through the tabs on the left and get familiar with the interface and settings. Next, we will set up a Wings node to run our first Minecraft server!
(Note: If your Health tab has an error about the Database, Queue, or Schedule, don’t worry - it should go away in a few minutes once the panel finishes setting up the database and runs the health checks again.)
Setting up a Wings Node
The official Pelican Wings documentation doesn’t have instructions for running Wings in Docker, but it’s actually very simple to set up. We will modify our Docker Compose file to add a new service for Wings.
Update your docker-compose.yml file to look like this, replacing <YOUR_EMAIL_HERE> with the same email address from the Panel, <YOUR_NPM_IP_ADDRESS> with the IP address of your Reverse Proxy, and <YOUR_HTTPS_PANEL_URL_HERE> with the HTTPS URL of your panel (e.g., https://pelican.local.example.com).
services: panel: image: ghcr.io/pelican/panel:latest container_name: pelican_panel restart: always networks: - default ports: - "80:80" extra_hosts: - "host.docker.internal:host-gateway" volumes: - pelican-data:/pelican-data - pelican-logs:/var/www/html/storage/logs - ./Caddyfile:/etc/caddy/Caddyfile environment: XDG_DATA_HOME: /pelican-data APP_URL: "<YOUR_HTTPS_PANEL_URL_HERE>" ADMIN_EMAIL: "<YOUR_EMAIL_HERE>" BEHIND_PROXY: "true" TRUSTED_PROXIES: "<YOUR_NPM_IP_ADDRESS>"
wings: image: ghcr.io/pelican/wings:latest container_name: pelican_wings restart: unless-stopped networks: - wings0 ports: - "2022:2022" - "8080:8080" environment: TZ: "UTC" WINGS_UID: 998 WINGS_GID: 998 WINGS_USERNAME: pelican volumes: - "/var/run/docker.sock:/var/run/docker.sock" - "/var/lib/docker/containers/:/var/lib/docker/containers/" - "/etc/pelican/:/etc/pelican/" - "/var/lib/pelican/:/var/lib/pelican/" - "/var/log/pelican/:/var/log/pelican/" - "/tmp/pelican/:/tmp/pelican/" - "/etc/ssl/certs:/etc/ssl/certs:ro"
volumes: pelican-data: pelican-logs:
networks: default: ipam: config: - subnet: 172.20.0.0/16
wings0: name: wings0 driver: bridge ipam: config: - subnet: 172.21.0.0/16 driver_opts: com.docker.network.bridge.name: wings0Restart the stack with docker compose down && docker compose up -d. Both the Panel and Wings containers should start up. If you check the Panel logs with docker logs -f pelican_panel, you should not see any errors, but when you check the Wings logs with docker logs -f pelican_wings you will see the below error:
This is completely normal, as the Wings container is looking for its configuration file, but we haven’t set up the node in the panel yet so the config file hasn’t been generated. Let’s fix that now!
Create a Proxy Host in NPM for the Wings node with the following settings:
- Domain Name:
wings.local.example.com - Scheme: http
- Forward Hostname/IP: 192.168.1.XXX (IP of your Pelican server)
- Forward Port: 8080
- Websockets Support: Enabled
- SSL Tab -> Select your certificate for the domain and check “Force SSL” and “HTTP/2 Support”


Then navigate to the Nodes tab in the Pelican panel and click “Create Node”. Fill out the form with the following settings:
- Domain name:
wings.local.example.com(same as the domain you set up in NPM, no https:// prefix) - Display Name:
wings node 1(or whatever you want to call it) - Communication of SSL: “HTTPS with (reverse) proxy”
- Connection Port: 443
- Listening Port: 8080
Click the Forward arrow in the bottom right, then update any Advanced Settings you’d like. Note that the “Upload Limit” cannot exceed what was set in the Caddyfile for the panel (512M in our case). It might be beneficial to set Memory, Disk, and CPU limits if your server’s resources are shared with other services. Click ”+ Create Node” when you’re done.
The next screen will provide you with your config.yml file. Copy and paste them into a new file on your server at /etc/pelican/config.yml. This file is not in our main ~/pelican directory because the location must match the same path as inside the Wings container, which is also /etc/pelican/config.yml. This is already defined as a bind-mount in our docker-compose.yml file.
Note: Depending on when/how the /etc/pelican directory was created, it may require elevated privileges to create the config.yml file inside of it. If you get a “Permission denied” error in your terminal, run sudo chown $USER /etc/pelican to change its ownership to you. Then you can run touch /etc/pelican/config.yml without issue.
Restart your Docker stack again with docker compose down && docker compose up -d and check the Wings logs with docker logs -f pelican_wings. You should see that Wings has successfully connected to the panel. The most important part is the “Green Heart” shown in the Nodes tab of the panel, which indicates that the node is healthy and connected to the panel. If you don’t have the green heart, resolve that before continuing!
If you’re still getting a red heart, be sure to check your NPM proxy host entry is pointing to the correct IP address and port of your server, AND that the token_id and token lines in config.yml match the ones inside the Node “Configuration File” tab.
Setting up our first Minecraft server
Now that we have our Wings node set up and connected to the panel, we can create our first Minecraft server! There are two small things we need to take care first: provisioning Port Allocations and importing an Egg for Minecraft servers.
For the port allocations, edit your Node and find the Allocations section at the bottom of the “Basic Settings” tab.
A window will pop up to “Create new allocation”. In the “IP Address” dropdown, choose 0.0.0.0. Then in the “Ports” field, enter a range of ports that you want to use for your Minecraft servers. For example, you could enter 25560-25569 to allocate 10 ports for Minecraft servers. Click “Submit” when you’re done.
Then we need to add a Game Egg. Go to the Eggs tab on the left side menu. You will see some listed here if you chose some during the panel installation step. If you want to add more, choose the Import button in the top-left.
Now for the fun part! Go to the “Servers” tab in the panel and click “New Server”.
Give the server a name, ensure your Node is selected, then choose a port allocation from the dropdown (one of the ports you allocated earlier). Then click “Next” in the bottom right.
Choose your Egg from the dropdown (the one you imported earlier) and click “Next” in the bottom right. No other settings on this step should need to be changed.
Set server-specific environment variables if you’d like, but for a basic Minecraft server, there is no need to change anything here. Click “Create Server” in the bottom right.
If all goes well, you’ll see the server “Installing”! Go back to the “Servers” tab on the left sidebar, then click the “View Console” button on the server to see the startup status.
If it doesn’t start automatically, click the “Start” button!
Accept Minecraft’s EULA.
Congratulations! Your Minecraft server is now up and running with Pelican in Docker!
Connecting to your Server
There are a few situations where you might want to connect to your server, and each has some details specific to it.
1. Connecting from LAN using IP address
This is already working! You can connect to your server on your LAN (home network) using the Pelican server’s IP address and the port you allocated (e.g., 192.168.1.50:25565).
2. Connecting from WAN using IP address
This requires forwarding the server port on your router (Google your router’s model for detailed instructions) from the WAN to your Pelican server address.
For a general overview, log into your router’s admin panel (e.g. http://192.168.1.1) and go to the Port Forwarding section (might be under Advanced settings).
Then you will need to add an entry here along the lines of:
“Forward traffic from WAN on port 25565 (or whichever port you want) to my server on LAN IP 192.168.1.50 on port 25565”.
Save that, then you will need to find your WAN public IP address (whatismyip.com works great for this) and give it to whomever you want to connect to your server. They will open Minecraft and connect to XX.XX.XX.XX:25565 where the XX... is replaced by your public IP.
Note that you might not be able to connect to your server from that same address while on your LAN. Many routers don’t support NAT loopback (also called NAT hairpinning), which is when a request from inside your network goes out to your own public IP and back in. Instead, use the LAN IP address from situation #1 above.
3. Connecting from LAN using FQDN
This section is about connecting to your server with a Fully Qualified Domain Name (FQDN) like minecraft.local.example.com instead of an IP address.
How DNS resolution works
When you type an FQDN into Minecraft, your PC first has to turn it into an IP address. It asks your router (or Pi-hole/AdGuard Home, if your router uses one as its DNS server). The router checks its own local DNS entries first. It only finds a match if someone has added an “A” or “CNAME” record there. If there’s no match, it asks upstream DNS servers like Google, Cloudflare or Quad9, which know every public FQDN on the internet. That’s how www.google.com gets resolved to one of Google’s servers.
So to use an FQDN on your LAN, we add a local DNS record that points the name at a machine on your network.
Adding the DNS record
Like the port forwarding section above, you’ll probably need to Google your router’s model for exact steps. In general, log into your router’s admin panel (e.g. http://192.168.1.1) and find the DNS Server section (it might be under Advanced settings).
Add an entry along the lines of:
“Domain Name (‘A’ Record): minecraft.local.example.com -> LAN IP: 192.168.1.50 (Pelican server)”
That’s it! Connect in Minecraft with minecraft.local.example.com:25565. The DNS record handles the name and the port goes straight to Wings, so no proxy is involved.
Alternative: Reusing an FQDN pointed to NPM
If you already have a DNS record (wildcard or individual) that points to Nginx Proxy Manager, the name resolves to NPM’s IP rather than Pelican’s. In that case, NPM has to pass the game traffic along to Pelican. Normal Proxy Hosts in NPM only handle HTTP, while Minecraft uses raw TCP (and UDP for voice chat), so we need a Stream.
In NPM, create a new Stream under “Hosts -> Streams” and enter the following details:
| Field | Value | Note |
|---|---|---|
| Incoming Port | 25565 | Whichever port your server is on |
| Forward Host | 192.168.1.50 | Pelican server IP |
| Forward Port | 25565 | Same as above |
| TCP Forwarding | Yes | |
| UDP Forwarding | Yes | Used for MC voice chat |

Repeat this for every port allocation you use in Pelican. NPM doesn’t support port ranges yet. The underlying Nginx can do it, but there’s an open GitHub issue tracking it in NPM.
If NPM runs in Docker, you’ll also need to map each port onto the container:
ports: - 80:80 # Existing NPM port - 81:81 # Existing NPM port - 443:443 # Existing NPM port - 25559:25559 # Game server port - 25560-25570:25560-25570 # Game server port rangesYour DNS record should point to NPM’s IP (e.g. minecraft.local.example.com -> 192.168.1.100), not Pelican’s.
If you use a wildcard record like *.local.example.com, keep in mind that any subdomain will reach your server on that port. For example, scoobydoo.local.example.com:25565 works too. If you don’t want that, create a separate record for each subdomain instead of a wildcard.
4. Connecting from WAN using FQDN
This is the final method I will cover and it’s the holy grail of what I was chasing when trying to create a Minecraft server when I was 13. All the public servers I used to play had super clean URLs like minecraft.example.com and it seemed like magic to me. Fast forward to the late 2020s and we’ve cracked the code!
The process here is pretty simple and combines the LAN FQDN method and WAN IP methods from earlier. Here are the steps:
- Create a DNS (“A”) record in your cloud domain provider (the place you bought example.com from) and point it to your WAN (public) IP address
- Forward your server ports on your home router to your Pelican server (e.g. WAN 25565 -> LAN 192.168.1.50:25565)
This is the same idea as the LAN DNS record from section 3, except the record lives at your public domain provider and points to your public IP.
And you’re done! Similar to the WAN IP method, you might not be able to connect to this address from a device on your LAN. Many routers don’t support NAT loopback (also called NAT hairpinning or NAT reflection), which is when a request from inside your network goes out to your own public IP and back in. You can work around this with a local DNS override (the same LAN DNS record from section 3), so the same FQDN resolves to 192.168.1.50 at home and to your public IP everywhere else.
Updating Pelican
Since we’re using the official images, updating Pelican is just a matter of pulling the newest images and recreating the containers. There’s no need to clone repositories or build anything ourselves.
Panel and Wings releases are usually published around the same time, and running the latest version of both is recommended. You can follow new releases here: Panel, Wings.
1. Back up your data
Before updating, it’s a good idea to back up your data and skim the release notes for any breaking changes. If something goes wrong, a backup lets you roll back instead of starting over.
The two things worth backing up are:
- Panel: the
pelican-dataDocker volume, which holds the database and configuration - Wings: the
/etc/pelicandirectory, which holds the node configuration
If your server runs in a virtual machine (e.g. on Proxmox), the easiest option is to take a snapshot of the VM before updating.
2. Pull the new images and restart
cd ~/pelicandocker compose pull # Download the newest panel and wings imagesdocker compose up -d # Recreate any containers whose image changedDocker Compose only recreates the containers that have a new image, so this command is safe to run even if only one of them was updated.
Once everything is running, you can delete the old images to free up disk space:
docker image prune3. Verify the update
Check that both containers are running and watch the Panel logs for errors:
docker compose psdocker logs --follow pelican_panelThen log into the Panel, go to the “Nodes” tab, and make sure your node still has a green heart. If it shows a red heart, check the Wings logs with docker logs --follow pelican_wings.
If something broke, read the release notes for the version you updated to. Breaking changes and the steps to fix them are usually listed there. You can also search the Pelican Discord server for others who hit the same issue.
Final Thoughts
Congratulations on setting up your Pelican game server! It is an amazing application to use once you’re able to get it running and I’m grateful to put this post out into the world to help other struggling homelabbers and gamers.
If you’re still in need of assistance, join the Pelican Discord server and search the community support forum. They are more than willing to help, but know that they only officially support their own installation guides and won’t be able to help fix issues encountered while following my guide here. I try to follow as close to the official docs as possible and to update this regularly, but running Wings in Docker and using NPM are not approaches they support.
If you have questions for me, you can find my contact information in the footer of this site.
Thank you for joining me in this journey of hosting Minecraft servers at home. The process has been long and arduous but is worth it in the end. Have a great day!