Troubleshooting
| Symptom | Likely cause | What to check |
|---|---|---|
| The domain stays Pending forever | No queue worker running | Confirm php artisan queue:work is active (supervisor/systemd) |
| "The node hosting this server does not have the domain proxy feature enabled" | Missing NodeProxySetting for that node, or it's enabled=false | Admin → Nodes → (node) → Proxy → check Enabled |
| "Server, node, or allocation not found" | The server has no allocation assigned | Admin → Servers → (server) → Network → assign an allocation |
| "Could not connect to Wings on node [...]" | Wings is down, the binary doesn't have the addon, firewall blocking the daemon's port | curl the / endpoint from the panel to the node (see Wings Installation) |
Nginx error (nginx config test failed) | Port already in use by another vhost, broken syntax in a hand-edited . | Run nginx - directly on the node and read the error detail |
Let's Encrypt fails (certbot failed for .) | Port 80 closed, DNS not yet resolving to the node, Let's Encrypt rate limit reached | dig <domain> should point at the node's IP; confirm port 80 is open; check Let's Encrypt rate limits at https://letsencrypt.org/docs/rate-limits/ |
| "The domain 'x' is already in use on this panel" when recreating a domain that was just deleted | Missing the 2026_ migration, or the panel is running an old version of DomainService/RevokeDomainProxy that did a soft-delete | Confirm the migration ran (php artisan migrate:status) and that DomainService::delete() does a hard delete |
| Cloudflare in "Full" or "Full Strict" mode throws an SSL error at the origin | Outdated manager., missing the self-signed certificate block for cf_ | Verify wings/ is the version included in this package (it generates the self-signed cert + port 443 listener automatically) |
| The panel shows "Wings proxy module status" as red in Admin → Nodes → Proxy | The GET / health check isn't responding | Confirm Wings is compiled with this addon and is running (systemctl status wings) |
| The user doesn't see the "Proxy" tab on their server | They're missing the 3 domain. permissions, or the frontend wasn't rebuilt | Check Permissions; confirm yarn run build:production ran after installing |
| Domain stays Active but visiting it shows something else (another site, a 444 error, nginx's default page) | The node has other server{} blocks on the same port (for example the panel itself running on the same server) and PawProxy's config directory never got included in the main nginx. | Confirm the http {} block in nginx. has include <domains_, see Wings Installation, step 4. Wings validates this automatically after every Apply() (see next row) |
| "nginx accepted and reloaded the config for [...], but it never actually loaded it" | Wings wrote the . and nginx -/nginx - returned no error, but the domain's server_ never showed up in nginx -. Almost always the include line above is missing | Add the missing include to nginx., reload nginx, and try again (delete the domain in error state and create it again). Even better: use the "Test configuration" button in Admin → Nodes → (node) → Proxy before any client creates a domain, so this exact problem gets caught without anyone having to run into it first. |
A domain in None mode works over http:/ but doesn't load (or Cloudflare returns 520) over https:/ | The domain has the orange cloud turned on in Cloudflare, and None doesn't open a listener on 443 on purpose. Cloudflare (or the browser, which by default tries HTTPS first) has nobody to talk to at the origin | If the domain is going to be proxied on Cloudflare, use Cloudflare mode instead of None (it adds the port 443 listener with the self-signed cert Cloudflare needs), or switch that domain's DNS to grey cloud (DNS-only) if you really want plain HTTP |
You updated a . file in the addon (for example after a fix) and the old behavior is still there; changes don't seem to apply to domain jobs | php artisan queue:work (the process behind pteroq) loads classes once at startup and reuses them for every job while it keeps running. Uploading a new file isn't enough if the worker isn't restarted | php artisan queue:restart (tells the worker to finish its current cycle and restart) or systemctl restart pteroq directly. This isn't needed for changes to web-side controllers/routes (those do reload on their own), it's specific to Jobs that run on the queue. |
Where to look at logs
- Panel:
storage/, that's where job exceptions (logs/ laravel. log ApplyDomainProxy/RevokeDomainProxy) land if something breaks before reaching Wings. - Queue: if you run
php artisan queue:workwith-or supervisor, the standard output shows every attempt and its result (remember jobs retry 3 times with backoff before marking the domain as permanently- verbose error). - Wings: the daemon's own logs (
journalctl -or wherever it's configured). That's where errors fromu wings - f nginx -,t nginx -, ands reload certbotshow up with the full command output. - Domain status: the
error_column in themessage server_table (or the tooltip indomains DomainRow.) always has the last error exactly as Wings returned it.tsx
Next: Known limitations →

