SSD Nodes Learn 🎉 VPS desde $5.50/mês
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-13

Como hospedar o Open Connector para agentes de IA

Execute o gateway Open Connector na sua VPS, com imagem fixada, origem TLS, callbacks OAuth e backups, para evitar tokens SaaS nos agentes de IA.

O que o Open Connector faz por um agente de IA

A instalação autónoma do Open Connector coloca um gateway de autenticação entre os seus agentes de IA e todas as APIs de software como serviço (SaaS) que utilizam. Assim, o agente nunca armazena um token do fornecedor. É um gateway de código aberto da OOMOL Lab, licenciado ao abrigo da Apache 2.0. É executado como um único contentor, mantém o estado num único ficheiro SQLite e expõe ações dos fornecedores por HTTP e por MCP (model context protocol).

O problema começa na segunda integração. Cada fornecedor tem o seu próprio fluxo OAuth (open authorization), a sua própria validade para tokens de atualização e os seus próprios nomes de escopo. Integrar manualmente cinco fornecedores num agente significa criar cinco handlers de redirecionamento, cinco armazenamentos de credenciais e cinco ciclos de atualização que têm de ser executados antes de um token expirar. Quase ninguém escreve esse código. Em vez disso, criam um personal access token de longa duração para cada serviço e colam-no na configuração do agente, num ficheiro de ambiente ou no próprio prompt. Todas as ferramentas executadas pelo agente podem ler esse token. O token também fica registado na transcrição. É essa a falha descrita em manter segredos fora dos agentes de IA.

Um gateway de autenticação divide a credencial em duas partes. O gateway armazena a credencial do fornecedor e executa o fluxo OAuth. O agente recebe um token de runtime válido apenas para o gateway. Quando o agente chama uma ação, o gateway carrega a credencial armazenada, injeta-a no pedido de saída no lado do servidor e devolve apenas o corpo da resposta. O agente nunca recebe o access token do fornecedor. Assim, uma transcrição do agente que seja divulgada custa-lhe um único token de runtime revogável, e não a sua conta do GitHub.

O catálogo anuncia mais de 1,000 fornecedores e 10,000 ações predefinidas. Estes valores são do próprio projeto e não podem ser verificados externamente. O que pode ser verificado é a estrutura: um endpoint HTTP por ação, uma ligação armazenada por fornecedor e um token por agente.

Por que fazer self-hosting do Open Connector em vez de usar um serviço de connector alojado

Um serviço de connector alojado faz o mesmo trabalho e armazena os refresh tokens de todos os providers que liga a ele. Um refresh token do Google ou do GitHub é uma chave de longa duração para o seu email e os seus repositórios e normalmente continua válido depois de uma alteração da palavra-passe. Uma violação desse serviço torna-se uma violação sua. O self-hosting coloca esses registos numa base de dados SQLite num computador que arrenda e administra, protegida por uma chave que nunca sai da sua máquina.

Considere o custo antes de começar. Este VPS passa a ser o servidor mais valioso que administra. Ele armazena credenciais ativas de uma dúzia de serviços num único ficheiro. Por isso, deve receber o mesmo tratamento que um host de um gestor de palavras-passe: uma firewall que expõe apenas a porta 443, nenhuma conta partilhada, uma cópia de segurança que tenha realmente restaurado pelo menos uma vez e um alerta quando deixar de responder. Se não colocaria o seu cofre de palavras-passe neste computador, também não coloque o connector nele.

Fixe uma versão antes de instalar qualquer componente

O Open Connector é recente. O repositório surgiu pela primeira vez em 29 June 2026 e, em 1 August 2026, a versão mais recente com tag é v1.3.3, publicada em 30 July 2026 e também identificada com a tag latest. O registry publica igualmente uma tag tip, criada a partir do commit mais recente em main.

Num projeto tão recente, as tags móveis mudam com frequência. Um docker compose pull que avance duas versões pode alterar um endpoint de que o seu agente depende, e acabará por passar a noite a depurar o problema como se fosse um erro do agente. Fixe a imagem numa tag de versão e atualize quando decidir fazê-lo, depois de ler as notas da versão.

Implemente o Open Connector atrás de TLS no seu próprio VPS

Antes de iniciar o contentor, precisa de:

  • Docker com o plugin Compose, no Ubuntu 24.04 ou numa versão próxima
  • um nome de host cujo registo A aponte para este VPS, por exemplo connect.example.com
  • um reverse proxy que já faça a terminação TLS (transport layer security) para esse nome de host
  • dois segredos aleatórios, gerados abaixo

