Solução alternativa para página de manutenção - isso é possível?

Ocorreu um erro na minha atualização

api_key = "a quick brown fox"
fetch("https://api.example.com/data", headers: { 'Authorization' => api_key })

Por favor, ajudem-me a corrigi-lo.

E aí!

Não estou respondendo à sua pergunta, só estou curioso. Por que você acha que precisa de uma página de manutenção? Parece bastante chato de configurar para pouco benefício.

Minhas instâncias ficam fora do ar por 5 minutos por mês para atualizações e é basicamente isso.

Sempre que eu fazia alterações significativas, como instalar plugins, por exemplo, às vezes levava 20 minutos.

Não é um grande problema, se considerarmos que isso não é feito toda semana ou mesmo todo mês, mas para um visitante novo, aquela página feia indicando que algo não está funcionando, não é uma boa primeira impressão. Até mesmo para visitantes recorrentes que não sabem que o site estará fora do ar, isso pode colocá-los em “modo de pânico”, pensando que toda a comunidade foi desativada ou algo assim, talvez alguns deles me enviando e-mails imediatamente perguntando o que está acontecendo.

Acho que é apenas um toque agradável para o visitante, novo ou antigo, para informá-los do que está acontecendo.

Se essa abordagem sugerida pelo Claude é algo que leva apenas alguns minutos, mas não precisa ser feita novamente, acredito que seja um tempo bem investido.

tenho uma solução, mas não tenho tempo para postá-la agora. responderei mais tarde.

Leva apenas segundos se você migrar para a instalação com dois contêineres.

Você pode até agendar a migração para a noite, se realmente quiser, enquanto você e/ou seu público principal estiverem dormindo.

Você não precisa de uma página de manutenção.

Eu uso a construção de contêiner duplo por trás do CDN do Cloudflare. O contêiner duplo minimiza o tempo de inatividade e meus dois fóruns de produção principais têm no máximo 30 segundos offline durante as reconstruções. Eu gosto de ter uma página de manutenção porque a página padrão de servidor web está inativa é feia e não dá nenhuma dica sobre por quanto tempo ela estará offline.

