This is sort of a long post so a TL;DR: Machines no longer have public IPv6 addresses, but still with IPv6 connectivity. Apps’ public IPv6 addresses are unchanged, only individual Machines. You are very unlikely to be affected by this change, unless your Machines need to connect to something external that supports both IPv4 and IPv6, and you specifically need to connect over IPv6. In that case, you’ll need to configure something like /etc/gai.conf manually.
Fly Machines have had a public IPv6 addresses assigned to them from early on. Eagle-eyed users might have noticed that Machines created recently have been lacking that public IPv6 addresses, and instead with only a private 6PN.
That’s right, we’re using IPv6 NAT now. For outbound internet traffic from Machines, we’re having hosts running Machines SNAT the 6PN addresses to the host’s public IPv6. Now, before anyone says “ewww”, hear me out: we’re not doing this due to dubious “security” arguments about how NAT increases security. It, in fact, does not, at least not in our case. Existing public IPv6s on Fly Machines already have strict, stateful firewall policies: you cannot just talk to a random Fly Machine on its public IPv6 unsolicited, even if that address is “public”. This does not change whether we’re using NAT or not. Apps have IPv6 addresses to accept requests from users, those addresses are routed through our load-balancer, fly-proxy, and those are also unaffected by IPv6 status of individual machines constituting apps.
Rather, we’re doing this mostly out of operational simplicity and reliability. With a public, semi-static IPv6 address for each Machine, renumbering (which is occasionally needed) currently requires at least force-updating each Machine. In some cases, routing the IPv6 blocks to our hosts with some providers have proven unreliable. This can happen, for example, if an upstream does not route via static routes but instead rely on neighbor discovery. This has been the source of some IPv6 instability reported both in premium support and on this community forum.
Granted, most of these issues can be either engineered or negotiated away, and yes, IPv6 NAT is just the “lazy” solution here, in some sense. But it also makes a lot of real problems go away, and, in our opinion, does not really change the experience of using Fly Machines. A Fly Machine is also not like a home device or a traditional VPS: they are only constituents of apps and may be created / destroyed / migrated / … any time, and do not really need a permanent, routable address for themselves; only apps as a whole do. The only difference is that in most glibc or musl-based images, IPv4 will now be prioritized by default over IPv6. This may even be helpful in other cases, but if you really want your app to talk over IPv6 only (if the target domain also has an IPv4 address), you’ll now need to configure getaddrinfo’s behavior manually.
What if you do require a predictable, outgoing IPv6 address for Machines? Again, even when we were allocating public IPv6 addresses, those addresses aren’t truly static, and they can change due to a number of reasons. The recommended way of getting a predictable IPv6 (or IPv4) is to use Egress IPs, which even allows all Machines of your app to share one single outgoing IP (up to some limitations) in each region.