I ran Pterodactyl for two years on a customer box at the day job. Two physical machines, around forty game servers, mostly Minecraft and a long tail of "can you spin me up a Valheim real quick" requests. It worked. It was also clearly slowing down — issues piling up, releases getting rarer, and at some point last year it became official: Pterodactyl Panel 1.x stays in maintenance mode, no 2.x is coming.
Around the same time the core developers forked it and started over as Pelican Panel. Same MIT license, same general shape (Panel + Wings daemon + Docker eggs), but a much cleaner stack underneath. I migrated my home box first, then the customer node a few weeks later. No regrets.
This is the ten-minute version, before I forget it.
TL;DR
# On a fresh Ubuntu 24.04 box, with Docker already installed:
mkdir -p /opt/pelican && cd /opt/pelican
curl -fsSL https://github.com/pelican-dev/panel/releases/latest/download/docker-compose.yml -o docker-compose.yml
docker compose up -d
# Then open http://your-server/installer and walk through it.
That's the whole panel. Wings (the daemon that actually runs game containers) gets installed separately on whatever boxes you want to host servers on — covered below. Numbers and exact URL: check the current Pelican docs, the release artifact name has shifted once already.
Pelican vs Pterodactyl in 30 seconds
- Same architecture: Panel (web UI + API) on one box, Wings (daemon) on each game host. Eggs are still JSON, mostly drop-in compatible.
- Different stack under the panel: Pelican uses Filament on top of Laravel 11, which means the admin UI is generated and consistent instead of the bespoke Vue thing Pterodactyl shipped. It feels modern.
- Simpler install: Pelican ships an installer wizard at
/installerand a single-binary-ish Docker image. Pterodactyl wanted you to hand-edit.env, runphp artisanmigrations, set up queues, redis, supervisor, the works. Pelican does all that for you on first boot. - SQLite is a real option for small deployments. Pterodactyl basically required MariaDB + Redis. Pelican will happily run on SQLite for a homelab; switch to MariaDB when you actually need it.
- Wings is still Wings. They kept the daemon name and the egg format on purpose so migrating doesn't mean throwing out years of community eggs.
- Active. That's the real one. Issues get answered. Releases ship.
Install Pelican Panel on Ubuntu 24.04 (Docker)
I'm picking the Docker compose path because it's what I run in production now and it's genuinely less painful than the native PHP install. The native path (PHP 8.3, nginx, php-fpm, redis, mariadb, queue worker, scheduler cron) still works if you're allergic to Docker, and the docs cover it — but I've stopped doing it that way.
Prereqs:
- Ubuntu 24.04, fresh
- Docker Engine + compose plugin (see /nginx-reverse-proxy-setup/ if you also need to put nginx in front)
- A DNS name pointing at the box (
panel.example.com) - UFW configured (I have a separate post on /ufw-firewall-rules-ubuntu/)
sudo mkdir -p /opt/pelican
cd /opt/pelican
sudo curl -fsSL \
https://github.com/pelican-dev/panel/releases/latest/download/docker-compose.yml \
-o docker-compose.yml
Open the compose file. You'll want to set a volume for /pelican-data (so SQLite + uploads + config survive container restarts) and pin a port. Defaults bind to :80 on the host, which is fine if the box does nothing else, otherwise change it to :8080 and put nginx in front.
sudo docker compose up -d
sudo docker compose logs -f app
When the container is healthy, hit http://your-server/installer in a browser. The wizard asks you for:
- DB driver (SQLite for a homelab, MariaDB for "real")
- Cache/queue driver (file is fine for small, redis for larger)
- Admin user
- App URL — set this to the final
https://panel.example.com, not the IP, otherwise you'll be regenerating later
For TLS, terminate with nginx + Let's Encrypt in front of the panel container. The reverse-proxy walkthrough is in /nginx-reverse-proxy-setup/; the Pelican-specific bit is just "proxy_pass to whatever port you bound the panel container to, set X-Forwarded-Proto https."
Install Wings (the daemon)
Wings runs on every host that should actually run game servers. Can be the same box as the Panel; can be ten boxes spread across racks. Pelican still ships it as a single Go binary.
# On the Wings host:
sudo mkdir -p /etc/pelican /var/lib/pelican /var/log/pelican
sudo curl -L -o /usr/local/bin/wings \
"https://github.com/pelican-dev/wings/releases/latest/download/wings_linux_amd64"
sudo chmod +x /usr/local/bin/wings
Docker has to be installed and running on the Wings host — that's how game servers actually get sandboxed. If you don't have it yet, install it the normal way (get.docker.com script or distro packages). Wings talks to the Docker socket.
In the Panel UI: Admin → Nodes → Create Node. Fill in FQDN, ports (default daemon port 8080, SFTP 2022), allocate disk and memory. Once saved, click Configuration on the node and copy the generated YAML to the Wings host:
sudo nano /etc/pelican/config.yml
# paste, save
Run it:
sudo wings --debug
If the panel goes green and SFTP comes up on :2022, kill the foreground process and create a systemd unit (the docs ship one, drop it in /etc/systemd/system/wings.service):
sudo systemctl enable --now wings
sudo systemctl status wings
First node, first server
The eggs are the part that hasn't really changed. From the admin panel: Eggs → Import and grab a Paper egg from the community repo (the pelican-eggs org on GitHub mirrors most of what parkervcp/eggs had for Pterodactyl, and a lot of the old eggs still import cleanly).
Then Servers → Create:
- Owner: yourself
- Node: the one you just registered
- Allocation: pick a free
ip:port(e.g.0.0.0.0:25565) - Egg: Paper
- Memory/CPU/Disk: 4 GB / 200% / 10 GB is a sensible Paper baseline
- Startup: leave defaults, set MC version to
1.21.4or whatever you actually want
Hit create. Wings pulls the Java image, downloads the Paper jar, accepts the EULA when you toggle the variable, and you've got a running server in about 90 seconds.
If you want to compare what the panel is doing under the hood against the manual approach, my manual Minecraft Java server on Linux post walks through the same end state without any panel — useful for understanding what Wings is actually doing and what to look at when something breaks.
Migration thoughts if you're on Pterodactyl
I did one in-place migration and one rebuild-from-scratch.
Rebuild-from-scratch is faster. Stand up Pelican on a fresh box, import your eggs, recreate servers, rsync the world files / save directories from the old Wings host into the new server's volume on the new Wings host, fix permissions, done. For forty servers it took me an afternoon.
In-place migration (Pelican now has a migration tool that reads a Pterodactyl database and ports users, nodes, servers, allocations) works but you need to be on a recent Pterodactyl 1.x and you need MariaDB on both sides. I'd only do it if you have hundreds of servers or sensitive user accounts you can't recreate. Otherwise, fresh box.
Either way: read the current Pelican migration docs before starting. The tool has changed twice since release.
Gotchas
Stuff that actually bit me:
- Egg compatibility is "mostly". Old
parkervcpeggs that shell out to weird scripts sometimes assume Pterodactyl-specific env vars. Re-import frompelican-eggsinstead of the old repo when there's a Pelican-side fork available. Modded Minecraft (Forge/NeoForge) eggs in particular got cleaned up. - Port conflicts on multi-server boxes. Wings allocations are per-IP, and if you've got the panel on
:80and Wings's SFTP on:2022and twenty Minecraft servers between25565–25585, sooner or later you'll allocate8080to a server and Wings will silently refuse to start it. Reserve a clean range in UFW and stick to it. - Docker permissions. Wings has to be able to talk to
/var/run/docker.sock. If you run Wings as a non-root user, it has to be in thedockergroup. Symptom: server creates fine, install fails withpermission denied while trying to connect to the Docker daemon socket. - Reverse-proxy and websockets. The console in the panel uses websockets to Wings on the daemon port. If you're proxying both panel and daemon through nginx, make sure the daemon vhost has
proxy_http_version 1.1,Upgrade/Connectionheaders, and a longproxy_read_timeout(I use 7200s). Without it the console just shows nothing and you'll think Wings is broken. It isn't. - Let's Encrypt on the daemon. Wings wants a real cert for the SFTP/daemon endpoint, not just the panel. Easiest path: a separate
node1.example.comDNS record, certbot for both, point Wings at the cert files inconfig.yml. - SQLite isn't free. It's fine for a personal box. The moment you have multiple admins clicking around or you cross ~30 servers, switch to MariaDB. The
php artisan db:migrate-to-mysql-style tooling exists in the panel, check the docs for the current command name.
Why I switched
Honestly, because Pterodactyl stopped feeling alive and Pelican does. The Filament admin is nicer to look at. The installer wizard means I can stand a panel up in fifteen minutes instead of an hour. SQLite mode means my homelab Pelican isn't running a whole MariaDB just to track three Minecraft servers. And the eggs I care about — Paper, Velocity, Forge, Valheim, Satisfactory — all work.
The day-job side matters too. I don't want to be the guy still running an unmaintained panel in front of customer game servers in 2027. Pelican is the path forward that doesn't involve me writing my own panel, and that's the one I'm picking.
If you're on Pterodactyl right now and it's working fine: no rush. 1.x will keep going for a while. But the next time you spin up a new node, do it on Pelican. You'll save yourself the migration later.