Troubleshooting

SymptomLikely causeWhat to check
The domain stays Pending foreverNo queue worker runningConfirm 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=falseAdmin → Nodes → (node) → Proxy → check Enabled
"Server, node, or allocation not found"The server has no allocation assignedAdmin → 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 portcurl the /api/proxy/health 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 .confRun nginx -t 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 reacheddig <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 deletedMissing the 2026_05_29_000001_fix_server_domains_unique_index.php migration, or the panel is running an old version of DomainService/RevokeDomainProxy that did a soft-deleteConfirm 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 originOutdated manager.go, missing the self-signed certificate block for cf_proxiedVerify wings/new-files/proxy/manager.go 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 → ProxyThe GET /api/proxy/health health check isn't respondingConfirm Wings is compiled with this addon and is running (systemctl status wings)
The user doesn't see the "Proxy" tab on their serverThey're missing the 3 domain.* permissions, or the frontend wasn't rebuiltCheck 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.confConfirm the http {} block in nginx.conf has include <domains_path>/*.conf;, 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 .conf and nginx -t/nginx -s reload returned no error, but the domain's server_name never showed up in nginx -T. Almost always the include line above is missingAdd the missing include to nginx.conf, 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 originIf 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 .php file in the addon (for example after a fix) and the old behavior is still there; changes don't seem to apply to domain jobsphp 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 restartedphp 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/logs/laravel.log, that's where job exceptions (ApplyDomainProxy/RevokeDomainProxy) land if something breaks before reaching Wings.
  • Queue: if you run php artisan queue:work with --verbose or supervisor, the standard output shows every attempt and its result (remember jobs retry 3 times with backoff before marking the domain as permanently error).
  • Wings: the daemon's own logs (journalctl -u wings -f or wherever it's configured). That's where errors from nginx -t, nginx -s reload, and certbot show up with the full command output.
  • Domain status: the error_message column in the server_domains table (or the tooltip in DomainRow.tsx) always has the last error exactly as Wings returned it.

Next: Known limitations →