O guia Reverse proxy Traefik para várias aplicações Docker Compose explica a configuração do proxy. A configuração dos certificados, do início ao fim para uma única aplicação, está no guia n8n num VPS com Docker e HTTPS.

Gere primeiro os segredos. A chave de encriptação protege as credenciais armazenadas. O token de administrador protege a consola web e toda a superfície /api. Nenhum dos dois tem um valor predefinido, e o runtime arranca normalmente sem eles.

mkdir -p ~/open-connector && cd ~/open-connector
umask 077
printf 'OOMOL_CONNECT_ENCRYPTION_KEY=%s\n' "$(openssl rand -base64 32)" > .env
printf 'OOMOL_CONNECT_ADMIN_TOKEN=%s\n' "$(openssl rand -base64 32)" >> .env
chmod 600 .env

Copie já os dois valores para o seu gestor de palavras-passe, antes do primeiro arranque. A chave de encriptação não pode ser recuperada, e a razão está na lista de falhas mais abaixo.

Agora compose.yaml. Difere do exemplo a montante em dois pontos, e ambos são importantes.

services:
  connector:
    image: ghcr.io/oomol-lab/open-connector:v1.3.3
    restart: unless-stopped
    ports:
      - "127.0.0.1:3000:3000"
    volumes:
      - connector-data:/app/data
    environment:
      OOMOL_CONNECT_DATA_DIR: /app/data
      OOMOL_CONNECT_ORIGIN: "https://connect.example.com"
      OOMOL_CONNECT_ENCRYPTION_KEY: "${OOMOL_CONNECT_ENCRYPTION_KEY:?set this in .env}"
      OOMOL_CONNECT_ADMIN_TOKEN: "${OOMOL_CONNECT_ADMIN_TOKEN:?set this in .env}"

volumes:
  connector-data:

A primeira alteração é a tag fixada, em vez de latest. A segunda é a porta. O ficheiro a montante publica 3000:3000, que faz bind em todas as interfaces do host. O Docker escreve as portas publicadas na tabela NAT (network address translation) antes de o chain de filtragem do ufw ver o pacote. Por isso, ufw deny 3000 não fecha essa porta. Esta é a armadilha descrita em por que as portas do Docker contornam o ufw. Escrever 127.0.0.1:3000:3000 publica apenas na interface de loopback, e o reverse proxy liga-se a partir do mesmo host.

O :? marca cada variável como obrigatória. Assim, a stack recusa arrancar quando .env está em falta, em vez de arrancar com as credenciais sem encriptação. Manter os valores em .env, em vez de no ficheiro Compose, é o padrão apresentado em ficheiros env e segredos do Docker Compose.

docker compose up -d
docker compose logs -n 30 connector
curl -s http://127.0.0.1:3000/health
sudo ss -tlnp | grep 3000

/health responde { "ok": true } quando o runtime está ativo. ss tem de mostrar 127.0.0.1:3000. Uma linha com 0.0.0.0:3000 significa que o mapeamento da porta ainda é o do exemplo a montante e que o gateway está a responder diretamente para toda a Internet. Uma ligação recusada na verificação de integridade significa que o contentor ainda não está a escutar. Nesse caso, leia os logs antes de alterar o proxy.

Etiquetas do Traefik para o mesmo serviço
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.connector.rule=Host(`connect.example.com`)"
      - "traefik.http.routers.connector.entrypoints=websecure"
      - "traefik.http.routers.connector.tls.certresolver=le"
      - "traefik.http.services.connector.loadbalancer.server.port=3000"

Quando o Traefik é executado no Docker no mesmo host, ligue este serviço à rede do Traefik e elimine o bloco ports:, porque o Traefik chega ao contentor através da rede interna e não é necessário publicar nada no host. certresolver=le tem de corresponder ao nome do resolver na configuração estática do Traefik. Caso contrário, o router inicia sem certificado.

Por que o OAuth exige um nome de host real

OOMOL_CONNECT_ORIGIN é a configuração que as pessoas ignoram, e isso quebra o OAuth de uma forma que parece um erro do provedor. O runtime cria o URI de redirecionamento a partir dessa origem, no formato <origin>/oauth/callback. Se não for definida, a origem assume o valor http://localhost:3000. Assim, o runtime envia ao provedor um URI de redirecionamento http://localhost:3000/oauth/callback, enquanto a aplicação OAuth tem https://connect.example.com/oauth/callback registado. As duas strings são diferentes, por isso o GitHub responde:

