VPS Tutorials
Cloudflare 521 / 522 on a VPS Website: What to Do (2026): Origin, Firewall, and Nginx Timeout Troubleshooting
After a VPS website is put behind Cloudflare, a 521 Web Server Is Down or 522 Connection Timed Out error usually does not mean Cloudflare itself is broken. More often the origin refuses connections, nothing is listening on 80/443, a firewall or security group is blocking traffic, Nginx/Apache/Caddy is not running, the origin is overloaded, origin-pull IPs are blocked, or the TLS/proxy configuration does not match. This article troubleshoots layer by layer, starting from the difference between 521 and 522, then curl to the origin, Cloudflare IPs, Nginx logs, firewalls, and timeouts.

When a 521 or 522 appears on a Cloudflare page, many people's first reaction is: is Cloudflare down?
Most of the time, it is not.
Both errors happen at the step where Cloudflare connects back to your VPS origin, but they mean different things:
- 521 Web Server Is Down: Cloudflare reached the origin IP, but the origin refused the connection or the web service is not up.
- 522 Connection Timed Out: Cloudflare tried to connect to the origin but the connection timed out, usually a network, firewall, load, or origin-pull path problem.
Put simply: 521 is more like "the door is closed"; 522 is more like "knocked and nobody answered."
Do not treat every Cloudflare 5xx as the same thing.
| Error | Common meaning | Check first |
|---|---|---|
| 521 | Origin refuses connection / web service not listening | Nginx/Apache/Caddy, 80/443 listening, firewall rejection |
| 522 | Cloudflare-to-origin connection timed out | Security group, UFW, origin load, routing, timeout |
| 523 | Cloudflare cannot find a route to the origin | Origin IP, DNS, routing issues |
| 525 | SSL handshake failed | Cloudflare SSL mode, certificate, TLS configuration |
| 526 | Origin certificate invalid | Under Full strict, the certificate is untrusted or expired |
This article covers only the most common 521 and 522. For certificate renewal failures, see: What to Do When Let's Encrypt Certificate Renewal Fails on a VPS.
First confirm whether your VPS origin itself is reachable.
If you know the origin IP:
curl -I http://源站IP
curl -I https://源站IP
If the site depends on the Host header, use:
curl -I http://源站IP -H 'Host: example.com'
curl -I https://源站IP -H 'Host: example.com' -k
If even a direct connection fails, the problem is at the origin, not at Cloudflare.
Common results:
Connection refused: the service is not listening or the connection was refused, more like 521.Connection timed out: firewall, security group, routing, or the origin is stuck, more like 522.SSL certificate problem: check the certificate or Cloudflare SSL mode.- Reachable directly but not through Cloudflare: focus on whether Cloudflare origin-pull IPs are being blocked.
On the VPS, run:
sudo ss -lntp | egrep ':80 |:443 '
You should see Nginx, Apache, Caddy, or your application listening.
If nothing is listening:
sudo systemctl status nginx --no-pager
sudo systemctl status apache2 --no-pager
sudo systemctl status caddy --no-pager
Check the logs:
sudo journalctl -u nginx -n 100 --no-pager
sudo journalctl -u apache2 -n 100 --no-pager
sudo journalctl -u caddy -n 100 --no-pager
If Nginx reload fails, the configuration has a syntax error, or the certificate path is wrong, Cloudflare may see a 521. For Nginx configuration troubleshooting, see: What to Do When Nginx Configuration Is Wrong on a VPS.
Local firewall:
sudo ufw status verbose
sudo iptables -S
sudo nft list ruleset
If using firewalld:
sudo firewall-cmd --list-all
At minimum, allow 80 and 443:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
But allowing ports in the system firewall is not enough. Also check the cloud provider's security group / firewall:
- Is inbound 80/tcp allowed?
- Is inbound 443/tcp allowed?
- Did you allow only your own IP but not Cloudflare origin-pull IPs?
- Is there a region, route, or DDoS policy blocking traffic?
Cloudflare origin pull does not access the origin from your local computer; it accesses your VPS from Cloudflare's edge nodes. The fact that you can reach it locally does not mean Cloudflare can.
Many people install Fail2Ban, a WAF, Nginx deny rules, or a cloud firewall and then block Cloudflare origin-pull IPs as suspicious traffic.
First check the Nginx access/error log:
sudo tail -n 100 /var/log/nginx/access.log
sudo tail -n 100 /var/log/nginx/error.log
If you see no Cloudflare requests at all, they may be blocked before reaching the system firewall or security group.
If you see requests but they return 403/444/499/5xx, check Nginx, the application, or WAF rules.
In Fail2Ban scenarios, check:
sudo fail2ban-client status
sudo fail2ban-client status sshd
If you restrict origin access by IP allowlist, remember to use Cloudflare's officially published IP ranges and keep them updated. Do not hand-write a few old IP ranges and leave them unattended long-term.
522 does not necessarily mean the port is closed. It is more commonly a timeout while Cloudflare establishes a connection to the origin.
Check load on the VPS:
uptime
free -h
df -h
top
Check disk I/O:
iostat -x 1
Check Nginx / application logs:
sudo journalctl -u nginx -n 100 --no-pager
sudo tail -n 100 /var/log/nginx/error.log
If origin CPU, memory, and disk I/O are all high, Cloudflare connections may time out. For high disk I/O, see: What to Do When VPS Disk I/O Is Very High.
Common causes:
- PHP-FPM / Gunicorn / Node upstream is stuck;
- Slow database queries hold up requests;
- Insufficient memory triggers swap or OOM;
- Disk I/O wait is too high;
- Backend connection pool is exhausted;
- Crawler or attack traffic saturates the server.
Although 521/522 are not exactly SSL errors, a wrong SSL mode makes troubleshooting more complicated.
Common modes:
- Flexible: browser to Cloudflare is HTTPS, Cloudflare to origin is HTTP;
- Full: Cloudflare to origin is also HTTPS, but the certificate is not strictly verified;
- Full strict: Cloudflare to origin is HTTPS and the origin certificate must be valid.
For production sites, Full strict is recommended, with Let's Encrypt or a Cloudflare Origin Certificate installed on the origin.
If your origin only listens on 80 but Cloudflare pulls over HTTPS, problems will occur. Check:
sudo ss -lntp | egrep ':80 |:443 '
curl -I https://源站IP -H 'Host: example.com' -k
If the certificate is expired or the domain does not match, it is usually more like 525/526, but many users run into it while troubleshooting 521/522.
A/AAAA records in Cloudflare DNS must point to the real origin.
Check:
dig +short example.com
If the orange-cloud proxy is enabled, an external dig sees Cloudflare IPs, not the origin IP. You need to check in the Cloudflare dashboard whether the origin IP in the DNS record is correct.
Common problems:
- Cloudflare DNS was not updated after the VPS IP changed;
- The A record was updated but the AAAA record still points to the old IPv6;
- The origin disabled IPv6 but Cloudflare still pulls over AAAA;
- Multiple DNS records point to different machines.
For IPv6 configuration issues, see: IPv6 VPS Configuration Guide.
If you urgently need to determine whether it is a Cloudflare path problem, you can temporarily change the DNS record from orange cloud to grey cloud so traffic goes directly to the origin.
But note:
- Grey cloud exposes the origin IP;
- If HTTPS is not properly configured on the origin, users may see certificate errors;
- This is only a troubleshooting method, not a long-term solution;
- DNS changes may have cache delays.
A safer approach is to use curl -H 'Host: 域名' 源站IP to test the origin directly, without immediately changing production DNS.
If you are opening a ticket, do not just say "Cloudflare 522." It is recommended to provide:
date
curl -I http://源站IP -H 'Host: example.com'
curl -I https://源站IP -H 'Host: example.com' -k
sudo ss -lntp | egrep ':80 |:443 '
sudo ufw status verbose
sudo journalctl -u nginx -n 100 --no-pager
sudo tail -n 100 /var/log/nginx/error.log
uptime
free -h
df -h
If you suspect Cloudflare origin-pull IPs are blocked, attach firewall and security group screenshots. This makes it easier to locate the problem than sending only a screenshot of the error page.
When you encounter Cloudflare 521 / 522, check in this order:
- Confirm the error code: 521 is connection refused, 522 is connection timed out.
- Use
curl -H 'Host: 域名' 源站IPto connect directly to the origin. - On the VPS, use
ss -lntpto confirm whether 80/443 is listening. - Check Nginx/Apache/Caddy service status and logs.
- Check UFW, iptables/nftables, firewalld.
- Check whether the cloud provider security group allows Cloudflare origin pull.
- Check whether Cloudflare IPs are being blocked by mistake.
- In 522 scenarios, check CPU, memory, disk I/O, and upstream services.
- Check Cloudflare DNS records and whether A/AAAA point to the correct origin.
- Check whether the SSL mode matches the origin listening/certificate setup.
The core of Cloudflare 521 / 522 is not "Cloudflare is broken," but that the path from Cloudflare to your VPS origin has a problem.
For 521, first check whether the web service is started, whether 80/443 is listening, and whether the firewall is rejecting connections; for 522, first check the firewall/security group, origin load, network, and timeouts. First use curl to bypass Cloudflare and connect directly to the origin, then look at ss, journalctl, Nginx logs, and security group rules. This will basically narrow the problem down to the origin, the network, or the Cloudflare configuration.