por exemplo, para um site em your-domain.com eu simplesmente uso uma rota de trabalhador do Cloudflare definida como `yourdomain.com/.

Etapa 1: Crie a página do trabalhador

você pode configurar a página de manutenção na página de configurações workers & pages no Cloudflare - clique no botão create application:

então use o modelo hello world:

então dê a ele um nome e clique em deploy:

então vá para a página de visão geral dessa página de manutenção e clique em edit code:

e cole este código na janela de código worker.js (substitua seu domínio e qualquer mensagem que você queira, edite o texto, a cor do texto, o fundo, etc):

export default {
  async fetch(request, env, ctx) {
    try {
      // Busca a solicitação original do seu servidor
      const response = await fetch(request);

      // Se SEU SITE estiver trocando contêineres, ele gera um erro 502, 521 ou 530
      if (response.status === 502 || response.status === 521 || response.status === 530) {
        return returnCustomErrorPage();
      }

      // Se tudo estiver bem, retorne o tráfego normal do fórum
      return response;
    } catch (e) {
      // Se o servidor estiver completamente inacessível
      return returnCustomErrorPage();
    }
  }
};

function returnCustomErrorPage() {
  const html = `
    <!DOCTYPE html>
    <html lang="pt-BR">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Atualização do Sistema - YOUR-SITE.com</title>
      <style>
        body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; text-align: center; padding: 50px; color: #333; background-color: #f9f9f9; }
        h1 { font-size: 2.5em; margin-bottom: 0.5em; color: #9400D3; }
        p { font-size: 1.2em; line-height: 1.5; }
        .container { max-width: 600px; margin: 0 auto; background: white; padding: 40px; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
      </style>
    </head>
    <body>
      <div class="container">
        <h1>Apenas uma breve janela de atualização</h1>
        <p><strong>YOUR-SITE</strong> está passando por uma breve atualização de sistema de 30 segundos.</p>
        <p>Tomem um gole rápido da sua bebida — esta página será atualizada automaticamente assim que estivermos de volta online.</p>
      </div>
      <script>
        // Verifica automaticamente se o site está de volta a cada 10 segundos
        setInterval(function() {
          window.location.reload();
        }, 10000);
      </script>
    </body>
    </html>
  `;

  return new Response(html, {
    status: 503, // 503 é o melhor para SEO, para que o Google não penalize você por tempo de inatividade
    headers: {
      "Content-Type": "text/html;charset=UTF-8",
      "Retry-After": "30"
    }
  });
}

deve ficar mais ou menos assim. clique em deploy para salvá-lo:

Etapa 2: Adicione a rota

agora vá para a página de rotas do trabalhador do Cloudflare e clique no botão add route para abrir o modal de nova rota, preencha a rota do domínio e selecione a página do trabalhador que você acabou de criar, então clique em salvar:

Etapa 3: Executando atualizações ou reconstruções

agora, quando você ssh para seu servidor e executar suas atualizações do sistema ou fazer uma reconstrução, em vez de uma página de site inativo ou erro, esta página será exibida quando o tempo de inatividade realmente acontecer (eu uso 30 segundos no meu porque esse é o máximo para meus sites)

eu tendem a adicionar e excluir minha página de rota de trabalhadores sempre que estou fazendo manutenção, mas alguns gostam de simplesmente deixá-lo lá o tempo todo (eu deixo o código real para a página, eu apenas adiciono e removo a rota).

eu acho que é isso.

Opcional: Execute atualizações com um script e agende

eu também uso um script de shell unix em meu servidor para executar a atualização específica do contêiner duplo, que eu criei assim:

cat << 'EOF' > /root/update-web.sh
#!/bin/bash
cd /var/discourse
echo "➡️ Baixando os scripts mais recentes do Docker Discourse..."
git pull

echo "➡️ Bootstrapando novo contêiner web em segundo plano (leva ~8 minutos)..."
./launcher bootstrap web_only

if [ $? -eq 0 ]; then
    echo "✅ Bootstrap bem-sucedido! Trocando contêineres..."
    ./launcher destroy web_only && ./launcher start web_only
    echo "🚀 Pronto! Site atualizado com quase zero tempo de inatividade."
else
    echo "❌ Bootstrap falhou! Abortando troca para manter o site atual online."
fi
EOF

chmod +x /root/update-web.sh

então eu o executo no prompt root em meu servidor com o comando ./update-web.sh.

você pode automatizá-lo para um horário específico, como 1 da manhã de domingo no seu horário local com um trabalho cron. para mim 1:00am local é 8:00 AM UTC, (você pode descobrir a data UTC do seu servidor) digitando date no prompt de comando quando estiver ssh’d.

então:

execute este comando para abrir o agendador de tarefas do seu servidor:

crontab -e

(se ele pedir para você escolher um editor, pressione seu editor preferido, 1 para nano é provavelmente o mais fácil)

eu rolo para o final dos comentários e cole isto:

0 8 * * 0 /root/update-web.sh >> /var/log/discourse-update.log 2>&1

(o que significa executar o arquivo /root/update-web.sh no minuto 0, hora 8 (UTC), toda manhã de domingo)

então salve e saia (se você estiver usando nano):

  1. Ctrl + O para salvar.
  2. Enter para confirmar.
  3. Ctrl + X para sair.

então eu posso executar cat /var/log/discourse-update.log quando eu acordar nas manhãs de domingo para verificar se ele foi executado corretamente. se você usar um agendador de tarefas cron, então você querer deixar a rota da página de trabalhadores.

eu acho que é tudo. me avise se você tiver perguntas lol. é muito mais simples do que eu fiz parecer lol. :grin:

Uau! Agradeço muito esse tutorial detalhado! :raising_hands:
Acabei de salvar sua resposta nas minhas anotações, então, quando eu instalar o Discourse novamente em breve, voltarei a consultá-la. Com certeza vou te contar como foi, mesmo que demore um pouco para eu fazer a instalação. No momento, estou terminando algumas coisas de codificação e só depois voltarei a me concentrar no Discourse.

E concordo que a página “web serve is down” seja feia, e para usuários inexperientes, essa mensagem não significa muito. Ter uma página de manutenção simples com uma mensagem personalizada é sempre preferível, mesmo que isso envolva algum trabalho de configuração.

Mais uma vez, obrigada muito por dedicar tempo para compartilhar isso. Espero que outras pessoas também achem útil :slight_smile:

E eis o problema.

Não é uma mudança simples e envolve infraestrutura adicional para se preocupar e manter, e, na minha opinião, definitivamente não vale a pena por alguns segundos de indisponibilidade.

Entendo o que você quer dizer, mas esse é apenas um caso. E se algo realmente quebrar e eu precisar corrigir, levando mais do que alguns segundos?

Além disso, como você está obtendo alguns segundos de indisponibilidade, enquanto eu estava vendo cerca de 20 minutos, após instalar plugins?

Porque na configuração com dois contêineres (vinculada em ambas as nossas postagens e uma dependência não negociável) você inicializa a nova compilação usando ./launcher bootstrap web_only (durante o qual seu site permanece 100% funcional), em seguida, você simplesmente destrói e inicia imediatamente o novo contêiner já compilado (o que leva segundos).

Ah, ok, isso ainda é para a configuração com 2 contêineres. Eu achei que você estava dizendo que não valia a pena o trabalho de construir a configuração com 2 contêineres completamente. O que você está dizendo que não vale a pena é apenas o trabalho extra da página de manutenção, certo?

Pessoalmente, sim.

Se você quiser redundância para os usuários da web que aparecerem com navegação atualizada durante os 30 a 60 segundos, então uma página de manutenção é justa.

Você tem que pesar o benefício disso contra o tempo necessário para manter a infraestrutura ao redor.

Agora entendi. Obrigado.

Então, minha pergunta é: com 2 contêineres, aquelas 20 minutos mais ou menos ainda continuam sendo um problema, a única diferença é que posso deixar que ele faça isso em um dos contêineres, o que não está ativo, e quando estiver pronto, fazer a troca. É assim que funciona?

Sim, ainda leva um tempo para construir o container. E, por falar nisso, você precisa garantir que seu servidor seja robusto o suficiente para permitir que esse processo ocorra em paralelo enquanto atende sua comunidade normalmente (essencialmente, o mais importante é garantir memória suficiente para começar – então, é muito importante ter SWAP suficiente). A compilação também ocupará pelo menos um núcleo, então considere ter um servidor com 1 ou 2 núcleos a mais.

Agora tudo faz sentido. Obrigado.

Inicialmente, eu estava usando isso, mas parece que não está mais disponível:

Então agora preciso usar esse:

O que representa um aumento significativo no preço… :confused: e parece ser um servidor menos eficiente…?

Recomendo pelo menos 4 GB e 3 núcleos (“vcpu”) para esse tipo de configuração …

Para referência, já que foi perguntado em outro tópico, a resposta: Any cheaper alternatives to Hetzner? - #2 by Canapin