I deployed a remix application today on fly.io, and it’s deploying successfully. If I use the fly proxy 8080 command, I can access the app on localhost, as I should be able to. However, I cannot access the app through the subdomain: twelvepool.fly.dev.
Hi there. I’m having a similar issue; just deployed an App using pretty much the default generated configuration file. Deployment succeeded, App is healthy and I can access it using the fly proxy command, but using the subdomain results in a 404.
If you haven’t checked, then see if the app process is listening for plaintext http connections on 8080 (as defined with services.internal_port) and responding approp?
How do you mean? If I understood properly, app is the default process. That’s the service exposing the services.internal_port. If I can reach the service with the fly proxy command, doesn’t that mean it’s listening properly?
And apologies if I misunderstood your question.
Maybe your web server is misconfigured, specifically the virtual hosts? Requests via fly proxy will have the Host header set to localhost:8080, while request via the .fly.dev subdomain will have the Host header set to that domain (there will also be additional headers automatically added by Fly).
Another potential difference is IPv4/IPv6: fly proxy will probably use IPv6, while the subdomain might get accessed over IPv4.
The web server configuration would be helpful for debugging, ideally as a minimal reproducible example…
The server is binding the listener to http://*:8080 and http://*:9001 which should be ANY interface on ports 8080 and 9001. That should work for both IPv4/v6.
I’ve updated the config to bind to http://0.0.0.0:8080 and http://0.0.0.0:9001 to do only IPv4. Results are still the same, the service isn’t reachable. The internal health check still works.
Deploying this to a kubernetes cluster and exposing it as a service with a TLS domain works, so this feels like something to do with fly’s platform.
There isn’t any additional configuration for the web server really…
Try deploying the same code to another app and see if it works? I recall a similar issue reported once before.
Btw, listening on all interfaces is the right thing to do (source of many a debug headaches if you ever find yourself accidentally using any of Fly’s IPv6-only features).
Try deploying the same code to another app and see if it works? I recall a similar issue reported once before.
Yeah, I’ve done this. I’ve even created a separate project with the bare minimum… basically just a server that can reply something static text content to :8080/ and :9001/healthz endpoints. I’ve published the code here. There really isn’t much to it.
I’ve then deployed a new app with this, but I’m still getting the same results, unfortunately.
Btw, listening on all interfaces is the right thing to do
Ok… some updates… this has nothing to do with the platform, it’s just a code issue, so apologies to everyone involved.
I’ve removed the 9001 port from the equation, left only 8080. Deployed and success, got a 200 as expected.
I then removed the 0.0.0.0 from the binding and left * to listen to any interface, since I think that should be the correct setting. Deployed and success, still got a 200 as expected.
The issue here is when listening to two ports, even though that’s not exactly the issue; particularly the way the endpoints are being mapped. To sum up, here’s what I’m doing (not real code)
The problem is that RequireHost that isn’t doing what I expected it to do. It works locally (I have no idea why it worked with Kubernetes) but it won’t work on fly.io (or [insert-competition-name]).
So… closing this issue, as it’s a code issue. Apologies and a thank you to all that replied.
This looks like the problem – the pattern will be matched against the Host header, not the local listening port; changing the pattern to "*:80" fixes the 404. See RequireHost and reverse proxy · Issue #42252 · dotnet/aspnetcore · GitHub; the later comments also describe how to match against the local port (it looks complicated).
Maybe Kubernetes is rewriting the Host header…
(Also worth mentioning the X-Forwarded-* headers, but I don’t think they are relevant here.)
The health check requests have the internal port in the Host header (unlike external requests).
I was about to post the same thing, but this is actually a hijacked thread :)
This looks like the problem – the pattern will be matched against the Host header, not the local listening port; changing the pattern to "*:80" fixes the 404. See RequireHost and reverse proxy · Issue #42252 · dotnet/aspnetcore · GitHub; the later comments also describe how to match against the local port (it looks complicated).
This is exactly it! It’s a complete mess, to be honest. But yes, changing to *:80 does work. Thank you for the link btw, it’s a great find!
later comments also describe how to match against the local port
Seems like this is the correct path, though it feels like this should be handled by ASPNET.
I’ve added another endpoint without the restrictions to dump the headers and this is what I get (removed some irrelevant values)
Ok, just sharing my success on this. Managed to get everything to work as expected.
Thanks to @tom93 and the links he provided, I was able to resolve the issue, which again, was a code issue, not a fly issue.
I’ve replaced the .RequireHost with a filter that verifies the local port instead. Not posting real code, since that’s out of scope, but this was what I had before
Which didn’t work unless we replaced the first one with *:80. That would mean different code on different environments (and/or providers). So… instead, I’m doing this instead