SSL Modes

None

HTTP only on port 80. No certificate management of any kind, on purpose, no listener is opened on 443. Useful for quick tests or strictly internal services where encryption doesn't matter.

nginx
server {
    listen 80;
    server_name mysite.com;
    location / {
        proxy_pass http://<forward_host>:<forward_port>;
        ...
    }
}

Watch out for domains behind Cloudflare with the orange cloud turned on. If the domain is proxied on Cloudflare (even if that mode isn't used here), Cloudflare, and almost any modern browser by default, will try to connect over HTTPS. Since this mode has nothing listening on 443, that returns an error (520 from Cloudflare, or the browser simply won't load the page). If the domain has the orange cloud turned on, use Cloudflare mode instead of None, even if you don't care about issuing any real certificate: it's the mode that adds the port 443 listener Cloudflare needs to talk to the origin. Reserve None for domains with no proxy of any kind (DNS-only / grey cloud).

Cloudflare (orange-cloud)

The user turns on the orange cloud on the DNS record inside Cloudflare. Wings writes:

  • Port 80: normal proxy_pass, trusting the headers Cloudflare sends (CF-Connecting-IP for the visitor's real IP, X-Forwarded-Proto inherited from Cloudflare).
  • Port 443 with a self-signed certificate generated locally by Wings (ECDSA P-256, valid for 10 years, regenerated only if fewer than 30 days remain before expiry).

This second listener on 443 is key: it lets Cloudflare work in Full or Full (Strict) mode, which are the default/recommended modes on Cloudflare today, without the user having to upload or manage any certificate. In Flexible mode (Cloudflare talks plain HTTP with the origin) that second listener simply isn't used, but it doesn't hurt that it exists.

If your Cloudflare is in Flexible mode and you're seeing "too many redirects" errors, that's a Cloudflare configuration issue (a conflict between flexible mode and a redirect-to-HTTPS on the origin), not this addon.

Let's Encrypt

Requirements: port 80 open on the node and the domain's DNS record already resolving to the node's IP (certbot can't complete the challenge if DNS hasn't propagated).

Internal flow:

  1. Wings first writes an HTTP-only block (same as None mode).
  2. certbot certonly --nginx -d <domain> --non-interactive --agree-tos -m <email>: this only issues the certificate, it doesn't touch the nginx configuration (unlike the typical use of certbot --nginx, certonly is used here on purpose).
  3. Wings rewrites the .conf with the full SSL block: a 301 redirect from 80 to 443, and the server { listen 443 ssl; ... } block pointing at /etc/letsencrypt/live/<domain>/fullchain.pem and privkey.pem.
  4. nginx -t && nginx -s reload.

Certificate renewal is handled by certbot's own cron/systemd-timer that already runs on the node outside the addon; the addon doesn't manage or monitor it. If certbot isn't renewing correctly at the system level, that's an issue with that installation, not PawProxy.

If certificate issuance fails (for example DNS not resolved yet), the domain keeps working over HTTP and the error is stored in error_message. The proxy doesn't go down, it just doesn't have HTTPS yet.

Custom (own certificate)

The user pastes their own certificate and private key (PEM), useful if they already have a wildcard, EV, or other-CA certificate and don't want to depend on Let's Encrypt.

Flow:

  1. On "Add Domain", Custom certificate mode → two text fields appear: certificate (full chain, PEM) and private key (PEM).
  2. The panel stores both encrypted in the database (Laravel's encrypted cast, using the panel's APP_KEY). They're never returned by the API once saved, not even to the same user who uploaded them.
  3. ApplyDomainProxy sends them to Wings only when ssl_mode = custom.
  4. proxy/manager.go writes them to /etc/nginx/ssl/pawproxy/<domain>/{fullchain,privkey}.pem (permissions 0600) and builds the listen 443 ssl block pointing there.
  5. When the domain is deleted, Revoke() removes that folder along with the rest of the cleanup.

Requires the node to have "User-supplied certificate" set to Allowed (Admin → Nodes → (node) → Proxy). If it's Blocked, creation fails with "Custom SSL certificates are not enabled for this node." before it ever reaches Wings.

There's no automatic renewal: if the pasted certificate has an expiry date, it's the user's responsibility to upload it again (delete the domain and create it again) before it expires.

Next: Troubleshooting →