The redirect_uri MUST match the registered callback URL for this application.

Um provedor OAuth redireciona o navegador de volta para esse URI. Portanto, o URI tem de ser um endereço acessível a partir da Internet. Os provedores rejeitam http:// simples para qualquer endereço que não seja localhost. Essa é a razão pela qual esta implantação precisa de um nome de host e de um certificado. Defina a origem antes da primeira inicialização, porque o valor é lido no arranque. Depois de editar .env ou compose.yaml, execute docker compose up -d novamente para aplicar a alteração.

Conecte o primeiro provider através de OAuth

Crie primeiro a aplicação OAuth no provider. No GitHub, o caminho é Settings, depois Developer settings, depois OAuth Apps e, por fim, New OAuth App. Defina o URL de callback de autorização como https://connect.example.com/oauth/callback. Guarde o client ID e o client secret.

Cada chamada /api transporta o token de administrador, por isso exporte-o uma vez para a sessão da shell.

export ADMIN_TOKEN='paste-the-admin-token'
curl -s https://connect.example.com/api/oauth/configs \
  -H "authorization: Bearer $ADMIN_TOKEN"

Essa listagem mostra o URI de redirecionamento que o runtime espera para cada provider. É a forma mais rápida de confirmar que a sua origem foi aplicada. Se continuar a indicar localhost, o contentor está a executar com o valor antigo e o fluxo OAuth falhará no último passo.

Guarde as credenciais do cliente e inicie uma autorização.

curl -s -X PUT https://connect.example.com/api/oauth/configs/github \
  -H "authorization: Bearer $ADMIN_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"clientId":"...","clientSecret":"..."}'

curl -s -X POST https://connect.example.com/api/oauth/authorizations \
  -H "authorization: Bearer $ADMIN_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"service":"github"}'

A segunda chamada devolve um authorizationUrl. Abra-o num browser, aprove os scopes e o provider devolverá o browser para /oauth/callback. Nesse ponto, o runtime troca o código e guarda a credencial. A consola web na sua origem executa os mesmos passos através de um formulário, usando o mesmo token de administrador. Os providers que utilizam uma chave de API simples não precisam de nada disto: PUT /api/connections/<service> com {"authType":"api_key","values":{"apiKey":"..."}} guarda diretamente a chave.

Atribua a cada agente um token de runtime, nunca a credencial

O agente autentica-se no gateway com um token de runtime, que a API de administração emite.

curl -s -X POST https://connect.example.com/api/runtime-tokens \
  -H "authorization: Bearer $ADMIN_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"name":"research-agent"}'

A resposta contém um token iniciado por oct_. Emita um token por agente e atribua-lhe o nome desse agente, porque revogar um token que não consegue identificar significa revogar todos. Depois, o agente chama as ações através de HTTP normal.

curl -s -X POST https://connect.example.com/v1/actions/github.get_current_user \
  -H "authorization: Bearer oct_..." \
  -H 'content-type: application/json' \
  -d '{"input":{}}'

Uma resposta válida é um envelope cujo campo success é true, com o payload do fornecedor em data. O token do GitHub não aparece em nenhum ponto dessa resposta. Num cliente MCP, aponte-o para https://connect.example.com/mcp com o mesmo cabeçalho bearer. O gateway disponibiliza ferramentas de descoberta como search_actions e execute_action, em vez de uma ferramenta por API, o que mantém reduzida a lista de ferramentas do agente. Executar servidores MCP numa VPS aborda o lado do cliente dessa configuração.

Faça mais uma verificação antes de considerar o trabalho concluído. Repita a chamada da ação depois de eliminar o cabeçalho authorization. O quickstart do próprio projeto chama /v1 sem qualquer bearer. Por isso, uma instalação sem autenticação de runtime configurada executará ações para qualquer pessoa que consiga alcançar a porta. Se a chamada não autenticada for bem-sucedida, tem duas opções: configurar tokens de runtime e confirmar que a chamada anónima falha, ou restringir /api, /v1 e /mcp no reverse proxy aos endereços de onde os seus agentes se ligam. Apenas /oauth/callback tem de permanecer aberto ao mundo, porque esse é o único caminho de que o redirecionamento do navegador de um fornecedor precisa.

