11 min de leituraIntegrações

Automação self-hosted no n8n para links: do Docker aos webhooks

Rode automação de link no n8n self-hosted com webhooks do Elido, Docker Compose e modo fila, mantendo os dados de workflow em infraestrutura que você controla na UE.

Marius Voß
DevRel · edge infra
Automação self-hosted no n8n para links: webhooks do Elido passam por um proxy reverso até uma instância n8n com fila e workers, tudo dentro de infraestrutura que você controla

Automação self-hosted no n8n para links significa três coisas rodando em servidores que você controla: uma instância n8n no Docker, um endpoint HTTPS público que recebe eventos de webhook do Elido, e chamadas de saída de volta para a API do Elido com um token escopado. Eventos de link e domínio chegam assinados, e eventos por clique estão no roadmap. Seus workflows decidem o que acontece depois, e os logs de execução nunca saem da sua infraestrutura.

Essa é a arquitetura inteira. O resto deste post é a parte que os guias rápidos pulam: como fazer webhooks passarem por um proxy reverso, como checar a assinatura para que um estranho não consiga disparar seus workflows, o que o modo fila muda, e quando o n8n Cloud é honestamente a escolha melhor. Eu rodo essa configuração em uma única VM pequena, e as peças móveis cabem em uma tela.

Se você também quer os próprios links no seu próprio hardware, isso é um trabalho separado e muito maior. O manual de self-hosting do Elido no k3s cobre isso. Aqui, o Elido continua gerenciado e só a camada de automação se move para dentro de casa.

O motivo de sempre é dados. Um workflow de encurtador de URL no n8n self-hosted vê todo payload que processa: a URL de destino, tags, às vezes um nome de campanha que diz mais do que você gostaria, e país, dispositivo e referrer se você trouxer analytics de clique para dentro dele. No n8n Cloud, essas execuções são armazenadas nos servidores de outra pessoa sob os padrões de retenção de outra pessoa. Self-hosted, elas ficam no seu Postgres, na região que você escolheu.

Segundo o Artigo 28 do GDPR, todo processador que toca dados pessoais precisa de um contrato e um lugar nos seus registros. Menos processadores, menos burocracia. Se seus dados de marketing já precisam ficar na UE, o guia de residência de dados na UE explica por que a camada de automação conta tanto quanto o encurtador.

O segundo motivo é a forma do custo. O n8n Cloud cobra por execuções, e um gatilho de webhook movimentado ou uma consulta frequente de analytics consome execuções rápido. Self-hosted, uma execução é uma linha em uma tabela e alguns milissegundos de CPU.

O terceiro é alcance. Uma instância self-hosted fica na mesma rede que o banco de dados do seu CRM ou sua ferramenta interna de tickets, então um evento de link pode cair em um sistema que nunca foi feito para encarar a internet.

A stack do Docker Compose

Uma stack mínima de automação de link no Docker com n8n precisa de quatro serviços. O próprio guia de Docker Compose do n8n é a referência; esta é a versão da qual eu partiria para trabalho com links, com o modo fila já ativado para você não precisar migrar depois.

services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: ${PG_PASSWORD}
      POSTGRES_DB: n8n
    volumes: [pgdata:/var/lib/postgresql/data]

  redis:
    image: redis:7

  n8n:
    image: docker.n8n.io/n8nio/n8n
    env_file: .env.n8n
    ports: ["127.0.0.1:5678:5678"]
    depends_on: [postgres, redis]

  n8n-worker:
    image: docker.n8n.io/n8nio/n8n
    command: worker
    env_file: .env.n8n
    depends_on: [n8n]

volumes:
  pgdata:

E o arquivo de ambiente compartilhado:

DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=change-me
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=redis
N8N_ENCRYPTION_KEY=generate-a-long-random-string
N8N_WEBHOOK_URL=https://n8n.example.com/
N8N_PROXY_HOPS=1

Duas linhas importam mais do que parece. A chave de criptografia precisa ser idêntica no processo principal e em todo worker, ou os workers não conseguem descriptografar a credencial do Elido e toda execução falha com um erro de autenticação confuso. E a porta 5678 fica vinculada só ao localhost, porque o proxy reverso é a única coisa que deveria encarar a internet.

