Multipath TCP (MPTCP) para DiscourseHub e PWA do Safari iOS atrás do Caddy

Continuando a discussão de Caddy na frente do Nginx do app via Docker Compose:

Após minha discussão anterior sobre a execução do Caddy na frente do contêiner nginx do Discourse para fornecer HTTP/3 e QUIC 0-RTT, tenho investigado uma pergunta separada, mas relacionada: se o Multipath TCP (MPTCP) poderia melhorar a continuidade da conexão para usuários do iOS que alternam entre redes Wi-Fi e celulares.

Meu trabalho anterior estava principalmente preocupado com o desempenho inicial de carregamento de páginas. Esta pergunta é diferente: acesso regularmente meu arquivo de estudo privado do Discourse enquanto me movo entre atividades, e conexões interrompidas ou buffering podem atrasar o acesso a informações importantes.

Por que estou perguntando

Em alguns locais, o Wi-Fi é confiável, mas a recepção celular é ruim; em outros, a situação é invertida.

A comutação de rede comum do iOS nem sempre forneceu a continuidade de que preciso. Já uso tecnologia separada de bonding/failover de rede para resiliência de conexão, mas estou interessado em entender se parte dessa continuidade poderia ser alcançada nativamente entre um cliente iOS e meu servidor Discourse.

Em particular, estou interessado na transferência de conexão (handover) e em evitar solicitações travadas, em vez de necessariamente agregar a largura de banda de duas conexões.

O que encontrei até agora

A documentação de compatibilidade do MPTCP para Linux lista o Caddy v2.10.0 em diante como suportando MPTCP por padrão, sujeito ao suporte do sistema operacional.

A documentação do MPTCP da Apple descreve como as aplicações podem optar pelo MPTCP através de URLSessionConfiguration.

No entanto, também encontrei uma explicação nos Fóruns de Desenvolvedores da Apple indicando que o WKWebView não expõe uma opção de configuração equivalente para MPTCP.

Isso me deixa incerto sobre se o DiscourseHub, o Safari ou um PWA iOS instalado poderiam se beneficiar do MPTCP, particularmente quando o HTTP/3 sobre QUIC também está disponível.

Ambiente de servidor confirmado

Verifiquei o VPS de produção usando comandos somente leitura, sem modificar sua configuração.

  • Proxy reverso: Caddy v2.11.4, imagem Docker oficial caddy:2.11.4

  • Host: Ubuntu, kernel Linux 6.8.0-146-generic

  • MPTCP do Host: net.mptcp.enabled = 1

  • MPTCP do Contêiner: /proc/sys/net/mptcp/enabled = 1

  • Rede Docker: caddy_default, driver bridge, opções {}

  • Ambiente Go: GODEBUG não definido

  • Portas publicadas: TCP 80, TCP 443 e UDP 443, em IPv4 e IPv6

O nginx do Discourse permanece atrás do Caddy, com o Caddy fornecendo o endpoint público HTTPS e HTTP/3.

Essas verificações sugerem que o servidor tem os pré-requisitos básicos para suporte a MPTCP, embora eu não tenha verificado a negociação real de MPTCP através do encaminhamento de portas publicadas do Docker.

Perguntas

  1. DiscourseHub: Sua rede iOS usa componentes capazes de solicitar MPTCP, ou seu conteúdo web principal é tratado através de APIs de rede que não expõem essa capacidade?

  2. Safari e PWAs instalados: Existe alguma diferença entre acessar o Discourse através do DiscourseHub, do Safari e de um PWA iOS instalado? O cliente precisa solicitar explicitamente o MPTCP, ou algum desses métodos de acesso poderia se beneficiar transparentemente?

  3. Rede Docker: A configuração bridge/NAT pode preservar a negociação inicial de MPTCP e fluxos subadicionais, ou isso poderia causar que as conexões recuem para TCP comum?

  4. HTTP/3 versus MPTCP: Como o HTTP/3 usa QUIC sobre UDP em vez de TCP, a migração de conexão QUIC forneceria alguma continuidade comparável ao alternar redes? Há uma distinção prática entre HTTP/2 sobre MPTCP e HTTP/3 sobre QUIC nesta situação?

  5. Recuperação no lado do Discourse: Existem mecanismos existentes no Discourse ou em seus clientes iOS para recuperar solicitações interrompidas quando a rede subjacente muda? Existe uma maneira recomendada de estabelecer qual transporte um cliente iOS está realmente usando?

Não estou propondo que o próprio Discourse gerencie múltiplas interfaces de rede. Estou tentando entender onde reside a responsabilidade entre o cliente iOS, o protocolo de transporte, o Docker/Caddy e o Discourse, e se há capacidades existentes que eu poderia aproveitar.

Agradeceria por qualquer orientação ou correção ao meu entendimento.

Obrigado!

Seguinte: interrupção da edição de post no iOS e continuidade da conexão HTTP/3

Encontrei agora um exemplo prático do problema de continuidade de conexão sobre o qual eu estava perguntando.

Em 21 de outubro de 2026, enquanto editava um post na minha instância privada do Discourse em um iPhone 16 Pro usando a PWA do Safari, a barra azul Salvando travou. Eu havia acabado de ditar algumas notas adicionais da aula.

O editor não estava mais acessível, inclusive quando toquei na barra azul de Salvamento, então não consegui copiar o texto não salvo para outro lugar.

Após esperar mais tempo que o habitual, desativei manualmente o Wi-Fi para tentar usar a conectividade celular. A página não mudou imediatamente, mas as tentativas subsequentes de navegação também pareceram travar.

Posteriormente, examinei os logs do Caddy e do nginx e o histórico de revisões do post.

Às 12:20:08 BST:

  • O Caddy registrou uma requisição HTTP/3 PUT /posts/70695 da conexão Wi-Fi da universidade, com todos os 1.000 bytes do corpo da requisição recebidos, mas status 0.

  • O nginx registrou a requisição correspondente como HTTP 400, sem tempo de processamento de rota do Discourse ou upstream.

  • Outras duas requisições do iPhone originadas da conexão celular também receberam HTTP 400 no mesmo segundo.

  • Nenhuma revisão bem-sucedida do post foi registrada naquele momento.

Uma edição subsequente teve sucesso às 12:20:55 BST, mas o texto ditado estava ausente.

Houve também um salvamento automático bem-sucedido de rascunho do Discourse às 12:19:44 BST, embora eu não consiga estabelecer se ele continha o texto perdido.

Reconheço que desativar manualmente o Wi-Fi pode ter interrompido requisições pendentes. No entanto, a operação original de Salvamento já estava travada antes de eu mudar a conexão de rede.

Isso levanta duas questões relacionadas ao meu post original:

  1. Migração de conexão QUIC: Existe uma maneira recomendada de determinar se o navegador iOS tentou migrar a conexão HTTP/3 existente, em vez de estabelecer uma nova conexão ou abandonar as requisições pendentes?

  2. Recuperação do editor do Discourse: Se uma requisição de edição de post travar ou for interrompida, é esperado que o editor permaneça inacessível atrás do estado de Salvamento? Existe algum mecanismo de timeout, repetição ou recuperação que deva preservar o texto não salvo?

Tenho interesse particular na segunda questão, pois não consegui voltar ao editor para copiar meu trabalho antes de tentar restaurar a conectividade.

Não alterei nenhuma configuração do Caddy, nginx ou HTTP/3 como resultado deste incidente, uma vez que as evidências disponíveis ainda não identificaram o que causou a parada inicial da operação de Salvamento.