Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save TheDevFreak/94b702f4c802fd76e41880ef1da3d9e7 to your computer and use it in GitHub Desktop.

Select an option

Save TheDevFreak/94b702f4c802fd76e41880ef1da3d9e7 to your computer and use it in GitHub Desktop.
Pterodactyl Panel Behind an NGINX Reverse Proxy
Your panel should run on port 80 (well whatever you want I suppose)
Node daemon port should be 443 (but still http) because it hard codes those ports into connection urls for websockets in the webui :/
Ensure you have `TRUSTED_PROXIES=proxyip` in your `/var/www/pterodactyl/.env` file.
server {
listen 443 ssl;
ssl on;
ssl_certificate /path/to/cert/fullchain.pem;
ssl_certificate_key /path/to/cert/key.pem;
server_name panel.domain.tld;
location / {
proxy_pass http://PANELIP_should_be_port_80/;
proxy_set_header Host $host;
client_max_body_size 50m;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_buffering off;
proxy_request_buffering off;
}
}
server {
listen 443 ssl;
ssl on;
ssl_certificate /path/to/cert/fullchain.pem;
ssl_certificate_key /path/to/cert/key.pem;
server_name node1.domain.tld;
location ~ ^\/api\/servers\/(?<serverid>.*)?\/ws$ {
proxy_pass http://node_ip:443/api/servers/$serverid/ws;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
client_max_body_size 50m;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_buffering off;
proxy_request_buffering off;
}
location / {
proxy_pass http://node_ip:443/;
proxy_set_header Host $host;
client_max_body_size 50m;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_buffering off;
proxy_request_buffering off;
}
}
@Catbirby
Copy link
Copy Markdown

Catbirby commented May 6, 2023

Hey there!

I wanted to reach out to mention that this config did not work for me out of the box (namely the panel section.) I was getting continual "400 bad request" errors from Nginx. After setting Nginx to debug mode I found this error
2023/05/06 16:43:04 [info] 1742#1742: *12 client sent duplicate host header: "Host: panel.domain.tld", previous value: "Host: panel.domain.tld" while reading client request headers, client: <ReverseProxy IP>, server: <Server IP>, request: "GET /favicon.ico HTTP/1.0", host: "panel.domain.tld"

What fixed it for me was just commenting out the proxy_set_header Host $host; line, but I am admittedly unsure if this is a real fix or not.

@regix1
Copy link
Copy Markdown

regix1 commented Jul 23, 2023

I'm going to post screenshots for anyone struggling. A lot has changed since this was posted.

I did not leave my FQDN blank, I set it to my node domain name. node1.domain.com
image

This is my general configuration:
image

Inside of my /etc/pterodactyl/config.yml

I changed:
api:
host: Internal IP of Server from Wings not 0.0.0.0
port: 443

You can change these inside of the panel too I just had trouble doing so. You can find your internal server ip on linux with "ip a"

Nginx Config:

server {
  listen 443 ssl http2;
  server_name panel.<domain>.com;

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

  location / {
    proxy_pass http://Internal_IP_of_Server_from_Wings/;
    proxy_set_header Host $host;
    client_max_body_size 50m;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_redirect off;
    proxy_buffering off;
  }
}

server {
  listen 443 ssl http2;
  server_name node1.domain.com;

  ssl_certificate /etc/letsencrypt/live/node1.domain.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/node1.domain.com/privkey.pem;

  location ~ ^\/api\/servers\/(?<serverid>.*)?\/ws$ {
    proxy_pass http://Internal_IP_of_Server_from_Wings:443/api/servers/$serverid/ws;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    client_max_body_size 50m;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_redirect off;
    proxy_buffering off;
  }

  location / {
    proxy_pass http://Internal_IP_of_Server_from_Wings:443/;
    proxy_set_header Host $host;
    client_max_body_size 50m;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_redirect off;
    proxy_buffering off;
  }
}

UPDATE:
To prevent NGINX from showing your local IP. You need to add this to your /etc/pterodactyl/config.yml

Example:
trusted_proxies:

  • 10.0.4.246

This is the IP of my nginx server. Different from where my Panel is run.

@FlowerShopGuy
Copy link
Copy Markdown

FlowerShopGuy commented May 23, 2024

regix1
THANK YOU, IT'S WORKING

