I got it running, thanks everyone for your help.
These are the exact steps I took:
1 Add your domain to Cloudflare
CF will not give an origin cert for a domain that they do not control. You won’t be able to do this for your Fly dev domain (eg:
your-app.fly.dev). Add the domain to CF, change the NS in your registrar’s dashboard, and wait until the NS have propagated.
2 Configure the DNS to point to your Fly app
You will need to add A records so that your domain or subdomain point to your Fly app.
To get the IP of your Fly app do:
In the DNS management section of CF’s dashboard add the A record. Typically when doing this, you’d want to avoid CF being a proxy, but in this case you must enable the option (the orange cloud) because the CF origin cert is only valid between your app and CF. Browsers will not accept the origin cert as valid.
3 Get the origin certs from CloudFlare
Go to the SSL/origin server section fo the dashboard. Create and download the cert and the key. I used PEM format, but YMMV.
4 Add the certs to your application
Obviously this will change for every app. I’m using Node.js and Fastify and injecting the certs via an env var that comes from two Fly secrets.
To add a cert file to a Fly secret use this:
fly secrets set SSL_KEY=- < key.pem
5 Configure fly to let you handle SSL in your app
fly.toml file remove the
tls handlers for the 443 port.
handlers = 
port = 443
Honestly, I don’t know if this needs to be done for the 80 port too. I think CF acting as a proxy won’t let you access the Fly app via HTTP anyway.
And that’s it. Deploy your app and no more 525 errors!
Took me a couple of hours at first, but now that I understand the whole process and its pitfalls it should be super easy to replicate.