Reduza a lista de ações ao necessário para o agente

Um gateway com mil provedores por trás dele oferece uma superfície ampla a um modelo de linguagem. Essa superfície aumenta assim que o modelo começa a ler texto que não escreveu, porque uma página devolvida pela sua própria instância do SearXNG em resposta às pesquisas Web do agente pode conter instruções destinadas a qualquer ação que o agente possa executar. A mesma contenção que faz um agente de programação aplicar a menor alteração funcional também deve ser usada nas permissões: conceda apenas as poucas ações de que o trabalho realmente precisa, e nada além disso. Dois controlos reduzem essa superfície.

OOMOL_CONNECT_ALLOWED_ACTIONS aceita uma lista de permissões separada por vírgulas e reconhece service.* e *. OOMOL_CONNECT_BLOCKED_ACTIONS é a lista de bloqueios, que tem precedência. Definir a lista de permissões como github.get_current_user,github.list_issues significa que todas as outras ações são recusadas, independentemente do que o agente solicitar. Essa é a diferença entre um erro e um incidente. Os tokens de execução têm as suas próprias regras de ações, além das regras globais, e a respetiva lista allowedProxies começa vazia. Por isso, POST /v1/proxy/:service é recusado até ser concedido. Esse endpoint de proxy encaminha uma solicitação bruta para um provedor com as suas credenciais anexadas. Deixe-o vazio, a menos que um agente específico precise dele.

OOMOL_CONNECT_ALLOW_PRIVATE_NETWORK tem o valor predefinido false. Isso impede que uma ligação a um provedor self-hosted aponte para um endereço privado, como o serviço de metadados da cloud em 169.254.169.254 ou a sua base de dados na mesma rede. Deixe-o desativado. Ative-o apenas para um provedor alojado por si.

Faça backup do servidor que armazena todos os tokens

Há duas coisas importantes, e cada uma é inútil sem a outra. O banco de dados em /app/data/connect.sqlite, dentro do volume connector-data, armazena as credenciais seladas. A chave de encriptação em .env remove a selagem. Um backup do volume sem a chave não restaura nada, e a chave sem o volume também não restaura nada. Por isso, a chave deve ficar no seu gestor de palavras-passe, e o volume deve fazer parte da sua rotação normal de backups.

Pare o contentor enquanto copia o ficheiro SQLite. Uma cópia feita durante uma operação de escrita pode restaurar um banco de dados corrompido.

docker volume ls | grep connector-data
docker compose stop connector
docker run --rm -v open-connector_connector-data:/data -v "$PWD":/backup alpine \
  tar czf /backup/connector-data.tgz -C /data .
docker compose start connector

O nome do volume é o diretório do seu projeto mais _connector-data. É por isso que o primeiro comando aparece aqui: cole o nome real no terceiro comando. Envie o arquivo para fora do VPS usando backups restic de um VPS. O restic encripta o arquivo antes de o enviar, porque esse arquivo é o armazenamento de credenciais.

O runtime mantém as execuções recentes de ações como registros de auditoria, 5,000 por padrão. Assim, o console pode indicar qual agente executou cada ação e quando. Esse log é o primeiro recurso a consultar quando um agente se comporta de forma estranha. Aponte também uma página de estado do Uptime Kuma para https://connect.example.com/health. Quando o gateway deixa de responder, os agentes falham de formas difíceis de interpretar. Saber que o gateway está indisponível evita perder uma hora a analisar a saída dos agentes.

O que falha e a mensagem que verá

redirect_uri_mismatch no fornecedor. A origem e o URL de callback registado são diferentes. Compare a cadeia exata de /api/oauth/configs com as definições da aplicação no fornecedor, incluindo https e http e qualquer barra final.

Cada chamada /api devolve 401. O cabeçalho do token de administração está em falta ou foi escrito incorretamente. O cabeçalho é Authorization: Bearer <token>, e a consola Web pede o mesmo token.

O contentor está em execução e as credenciais ficam em texto simples. Isto acontece quando OOMOL_CONNECT_ENCRYPTION_KEY nunca chega ao contentor, porque o runtime armazena os registos de credenciais sem encriptação em vez de impedir o arranque. Confirme isto na sua própria instalação: ligue um fornecedor com uma chave de API que consiga identificar e procure-a na base de dados.

docker compose cp connector:/app/data/connect.sqlite /tmp/connect.sqlite
grep -c 'github_pat_' /tmp/connect.sqlite
shred -u /tmp/connect.sqlite

Uma contagem superior a 0 significa que a chave não está a ser aplicada. Confirme que .env está no mesmo diretório que compose.yaml e que docker compose config mostra o valor. Com a chave definida, a mesma pesquisa devolve 0, porque o registo está selado com AES-256-GCM (advanced encryption standard, chave de 256 bits, modo Galois/counter).

Nada é desencriptado depois de uma restauração. A chave de encriptação foi alterada ou perdeu-se. Por conceção, nunca é escrita junto dos dados. Por isso, não existe um procedimento de recuperação e nenhum pedido de suporte resolve o problema. Ligue novamente todos os fornecedores. A rotação é suportada através de uma variável de chave separada e de um comando de dados no runtime. Leia as notas da versão atual antes de iniciar qualquer rotação.

O agente devolve um erro que menciona uma ação visível no catálogo. A descoberta e a execução são operações separadas. Uma ação pode aparecer em search_actions e, ainda assim, ser recusada por OOMOL_CONNECT_ALLOWED_ACTIONS, pela denylist ou pelas próprias regras desse token do runtime.

Atualizações. Faça uma cópia de segurança do volume, edite a tag da imagem para a nova versão e, em seguida, docker compose pull && docker compose up -d. Monitorize docker compose logs -n 50 connector à procura de uma linha de migração e execute novamente a verificação de integridade e uma ação real antes de voltar a confiar no sistema. Reverter significa repor a tag antiga. Isto só funciona porque a tag foi fixada.

FAQ

Preciso de um domínio público para alojar o Open Connector?

Para fornecedores que usam uma chave de API, não: um gateway em 127.0.0.1 é suficiente. Para OAuth, na prática, sim. O fornecedor redireciona um navegador para o seu URL de callback, por isso esse URL tem de ser resolvido a partir da Internet pública, e os fornecedores recusam http:// simples fora de localhost. Defina OOMOL_CONNECT_ORIGIN como o seu nome de host https:// antes do primeiro arranque e registe <origin>/oauth/callback na aplicação OAuth do fornecedor.

O que acontece se eu perder a chave de encriptação do Open Connector?

Não é possível desencriptar as credenciais armazenadas e não existe recuperação. A chave nunca é armazenada juntamente com os dados, por conceção, pelo que ninguém que tenha a base de dados a pode ler, incluindo você. A única opção é definir uma nova chave e voltar a ligar todos os fornecedores. Mantenha a chave num gestor de palavras-passe e a base de dados na sua rotação de cópias de segurança, porque uma reposição precisa de ambos.

O meu agente de IA pode ver o token de acesso do fornecedor?

Não quando faz chamadas através do gateway. O agente autentica-se com um token de execução que começa por oct_, e o gateway injeta a credencial do fornecedor no pedido de saída no servidor, devolvendo apenas a resposta. Há duas situações que quebram esta propriedade: o endpoint /v1/proxy/:service, que encaminha pedidos brutos com a sua credencial anexada e cujas concessões começam vazias por uma razão, e colar você próprio uma chave de API no agente, ignorando completamente o gateway.

O gateway deve estar acessível a partir da Internet pública?

Apenas /oauth/callback tem de estar acessível. Publique a porta do contentor em 127.0.0.1 para que as regras NAT do Docker não o possam expor para além da firewall e coloque o reverse proxy à frente. Depois, teste uma chamada de ação sem o cabeçalho authorization. Se funcionar, restrinja /api, /v1 e /mcp no proxy aos endereços usados pelos seus agentes, até que apenas as chamadas autenticadas funcionem.

O Open Connector está pronto para utilização em produção?

Está licenciado ao abrigo da Apache 2.0 e evolui rapidamente: o repositório surgiu em 29 June 2026 e a v1.3.3 foi lançada em 30 July 2026, por isso trate todos os números de versão deste guia como um retrato de 1 August 2026. Execute-o fixado numa etiqueta de lançamento, nunca em latest ou tip, leia as notas da versão antes de cada atualização e mantenha uma cópia de segurança de um volume que já tenha restaurado uma vez. O desenho é sólido para uma máquina que lhe pertença; o risco está na alteração frequente das versões, não na arquitetura.