Arquitetura n8n self-hosted para automação de link: o Elido envia webhooks assinados via HTTPS para um proxy reverso, que encaminha para o processo principal do n8n, que enfileira execuções no Redis para workers apoiados por Postgres, enquanto os workers chamam a API do Elido de saída com um token escopado

Chamando a API do Elido a partir do n8n self-hosted

Chamadas de saída não precisam de nada além do que já vem com o n8n. Crie uma credencial Header Auth com o nome Authorization e o valor Bearer seguido de uma chave de API do painel do Elido, depois a use a partir do node embutido HTTP Request. O n8n a criptografa em repouso com a chave do arquivo de ambiente, o que é mais um motivo para essa chave bater em todo lugar.

Toda rota de link é escopada a um workspace. Para encurtar uma URL, envie via POST para https://api.elido.app/v1/workspaces/{workspace_id}/links com um corpo JSON:

{
  "domain_id": 12,
  "destination_url": "{{ $json.url }}",
  "title": "Spring launch",
  "tags": ["n8n", "spring"]
}

Deixe slug de fora e o Elido gera um. O domain_id é o domínio curto onde o link vive; um GET para /v1/workspaces/{workspace_id}/domains lista os seus, e eu fixaria o ID no workflow em vez de consultá-lo a cada execução. Um GET na mesma rota de links lista links, e PATCH /v1/workspaces/{workspace_id}/links/{link_id} muda um destino ou tags depois do fato.

Defina um header Idempotency-Key no POST, construído a partir de algo estável no item que dispara o gatilho, como um ID de linha. Se o n8n tentar de novo o node depois de um timeout, a API reproduz a primeira resposta em vez de criar um segundo link. O guia rápido da API e SDKs cobre o resto da superfície, e a página de API e SDKs está lá se você preferir mover um passo para código depois.

Também existe um node de comunidade empacotado, n8n-nodes-elido, feito para envolver essas chamadas em uma forma mais amigável. Ele está publicado no npm (versão 0.2.0), mas continua opcional e, como não é um node verificado, só é instalado no n8n self-hosted, que é a configuração assumida por este post. Mantenha a versão com HTTP Request como sua base. Se você instalar pacotes de comunidade no modo fila, lembre-se de que a interface só instala no container principal; os workers nunca o veem. A partir do n8n 2.21, a rota de instalação por variável de ambiente corrige isso reconciliando todo container na inicialização, embora ela desinstale qualquer coisa que não esteja na sua lista na primeira vez.

Fazendo webhooks do Elido passarem pelo seu proxy reverso

Os eventos fluem no outro sentido. O Elido emite link.created, link.updated e domain.verified (entre outros) para um endpoint que você registra em Settings, Webhooks, e no n8n self-hosted esse endpoint é a URL de produção de um node Webhook. Um evento click.created por clique está no roadmap, mas ainda não lançado, então por enquanto os dados de clique vêm de uma busca agendada na API de analytics. A lista completa de eventos e os formatos de payload estão na referência webhooks para eventos de link.

Atrás de um proxy, o n8n constrói sua URL de webhook a partir do próprio protocolo, host e porta, o que significa que ele vai anunciar alegremente http://localhost:5678/webhook/... para quem perguntar. A página de configuração de proxy reverso é curta e vale a pena ler por inteiro: defina N8N_WEBHOOK_URL para seu endereço público, defina N8N_PROXY_HOPS=1, e faça o último proxy encaminhar X-Forwarded-For, X-Forwarded-Host e X-Forwarded-Proto. Guias mais antigos dizem WEBHOOK_URL; as versões atuais ainda leem isso, mas registram um aviso de descontinuação.

Nginx, Traefik, o que você já roda serve. O que importa é TLS no lado público e que o caminho /webhook/* chegue ao n8n intacto.

Um detalhe de tempo me pegou. O Elido espera dez segundos por uma resposta antes de contar uma entrega como falhada. Um workflow que escreve em uma API de planilha lenta e só depois responde pode estourar isso, ser tentado de novo, e escrever a mesma linha duas vezes. Configure o node Webhook para responder imediatamente e fazer o trabalho depois.

Se você está conectando isso para um cliente e quer o lado do webhook resolvido para você, a página do recurso de webhooks mostra o que você pode assinar antes de construir qualquer coisa.

Verificando a assinatura antes de qualquer coisa rodar

Uma URL de webhook pública é uma URL pública. Qualquer um que a encontre pode enviar um evento falso via POST e disparar seu workflow, então o primeiro node depois do gatilho deveria ser uma checagem de assinatura.

Cada entrega do Elido carrega X-Webhook-Signature (valor v1= mais um digest hex), X-Webhook-Timestamp em segundos Unix, X-Webhook-Event e X-Webhook-Delivery. O digest é HMAC-SHA256 sobre o timestamp, um ponto e o corpo bruto da requisição, chaveado com o segredo whsec_ mostrado uma vez quando você criou o endpoint.

Ative Raw Body no node Webhook primeiro. Esse é o passo que as pessoas pulam. Se você calcular o hash de JSON.stringify($json.body) em vez dos bytes exatos que o Elido enviou, a ordem das chaves ou os espaços em branco diferem e toda assinatura falha, e você vai passar uma noite convencido de que o segredo está errado. Depois um node Code:

const crypto = require("crypto");
const item = $input.first();
const h = item.json.headers;
const raw = (await this.helpers.getBinaryDataBuffer(0, "data")).toString(
  "utf8",
);

const ts = Number(h["x-webhook-timestamp"]);
if (Math.abs(Date.now() / 1000 - ts) > 300) throw new Error("stale delivery");

const expected =
  "v1=" +
  crypto
    .createHmac("sha256", $env.ELIDO_WEBHOOK_SECRET)
    .update(`${ts}.${raw}`)
    .digest("hex");
const got = h["x-webhook-signature"] || "";
if (
  got.length !== expected.length ||
  !crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected))
) {
  throw new Error("bad signature");
}
return [{ json: JSON.parse(raw) }];

O módulo crypto está disponível no node Code por padrão, então nenhuma configuração extra é necessária ali. A janela de cinco minutos bloqueia reproduções de uma requisição capturada. Quando você rotaciona o segredo, o Elido também envia X-Elido-Signature-Previous durante o período de carência, então você pode aceitar qualquer uma das chaves enquanto atualiza a variável. O guia de verificação de assinaturas de webhook tem uma versão deste node que verifica os dois headers, além da mesma checagem em Node, Python e Go.

Verificação de assinatura de webhook no n8n self-hosted: lê o timestamp e o corpo bruto, rejeita entregas com mais de 300 segundos, recalcula HMAC-SHA256 sobre timestamp ponto corpo bruto com o segredo do endpoint, compara em tempo constante, depois roda o workflow ou para a execução

Modo fila e retries

Com a checagem de assinatura no lugar, a pergunta restante é o que acontece sob carga ou quando algo está fora do ar. Dois sistemas de retry estão em jogo aqui, e cobrem falhas diferentes.

No modo fila do n8n, o processo principal recebe o webhook, cria uma execução e passa o ID dela para o Redis; os workers a pegam. Uma rajada de eventos se acumula na fila em vez de travar a resposta HTTP. Para mais volume de entrada você pode adicionar processadores de webhook dedicados atrás de um balanceador de carga, embora para a maioria das cargas de trabalho com links um processo principal e dois workers sejam suficientes.

O lado do Elido lida com o n8n ficando inacessível. Qualquer resposta não-2xx ou timeout é tentado de novo depois de 1, 5 e 15 minutos; depois de três tentativas a entrega é marcada como falhada e você pode reativá-la a partir do painel. Isso cobre um reinício de container ou um deploy rápido. Não cobre uma indisponibilidade de fim de semana, motivo pelo qual eu combinaria webhooks com uma reconciliação noturna que lista links pela API, como o post webhooks vs polling defende.

Use X-Webhook-Delivery como chave de idempotência. Retries a reutilizam.

n8n self-hosted vs n8n Cloud: trocas honestas

Eu prefiro hospedar por conta própria para isso, mas já vi equipes se arrependerem. Aqui está a comparação sem o discurso de vendas de nenhum dos lados.

Preocupaçãon8n self-hostedn8n Cloud
Onde os dados de execução vivemSeus servidores, sua região, sua retençãoInfraestrutura e padrões do n8n
Alcance de sistemas internosMesma rede que seu CRM e bancos de dadosSó o que você expõe publicamente
URL de webhook pública e TLSVocê roda o proxy e os certificadosFornecido
Upgrades, backups, patchesSeu trabalho, todo mêsCuidado por eles
Custo em alto volume de eventosCusto de servidor fixoEscala com as execuções

A última linha corta dos dois lados. Uma VM pequena é barata, mas uma hora de um engenheiro em um upgrade quebrado não é, e o n8n lança versões com frequência. Se ninguém na equipe é dono da máquina, o Cloud com o node HTTP Request e a API REST do Elido é a opção mais sensata, e as receitas de Make e IFTTT ou o guia do Zapier mostram como é esse caminho gerenciado em outras plataformas.

O que não consigo te dizer é se o seu encarregado de proteção de dados vai aceitar uma máquina self-hosted como mais simples do que um DPA de fornecedor. Na minha experiência geralmente aceitam, mas isso depende de quão bem a máquina é administrada. Para como funciona o lado do contrato do encurtador, o guia de GDPR para encurtadores de URL é o lugar para começar. E se você está pronto para conectar o primeiro workflow, pegue um token de API em um workspace e aponte um node Webhook para ele.

Relacionados no blog

Perguntas frequentes

Posso usar um encurtador de URL com o n8n self-hosted?

Sim. O n8n self-hosted consegue chamar qualquer encurtador com uma API REST pelo node embutido HTTP Request. Para o Elido isso significa uma credencial Header Auth carregando sua chave de API e um POST para a rota de links escopada por workspace. Eventos de entrada como link.created chegam pelo node Webhook embutido do n8n, que precisa de uma URL HTTPS pública. Um evento click.created por clique está planejado, mas ainda não disponível.

Como instalo nodes de comunidade no n8n self-hosted?

Em uma instância única, use Settings, depois Community Nodes, e cole o nome do pacote npm. No modo fila, a instalação pela interface não chega aos seus workers, então instale o pacote dentro de cada container ou, a partir do n8n 2.21, liste-o em N8N_COMMUNITY_PACKAGES com N8N_COMMUNITY_PACKAGES_MANAGED_BY_ENV definido como true. Para o Elido você não precisa de um: o node HTTP Request cobre a API.

O que é WEBHOOK_URL no n8n?

Ele diz ao n8n qual endereço público mostrar no editor e registrar com serviços externos, porque atrás de um proxy reverso o n8n não consegue deduzir isso a partir do próprio host e porta. As versões atuais do n8n leem N8N_WEBHOOK_URL e registram um aviso de descontinuação para o WEBHOOK_URL mais antigo. Combine-o com N8N_PROXY_HOPS=1 e headers encaminhados no proxy.

Como verifico uma assinatura de webhook no n8n?

Ative a opção Raw Body no node Webhook, depois adicione um node Code que recalcula HMAC-SHA256 sobre o header de timestamp, um ponto e o corpo bruto, usando o segredo do seu endpoint. Compare com o header de assinatura em tempo constante e rejeite qualquer coisa com mais de cinco minutos. Verifique contra os bytes brutos, nunca contra JSON reserializado.

O modo fila do n8n precisa de Redis?

Sim. No modo fila, a instância principal e quaisquer processadores de webhook transformam gatilhos recebidos em IDs de execução e os colocam em uma fila apoiada por Redis, e os workers os retiram dela. O n8n também desaconselha o modo fila com SQLite, então planeje usar Postgres. Todo processo precisa compartilhar a mesma chave de criptografia ou os workers não conseguem ler as credenciais armazenadas.

O n8n self-hosted é melhor para GDPR do que o n8n Cloud?

Pode ser, porque você escolhe onde os dados de workflow, os logs de execução e as credenciais vivem fisicamente e quem os administra. Não é automaticamente compatível: você passa a ser responsável por patches, controle de acesso, backups e retenção. Para automação de link que lida com dados de clique, hospedar por conta própria em uma região da UE remove um processador dos seus registros, o que simplifica a burocracia.

Experimente Elido

Cole uma URL, obtenha um link curto

Sem cadastro. O link vive 30 dias. Cadastre-se para mantê-lo para sempre.

Grátis, sem necessidade de registo · 2 por dia

Experimente o Elido

Encurtador de URL hospedado na UE: domínios personalizados, análises profundas e API aberta. Plano gratuito - sem cartão de crédito.

Tags
self-hosted n8n automation links
n8n self hosted url shortener
n8n docker link automation
n8n webhook signature verification
n8n queue mode
n8n http request node api

Continuar lendo