Just want to warning someone, your node should have a unic different A record even your node installed on the same IP as the panel, DON'T USE THE SAME DOMAIN NAME for node as for the pterodactyl game panel.
The first time i used same domain name for the panel and for the node and nothing is worked.
Should be.

panel.domain.com - ip: 92.222.100.100
node1.domain.com - ip: 92.222.100.100

@pugly-tech
Copy link
Copy Markdown

what would it look like if I'm using nginx proxy manager?

@regix1
Copy link
Copy Markdown

regix1 commented Jan 15, 2026

what would it look like if I'm using nginx proxy manager?

What do you have so far/tried?

@Dommschwenker
Copy link
Copy Markdown

I can't get Pterodactyl to work behind Nginx Proxy Manager either.

My setup
Domain with @ and * records linked to the VPS IP address

VPS (Proxmox)
Virtual bridge 192.168.111.1/24
UFW on the PVE
UFW Allow Ports 8082/TCP 2022/TCP 25585/TCP 25585/UDP
UFW Forward

-A PREROUTING -i vmbr0 -p tcp --dport 8082 -j DNAT --to-destination 192.168.111.202
-A POSTROUTING -p tcp --dport 8082 -d 192.168.111.202 -j MASQUERADE
-A PREROUTING -i vmbr0 -p tcp --dport 2022 -j DNAT --to-destination 192.168.111.202
-A POSTROUTING -p tcp --dport 2022 -d 192.168.111.202 -j MASQUERADE
-A PREROUTING -i vmbr0 -p tcp --dport 25585 -j DNAT --to-destination 192.168.111.202
-A PREROUTING -i vmbr0 -p udp --dport 25585 -j DNAT --to-destination 192.168.111.202
-A POSTROUTING -s 192.168.111.0/24 -o vmbr0 -j MASQUERADE

LXC-110-Debian13 (IP 192.168.111.110):
Docker + Nginx Proxy Manager
2 proxy hosts: ptero.domain.tld + node1.domain.tld
Scheme http / Port 80 / WebSocket on / SSL cert / SSL on / HTTP/2 on

LXC-202-Debian13 (IP 192.168.111.202):
Pterodactyl Panel + Wing
Application URL in Panel setup: ptero.domain.tld
.env TRUSTED_PROXIES=* added
Web Server Nginx Without SSL replaces server_name with ptero.domain.tld
Wing setup: FQDN node1.domain.tld, SSL Connection, Behind Proxy, Daemon Port 443, SFTP Port 2022

I copied the cert and key from LXC-110 to LXC-202

In config.yml I changed:
host: 192.168.111.202
port: 443
cert: /etc/pterodactyl/fullchain.pem
key: /etc/pterodactyl/privkey.pem
remote: 'https://ptero.domain.tld'

I added the entry in the proxy host for the panel (ptero.domain.tld) under “Advanced”:

location / {
  proxy_pass http://192.168.111.202/;
  proxy_set_header Host $host;
  client_max_body_size 50m;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_redirect off;
  proxy_buffering off;
}

I added the following entry in the proxy host for the node (node1.domain.tld):

  location ~ ^\/api\/servers\/(?<serverid>.*)?\/ws$ {
    proxy_pass http://192.168.111.202:443/api/servers/$serverid/ws;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection “upgrade”;
    proxy_set_header Host $host;
    client_max_body_size 50m;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_redirect off;
    proxy_buffering off;
  }

  location / {
    proxy_pass http://192.168.111.202:443/;
    proxy_set_header Host $host;
    client_max_body_size 50m;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_redirect off;
    proxy_buffering off;
  }

When I start Wing, I get the following error message

DEBUG: [Apr 15 16:50:11.465] making request to external HTTP endpoint endpoint=https://ptero.domain.tld/api/remote/servers?page=0& per_page=50 headers=map[Accept:[application/vnd.pterodactyl.v1+json] Authorization:[(redacted)] Content-Type:[application/json] User-Agent:[Pterodactyl Wings/vv1.12.1 (id:Ro7dVh4I79f67V0e)]] method=GET
FATAL: [Apr 15 16:50:11.488] failed to load server configurations error=http: request creation failed: Get "https://ptero.domain.tld/api/remote/servers?page=0& per_page=50": dial tcp 178.111.111.111:443: connect: connection refused

I have no idea what I'm doing wrong :(

I have updated the domain and the VPS IP in the post. These are correct in the live system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment