I’m trying to embed a preview within my current application. However, iframes don’t support headers, which prevents me from using a force instance id header. My attempt to use Nginx as a workaround is failing; it’s not routing to the Fly.io VM, though it works locally when proxy_pass is set to localhost.
Parsed config on the server
events {
worker_connections 1024;
}
http {
map $arg_auth $auth_header {
"" $http_authorization;
default "Bearer $arg_auth";
}
map $http_upgrade $connection_upgrade {
default upgrade;
"" close;
}
upstream code_server {
server 127.0.0.1:8080;
}
upstream dev_server {
server 127.0.0.1:3000;
}
upstream mcp_server {
server 0.0.0.0:8000;
}
upstream fallback_server {
server 127.0.0.1;
}
server {
listen 80;
server_name _;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_send_timeout 90s;
proxy_read_timeout 90s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;
proxy_set_header Authorization $auth_header;
proxy_intercept_errors on;
location = /sse {
proxy_pass http://mcp_server/mcp/;
}
location = /dashboard {
proxy_pass http://mcp_server/dashboard;
}
location /8000/ {
proxy_pass http://mcp_server/;
}
location /8080/eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3Y3liMmVuMTR3Z2Rrdzh2NHk4ZjZwemQ3cDBocjAiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.kOsPLto0Fq72exFYP1qJAHAin1tM-OHnpKghOi5sDAMr9KTLK9oLk0k_jDty89UBXAGc0OG4aEWLt2ShIFFoOMWrRKJLPb9YB0owQBCvUSGqxpLrmlIhFMrMqSmaRiWZ96exM__xWlgSFyhUkPmzcIfwcOeT7hKhUvJleAQ9O23rxhUZRZhV6KwjxuezEJB0kuWDqSfCHFEi_rwvijaIYsSI0yDJQ6yntWIyJugSlgfWoGLScomG8omeIzr79lt5Y9Y2vEPFKkMPbmTWiIjIYfphc1WQtXx2dJVMStYxSqcVjDX9iueB4bcVpjW0KnLuFrtW8skddGM9sFPmzQ2F3w/ {
proxy_pass http://code_server/;
}
location /preview/ {
proxy_pass http://dev_server/;
}
location /e82d6d1bd90258/ {
proxy_pass http://e82d6d1bd90258.vm.js7cyb2en14wgdkw8v4y8f6pzd7p0hr0.internal/;
}
error_page 401 = /_unauthorized;
location = /_unauthorized {
internal;
add_header Content-Type application/json;
return 401 '{"error":"unauthorized"}';
}
}
}
Hi… What port is e82d6d1bd90258
listening on? Usually that has to be explicitly provided after .internal
, since there is no mechanism in the middle translating port 80 → port 8080, etc.
https://fly.io/docs/networking/app-services/#private-services-on-6pn-direct-wireguard-connections
(Also keep in mind that there is no auto-start with .internal
traffic; it’s all very low-level.)
Aside: Fly-Replay
might work better for this, overall.
the goal is to implement hard-coded endpoints. However, Fly Proxy is designed without this capability, it operates under the assumption that all machines are interchangeable duplicates and will randomly select one to route traffic. So the above nginx config server runs inside every machine for ex, when a request like js7cyb2en14wgdkw8v4y8f6pzd7p0hr0.fly.dev/e82d6d1bd90258/preview/ is made to the nginx proxy, fly will direct it any machine available, the proxy picks up the machine id from the url and proxies to the /preview/ path of the actual machine, which then further proxies the request again to the nginx server for that specific machine without the machine id in itz path which then finally calls the endpoint.
The Fly-Replay
header allows you to specify an individual Machine ID as the target. From the second link above:
The recommended mechanism for connecting to user machines over HTTP is the fly-replay response header. This works by instructing our global proxy to reroute the request to a specific machine.
It’s entirely up to you which one you use, though.
-
I have edited my preview response to be more clear
-
Here is the architecture diagram i have for the proxy (simply cuz i can’t pass headers in iframe so i have to use search params in the url or simply just hardcode the routes)
root@1857273fd79308:/mcp-runner/vibz# cat /var/log/nginx/
access.log error.log
root@1857273fd79308:/mcp-runner/vibz# cat /var/log/nginx/error.log
2025/08/20 17:29:03 [error] 1030#1030: *2 "/usr/share/nginx/html/8080/1857273fd79308/eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3MXp0djJuOTBjc2Q2NzA4dm53eWhremg3cDB3MHgiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.mNq68XgAiJXE7J9GJdYRxeuNFFAsHDzmWE5XotTBI-cijA2RItIt9sUXeHFFhbUYL21fWPEpBK4CW-GU6ElFPZgTFXXucSKSQSU2gJmKflFt6yNhGlDYeREyD1dw0zG8uMTFiYlrQUgQ_NNOEB2UD2l1qywBpn4a4JVFIIeTUPd5OGfoNplflYsY8DD3lwsneDBybPt0x8sNRbnibI-5VCGcRYGjbetYRQ6g7JtztA95MKA5PwQ5cvP2nrT0_guzuu9iud4SBQAWrgMjenWVqYRYFQbNmc7uvh1eFlyHrwjdoYerKjWaBY4oIxN_Zqj5rqwPjqlXh6aDfCfA9WJs0A/index.html" is not found (2: No such file or directory), client: 172.16.28.130, server: _, request: "GET /8080/1857273fd79308/eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3MXp0djJuOTBjc2Q2NzA4dm53eWhremg3cDB3MHgiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.mNq68XgAiJXE7J9GJdYRxeuNFFAsHDzmWE5XotTBI-cijA2RItIt9sUXeHFFhbUYL21fWPEpBK4CW-GU6ElFPZgTFXXucSKSQSU2gJmKflFt6yNhGlDYeREyD1dw0zG8uMTFiYlrQUgQ_NNOEB2UD2l1qywBpn4a4JVFIIeTUPd5OGfoNplflYsY8DD3lwsneDBybPt0x8sNRbnibI-5VCGcRYGjbetYRQ6g7JtztA95MKA5PwQ5cvP2nrT0_guzuu9iud4SBQAWrgMjenWVqYRYFQbNmc7uvh1eFlyHrwjdoYerKjWaBY4oIxN_Zqj5rqwPjqlXh6aDfCfA9WJs0A/ HTTP/1.1", host: "js71ztv2n90csd6708vnwyhkzh7p0w0x.fly.dev", referrer: "http://localhost:3000/"
2025/08/20 17:29:04 [error] 1030#1030: *3 connect() failed (111: Unknown error) while connecting to upstream, client: 172.16.28.130, server: _, request: "POST /sse HTTP/1.1", upstream: "http://0.0.0.0:8000/mcp/", host: "js71ztv2n90csd6708vnwyhkzh7p0w0x.fly.dev"
2025/08/20 17:29:05 [error] 1030#1030: *7 open() "/usr/share/nginx/html/dashboard/1857273fd79308" failed (2: No such file or directory), client: 172.16.28.130, server: _, request: "GET /dashboard/1857273fd79308?auth=eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3MXp0djJuOTBjc2Q2NzA4dm53eWhremg3cDB3MHgiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.mNq68XgAiJXE7J9GJdYRxeuNFFAsHDzmWE5XotTBI-cijA2RItIt9sUXeHFFhbUYL21fWPEpBK4CW-GU6ElFPZgTFXXucSKSQSU2gJmKflFt6yNhGlDYeREyD1dw0zG8uMTFiYlrQUgQ_NNOEB2UD2l1qywBpn4a4JVFIIeTUPd5OGfoNplflYsY8DD3lwsneDBybPt0x8sNRbnibI-5VCGcRYGjbetYRQ6g7JtztA95MKA5PwQ5cvP2nrT0_guzuu9iud4SBQAWrgMjenWVqYRYFQbNmc7uvh1eFlyHrwjdoYerKjWaBY4oIxN_Zqj5rqwPjqlXh6aDfCfA9WJs0A HTTP/1.1", host: "js71ztv2n90csd6708vnwyhkzh7p0w0x.fly.dev", referrer: "http://localhost:3000/"
2025/08/20 17:29:05 [error] 1030#1030: *5 peer closed connection in SSL handshake while SSL handshaking to upstream, client: 172.16.28.130, server: _, request: "GET /1857273fd79308/preview/ HTTP/1.1", upstream: "https://66.241.124.94:443/preview/", host: "js71ztv2n90csd6708vnwyhkzh7p0w0x.fly.dev", referrer: "http://localhost:3000/"
2025/08/20 17:29:05 [error] 1030#1030: *8 peer closed connection in SSL handshake while SSL handshaking to upstream, client: 172.16.28.130, server: _, request: "GET /1857273fd79308/preview/ HTTP/1.1", upstream: "https://66.241.124.94:443/preview/", host: "js71ztv2n90csd6708vnwyhkzh7p0w0x.fly.dev"
2025/08/20 17:29:05 [error] 1030#1030: *10 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.16.28.130, server: _, request: "GET /favicon.ico HTTP/1.1", host: "js71ztv2n90csd6708vnwyhkzh7p0w0x.fly.dev", referrer: "https://js71ztv2n90csd6708vnwyhkzh7p0w0x.fly.dev/1857273fd79308/preview/"
2025/08/20 17:29:07 [error] 1030#1030: *11 peer closed connection in SSL handshake while SSL handshaking to upstream, client: 172.16.28.130, server: _, request: "GET /1857273fd79308/preview/ HTTP/1.1", upstream: "https://66.241.124.94:443/preview/", host: "js71ztv2n90csd6708vnwyhkzh7p0w0x.fly.dev"
2025/08/20 17:29:08 [error] 1030#1030: *13 peer closed connection in SSL handshake while SSL handshaking to upstream, client: 172.16.28.130, server: _, request: "GET /1857273fd79308/preview/ HTTP/1.1", upstream: "https://66.241.124.94:443/preview/", host: "js71ztv2n90csd6708vnwyhkzh7p0w0x.fly.dev"
root@1857273fd79308:/mcp-runner/vibz# cat /etc/nginx/nginx.conf
events {
worker_connections 1024;
}
http {
map $arg_auth $auth_header {
"" $http_authorization;
default "Bearer $arg_auth";
}
map $http_upgrade $connection_upgrade {
default upgrade;
"" close;
}
upstream code_server {
server 127.0.0.1:8080;
}
upstream dev_server {
server 127.0.0.1:3000;
}
upstream mcp_server {
server 0.0.0.0:8000;
}
upstream fallback_server {
server 127.0.0.1;
}
server {
listen 80;
server_name _;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_send_timeout 90s;
proxy_read_timeout 90s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;
proxy_set_header Authorization $auth_header;
proxy_intercept_errors on;
location = /sse {
proxy_pass http://mcp_server/mcp/;
}
location = /dashboard {
proxy_pass http://mcp_server/dashboard;
}
location /8000/ {
proxy_pass http://mcp_server/;
}
location /8080/eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3MXp0djJuOTBjc2Q2NzA4dm53eWhremg3cDB3MHgiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.mNq68XgAiJXE7J9GJdYRxeuNFFAsHDzmWE5XotTBI-cijA2RItIt9sUXeHFFhbUYL21fWPEpBK4CW-GU6ElFPZgTFXXucSKSQSU2gJmKflFt6yNhGlDYeREyD1dw0zG8uMTFiYlrQUgQ_NNOEB2UD2l1qywBpn4a4JVFIIeTUPd5OGfoNplflYsY8DD3lwsneDBybPt0x8sNRbnibI-5VCGcRYGjbetYRQ6g7JtztA95MKA5PwQ5cvP2nrT0_guzuu9iud4SBQAWrgMjenWVqYRYFQbNmc7uvh1eFlyHrwjdoYerKjWaBY4oIxN_Zqj5rqwPjqlXh6aDfCfA9WJs0A/ {
proxy_pass http://code_server/;
}
location /preview/ {
proxy_pass http://dev_server/;
}
location /1857273fd79308/ {
proxy_pass https://js71ztv2n90csd6708vnwyhkzh7p0w0x.fly.dev/;
proxy_set_header fly-force-instance-id 1857273fd79308;
}
error_page 401 = /_unauthorized;
location = /_unauthorized {
internal;
add_header Content-Type application/json;
return 401 '{"error":"unauthorized"}';
}
}
}
Hm… It shouldn’t be necessary to bounce through .fly.dev
like this…
To use Fly Replay, you can just reply (not proxy), and the Fly.io infrastructure will take care of the rest:
(You can also specify a particular instance
in there, if I’m reading the docs correctly.)
Or, if you want to continue with proxy_pass
, then maybe post the error logs from when you had .internal
. Possibly you were getting bitten by one of Nginx’s oft-mentioned DNS quirks.
Hope this helps a little!
Here’s the full log
root@080e6e2ce09798:/# service nginx restart
* Restarting nginx nginx [ OK ]
root@080e6e2ce09798:/# cat /var/log/nginx/access.log
172.16.24.226 - - [20/Aug/2025:19:24:01 +0000] "GET /dashboard?auth=eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3YXQ3Yzg5Z2RmeXdudnJzbWN4OHI5OG43cDBzNXMiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.C9OIomB396q4rBcx7XflaqFkpjEOgKQLS2RhtWU98CGN_19KngW5vVGWMVDCVdKt3tLbKew1OeckdrPU7NK2ZOp8YRNotAYnAk1hqZjp21tOjBZx1zTPFNlSwRfnS5qZALdndtMkLQs15NgEHm1EEXBtGV-pfaISblUlbmIWlj3lbENosaWbAnso5jVHW09VK1U2H2IyqbSW6yh4g7QccTFWgkk46fAQoYT2tpFNgcHjZf0f5sXxwa9NLRaDoV0AjpLNWIjXhpg2ZkmoYX8ae72K8Z09kPzTSuJWGWyERwpQktnNTTb_-eu3vgw4wu9yjGhTjS-tQlyPvhwngEGtbg HTTP/1.1" 200 3064 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36"
172.16.24.226 - - [20/Aug/2025:19:24:03 +0000] "GET /dashboard?auth=eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3YXQ3Yzg5Z2RmeXdudnJzbWN4OHI5OG43cDBzNXMiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.C9OIomB396q4rBcx7XflaqFkpjEOgKQLS2RhtWU98CGN_19KngW5vVGWMVDCVdKt3tLbKew1OeckdrPU7NK2ZOp8YRNotAYnAk1hqZjp21tOjBZx1zTPFNlSwRfnS5qZALdndtMkLQs15NgEHm1EEXBtGV-pfaISblUlbmIWlj3lbENosaWbAnso5jVHW09VK1U2H2IyqbSW6yh4g7QccTFWgkk46fAQoYT2tpFNgcHjZf0f5sXxwa9NLRaDoV0AjpLNWIjXhpg2ZkmoYX8ae72K8Z09kPzTSuJWGWyERwpQktnNTTb_-eu3vgw4wu9yjGhTjS-tQlyPvhwngEGtbg HTTP/1.1" 200 3064 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36"
172.16.24.226 - - [20/Aug/2025:19:24:04 +0000] "GET /dashboard?auth=eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3YXQ3Yzg5Z2RmeXdudnJzbWN4OHI5OG43cDBzNXMiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.C9OIomB396q4rBcx7XflaqFkpjEOgKQLS2RhtWU98CGN_19KngW5vVGWMVDCVdKt3tLbKew1OeckdrPU7NK2ZOp8YRNotAYnAk1hqZjp21tOjBZx1zTPFNlSwRfnS5qZALdndtMkLQs15NgEHm1EEXBtGV-pfaISblUlbmIWlj3lbENosaWbAnso5jVHW09VK1U2H2IyqbSW6yh4g7QccTFWgkk46fAQoYT2tpFNgcHjZf0f5sXxwa9NLRaDoV0AjpLNWIjXhpg2ZkmoYX8ae72K8Z09kPzTSuJWGWyERwpQktnNTTb_-eu3vgw4wu9yjGhTjS-tQlyPvhwngEGtbg HTTP/1.1" 200 3064 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36"
172.16.24.226 - - [20/Aug/2025:19:24:06 +0000] "GET /080e6e2ce09798/dashboard?auth=eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3YXQ3Yzg5Z2RmeXdudnJzbWN4OHI5OG43cDBzNXMiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.C9OIomB396q4rBcx7XflaqFkpjEOgKQLS2RhtWU98CGN_19KngW5vVGWMVDCVdKt3tLbKew1OeckdrPU7NK2ZOp8YRNotAYnAk1hqZjp21tOjBZx1zTPFNlSwRfnS5qZALdndtMkLQs15NgEHm1EEXBtGV-pfaISblUlbmIWlj3lbENosaWbAnso5jVHW09VK1U2H2IyqbSW6yh4g7QccTFWgkk46fAQoYT2tpFNgcHjZf0f5sXxwa9NLRaDoV0AjpLNWIjXhpg2ZkmoYX8ae72K8Z09kPzTSuJWGWyERwpQktnNTTb_-eu3vgw4wu9yjGhTjS-tQlyPvhwngEGtbg HTTP/1.1" 502 568 "https://js7at7c89gdfywnvrsmcx8r98n7p0s5s.fly.dev/080e6e2ce09798/dashboard?auth=eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3YXQ3Yzg5Z2RmeXdudnJzbWN4OHI5OG43cDBzNXMiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.C9OIomB396q4rBcx7XflaqFkpjEOgKQLS2RhtWU98CGN_19KngW5vVGWMVDCVdKt3tLbKew1OeckdrPU7NK2ZOp8YRNotAYnAk1hqZjp21tOjBZx1zTPFNlSwRfnS5qZALdndtMkLQs15NgEHm1EEXBtGV-pfaISblUlbmIWlj3lbENosaWbAnso5jVHW09VK1U2H2IyqbSW6yh4g7QccTFWgkk46fAQoYT2tpFNgcHjZf0f5sXxwa9NLRaDoV0AjpLNWIjXhpg2ZkmoYX8ae72K8Z09kPzTSuJWGWyERwpQktnNTTb_-eu3vgw4wu9yjGhTjS-tQlyPvhwngEGtbg" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36"
root@080e6e2ce09798:/# cat /var/log/nginx/error.log
2025/08/20 19:24:06 [error] 3118#3118: *8 peer closed connection in SSL handshake while SSL handshaking to upstream, client: 172.16.24.226, server: _, request: "GET /080e6e2ce09798/dashboard?auth=eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3YXQ3Yzg5Z2RmeXdudnJzbWN4OHI5OG43cDBzNXMiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.C9OIomB396q4rBcx7XflaqFkpjEOgKQLS2RhtWU98CGN_19KngW5vVGWMVDCVdKt3tLbKew1OeckdrPU7NK2ZOp8YRNotAYnAk1hqZjp21tOjBZx1zTPFNlSwRfnS5qZALdndtMkLQs15NgEHm1EEXBtGV-pfaISblUlbmIWlj3lbENosaWbAnso5jVHW09VK1U2H2IyqbSW6yh4g7QccTFWgkk46fAQoYT2tpFNgcHjZf0f5sXxwa9NLRaDoV0AjpLNWIjXhpg2ZkmoYX8ae72K8Z09kPzTSuJWGWyERwpQktnNTTb_-eu3vgw4wu9yjGhTjS-tQlyPvhwngEGtbg HTTP/1.1", upstream: "https://66.241.124.63:443/dashboard?auth=eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3YXQ3Yzg5Z2RmeXdudnJzbWN4OHI5OG43cDBzNXMiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.C9OIomB396q4rBcx7XflaqFkpjEOgKQLS2RhtWU98CGN_19KngW5vVGWMVDCVdKt3tLbKew1OeckdrPU7NK2ZOp8YRNotAYnAk1hqZjp21tOjBZx1zTPFNlSwRfnS5qZALdndtMkLQs15NgEHm1EEXBtGV-pfaISblUlbmIWlj3lbENosaWbAnso5jVHW09VK1U2H2IyqbSW6yh4g7QccTFWgkk46fAQoYT2tpFNgcHjZf0f5sXxwa9NLRaDoV0AjpLNWIjXhpg2ZkmoYX8ae72K8Z09kPzTSuJWGWyERwpQktnNTTb_-eu3vgw4wu9yjGhTjS-tQlyPvhwngEGtbg", host: "js7at7c89gdfywnvrsmcx8r98n7p0s5s.fly.dev", referrer: "https://js7at7c89gdfywnvrsmcx8r98n7p0s5s.fly.dev/080e6e2ce09798/dashboard?auth=eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3YXQ3Yzg5Z2RmeXdudnJzbWN4OHI5OG43cDBzNXMiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.C9OIomB396q4rBcx7XflaqFkpjEOgKQLS2RhtWU98CGN_19KngW5vVGWMVDCVdKt3tLbKew1OeckdrPU7NK2ZOp8YRNotAYnAk1hqZjp21tOjBZx1zTPFNlSwRfnS5qZALdndtMkLQs15NgEHm1EEXBtGV-pfaISblUlbmIWlj3lbENosaWbAnso5jVHW09VK1U2H2IyqbSW6yh4g7QccTFWgkk46fAQoYT2tpFNgcHjZf0f5sXxwa9NLRaDoV0AjpLNWIjXhpg2ZkmoYX8ae72K8Z09kPzTSuJWGWyERwpQktnNTTb_-eu3vgw4wu9yjGhTjS-tQlyPvhwngEGtbg"
root@080e6e2ce09798:/# cat /etc/nginx/nginx.conf
events {
worker_connections 1024;
}
http {
map $arg_auth $auth_header {
"" $http_authorization;
default "Bearer $arg_auth";
}
map $http_upgrade $connection_upgrade {
default upgrade;
"" close;
}
upstream code_server {
server 127.0.0.1:8080;
}
upstream dev_server {
server 127.0.0.1:3000;
}
upstream mcp_server {
server 127.0.0.1:8000;
}
upstream fly_server {
server js7at7c89gdfywnvrsmcx8r98n7p0s5s.fly.dev:443;
}
server {
listen 80;
server_name _;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_send_timeout 90s;
proxy_read_timeout 90s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;
proxy_set_header Authorization $auth_header;
proxy_intercept_errors on;
location /sse {
proxy_pass http://mcp_server/mcp/;
}
location /dashboard {
proxy_pass http://mcp_server/dashboard;
}
location /8000/ {
proxy_pass http://mcp_server/;
}
location /8080/eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3YXQ3Yzg5Z2RmeXdudnJzbWN4OHI5OG43cDBzNXMiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.C9OIomB396q4rBcx7XflaqFkpjEOgKQLS2RhtWU98CGN_19KngW5vVGWMVDCVdKt3tLbKew1OeckdrPU7NK2ZOp8YRNotAYnAk1hqZjp21tOjBZx1zTPFNlSwRfnS5qZALdndtMkLQs15NgEHm1EEXBtGV-pfaISblUlbmIWlj3lbENosaWbAnso5jVHW09VK1U2H2IyqbSW6yh4g7QccTFWgkk46fAQoYT2tpFNgcHjZf0f5sXxwa9NLRaDoV0AjpLNWIjXhpg2ZkmoYX8ae72K8Z09kPzTSuJWGWyERwpQktnNTTb_-eu3vgw4wu9yjGhTjS-tQlyPvhwngEGtbg/ {
proxy_pass http://code_server/;
}
location /preview/ {
proxy_pass http://dev_server/;
}
location /080e6e2ce09798/ {
proxy_pass https://fly_server/;
proxy_set_header fly-force-instance-id 080e6e2ce09798;
proxy_ssl_server_name on;
}
error_page 401 = /_unauthorized;
location = /_unauthorized {
internal;
add_header Content-Type application/json;
return 401 '{"error":"unauthorized"}';
}
}
}
Ah, I meant the logs from when you had proxy_pass http://e82d6d1bd90258.vm.js7cyb2en14wgdkw8v4y8f6pzd7p0hr0.internal/
.
Trying to proxy_pass
.fly.dev
with SSL seems like a whole can of worms that would best be left unopened, …
lol, how do you suggest i tackle this, the perfect solution would be fly io supporting defining headers in search params, like nginx does with auth headers.
root@080e6e2ce09798:/# cat /etc/nginx/nginx.conf
events {
worker_connections 1024;
}
http {
map $arg_auth $auth_header {
"" $http_authorization;
default "Bearer $arg_auth";
}
map $http_upgrade $connection_upgrade {
default upgrade;
"" close;
}
upstream code_server {
server 127.0.0.1:8080;
}
upstream dev_server {
server 127.0.0.1:3000;
}
upstream mcp_server {
server 127.0.0.1:8000;
}
upstream fly_server {
server js7at7c89gdfywnvrsmcx8r98n7p0s5s.fly.dev:80;
}
server {
listen 80;
server_name _;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_send_timeout 90s;
proxy_read_timeout 90s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;
proxy_set_header Authorization $auth_header;
proxy_intercept_errors on;
location /sse {
proxy_pass http://mcp_server/mcp/;
}
location /dashboard {
proxy_pass http://mcp_server/dashboard;
}
location /8000/ {
proxy_pass http://mcp_server/;
}
location /8080/eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3YXQ3Yzg5Z2RmeXdudnJzbWN4OHI5OG43cDBzNXMiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.C9OIomB396q4rBcx7XflaqFkpjEOgKQLS2RhtWU98CGN_19KngW5vVGWMVDCVdKt3tLbKew1OeckdrPU7NK2ZOp8YRNotAYnAk1hqZjp21tOjBZx1zTPFNlSwRfnS5qZALdndtMkLQs15NgEHm1EEXBtGV-pfaISblUlbmIWlj3lbENosaWbAnso5jVHW09VK1U2H2IyqbSW6yh4g7QccTFWgkk46fAQoYT2tpFNgcHjZf0f5sXxwa9NLRaDoV0AjpLNWIjXhpg2ZkmoYX8ae72K8Z09kPzTSuJWGWyERwpQktnNTTb_-eu3vgw4wu9yjGhTjS-tQlyPvhwngEGtbg/ {
proxy_pass http://code_server/;
}
location /preview/ {
proxy_pass http://dev_server/;
}
location /080e6e2ce09798/ {
proxy_pass http://080e6e2ce09798.vm.js7at7c89gdfywnvrsmcx8r98n7p0s5s.internal:80/;
proxy_set_header fly-force-instance-id 080e6e2ce09798;
}
error_page 401 = /_unauthorized;
location = /_unauthorized {
internal;
add_header Content-Type application/json;
return 401 '{"error":"unauthorized"}';
}
}
}
root@080e6e2ce09798:/# http://080e6e2ce09798.vm.js7at7c89gdfywnvrsmcx8r98n7p0s5s.internal:80/^C
root@080e6e2ce09798:/# curl -I http://080e6e2ce09798.vm.js7at7c89gdfywnvrsmcx8r98n7p0s5s.internal:80/
curl: (7) Failed to connect to 080e6e2ce09798.vm.js7at7c89gdfywnvrsmcx8r98n7p0s5s.internal port 80 after 1 ms: Connection refused
root@080e6e2ce09798:/# curl -I https://080e6e2ce09798.vm.js7at7c89gdfywnvrsmcx8r98n7p0s5s.internal:443/
curl: (7) Failed to connect to 080e6e2ce09798.vm.js7at7c89gdfywnvrsmcx8r98n7p0s5s.internal port 443 after 2 ms: Connection refused
root@080e6e2ce09798:/# curl -I https://080e6e2ce09798.vm.js7at7c89gdfywnvrsmcx8r98n7p0s5s.internal/
curl: (7) Failed to connect to 080e6e2ce09798.vm.js7at7c89gdfywnvrsmcx8r98n7p0s5s.internal port 443 after 0 ms: Connection refused
root@080e6e2ce09798:/# curl -I https://080e6e2ce09798.vm.js7at7c89gdfywnvrsmcx8r98n7p0s5s.internal
curl: (7) Failed to connect to 080e6e2ce09798.vm.js7at7c89gdfywnvrsmcx8r98n7p0s5s.internal port 443 after 1 ms: Connection refused
root@080e6e2ce09798:/# curl -I http://080e6e2ce09798.vm.js7at7c89gdfywnvrsmcx8r98n7p0s5s.internal:80
curl: (7) Failed to connect to 080e6e2ce09798.vm.js7at7c89gdfywnvrsmcx8r98n7p0s5s.internal port 80 after 1 ms: Connection refused
root@080e6e2ce09798:/# cat /var/log/nginx/access.log
172.16.24.226 - - [20/Aug/2025:19:51:39 +0000] "GET /080e6e2ce09798/dashboard?auth=eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3YXQ3Yzg5Z2RmeXdudnJzbWN4OHI5OG43cDBzNXMiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.C9OIomB396q4rBcx7XflaqFkpjEOgKQLS2RhtWU98CGN_19KngW5vVGWMVDCVdKt3tLbKew1OeckdrPU7NK2ZOp8YRNotAYnAk1hqZjp21tOjBZx1zTPFNlSwRfnS5qZALdndtMkLQs15NgEHm1EEXBtGV-pfaISblUlbmIWlj3lbENosaWbAnso5jVHW09VK1U2H2IyqbSW6yh4g7QccTFWgkk46fAQoYT2tpFNgcHjZf0f5sXxwa9NLRaDoV0AjpLNWIjXhpg2ZkmoYX8ae72K8Z09kPzTSuJWGWyERwpQktnNTTb_-eu3vgw4wu9yjGhTjS-tQlyPvhwngEGtbg HTTP/1.1" 502 568 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36"
root@080e6e2ce09798:/# cat /var/log/nginx/error.log
2025/08/20 19:51:39 [error] 3306#3306: *5 connect() failed (111: Unknown error) while connecting to upstream, client: 172.16.24.226, server: _, request: "GET /080e6e2ce09798/dashboard?auth=eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3YXQ3Yzg5Z2RmeXdudnJzbWN4OHI5OG43cDBzNXMiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.C9OIomB396q4rBcx7XflaqFkpjEOgKQLS2RhtWU98CGN_19KngW5vVGWMVDCVdKt3tLbKew1OeckdrPU7NK2ZOp8YRNotAYnAk1hqZjp21tOjBZx1zTPFNlSwRfnS5qZALdndtMkLQs15NgEHm1EEXBtGV-pfaISblUlbmIWlj3lbENosaWbAnso5jVHW09VK1U2H2IyqbSW6yh4g7QccTFWgkk46fAQoYT2tpFNgcHjZf0f5sXxwa9NLRaDoV0AjpLNWIjXhpg2ZkmoYX8ae72K8Z09kPzTSuJWGWyERwpQktnNTTb_-eu3vgw4wu9yjGhTjS-tQlyPvhwngEGtbg HTTP/1.1", upstream: "http://[fdaa:19:730d:a7b:f9:897c:7ef3:2]:80/dashboard?auth=eyJhbGciOiJSUzI1NiJ9.eyJrZXkiOiJPQVVUSF9UT0tFTiIsInZhbHVlIjoianM3YXQ3Yzg5Z2RmeXdudnJzbWN4OHI5OG43cDBzNXMiLCJzdWIiOiJrbjdkZGEyYjJjdGpia25zenpnMTA1YzJ6ZDdtYmZleSJ9.C9OIomB396q4rBcx7XflaqFkpjEOgKQLS2RhtWU98CGN_19KngW5vVGWMVDCVdKt3tLbKew1OeckdrPU7NK2ZOp8YRNotAYnAk1hqZjp21tOjBZx1zTPFNlSwRfnS5qZALdndtMkLQs15NgEHm1EEXBtGV-pfaISblUlbmIWlj3lbENosaWbAnso5jVHW09VK1U2H2IyqbSW6yh4g7QccTFWgkk46fAQoYT2tpFNgcHjZf0f5sXxwa9NLRaDoV0AjpLNWIjXhpg2ZkmoYX8ae72K8Z09kPzTSuJWGWyERwpQktnNTTb_-eu3vgw4wu9yjGhTjS-tQlyPvhwngEGtbg", host: "js7at7c89gdfywnvrsmcx8r98n7p0s5s.fly.dev"
root@080e6e2ce09798:/#
In case it helps, here is an example nginx config file I use:
In it you will find working examples of fly replay, proxy pass to internal addresses, and web socket support. I have a setup where I currently have 12 regions who transfer requests to the correct region based on the URL. These configuration files are generated for each region.