SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-25

Hospede o Open Connector para agentes de IA

Execute o gateway OAuth do Open Connector no seu VPS, com imagem fixada, origem TLS, callbacks OAuth e backups do SQLite, sem expor tokens SaaS aos agentes.

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 estes utilizam. Assim, o agente nunca guarda um token do fornecedor. É um gateway open source da OOMOL Lab, licenciado ao abrigo da Apache 2.0. É executado como um único contentor, guarda 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 escopos. Integrar manualmente cinco fornecedores num agente implica cinco handlers de redirecionamento, cinco repositórios 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, gera um personal access token de longa duração para cada serviço e cola-o na configuração do agente, num ficheiro de ambiente ou no próprio prompt. Esse token pode então ser lido por todas as ferramentas executadas pelo agente e fica registado na transcrição. É esta falha que manter segredos fora dos agentes de IA descreve.

Um gateway de autenticação separa a credencial em duas partes. O gateway guarda 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 guardada, 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 divulgada custa-lhe um único token de runtime revogável, e não a sua conta 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 guardada por fornecedor e um token por agente. Se a parte relacionada com agentes ainda for nova e termos como tool call ou MCP server ainda não estiverem consolidados, o percurso gradual em como aprender agentes de IA desde o início explica o ciclo, as ferramentas e as práticas de segurança que um gateway deste tipo pressupõe que já conhece.

Por que alojar o Open Connector por conta própria em vez de usar um serviço de conectores alojado

Um serviço de conectores alojado faz o mesmo trabalho e guarda os refresh tokens de todos os fornecedores que liga ao serviço. Um refresh token do Google ou do GitHub é uma chave de longa duração para o seu correio e os seus repositórios e, normalmente, continua válido depois de alterar a palavra-passe. Se esse serviço for comprometido, o seu ambiente também fica comprometido. O alojamento por conta própria coloca esses registos numa base de dados SQLite num computador que aluga e administra, protegida por uma chave que nunca sai da sua máquina.

Avalie o custo antes de começar. Este VPS passa a ser o servidor mais valioso que administra. Guarda credenciais válidas de uma dúzia de serviços num único ficheiro, por isso exige o mesmo tratamento que daria a um servidor 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 já tenha restaurado pelo menos uma vez e um alerta quando o servidor deixa de responder. Se não colocaria o seu cofre de palavras-passe nesta máquina, também não coloque o conector nela.

Fixe uma versão antes de instalar qualquer coisa

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

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

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

Antes de iniciar o container, você precisa de:

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

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

Gere primeiro os secrets. A chave de encriptação protege as credenciais armazenadas. O token de administrador protege o console web e toda a superfície /api. Nenhum dos dois tem valor padrão, e o runtime inicia 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 agora os dois valores para o seu gestor de passwords, antes da primeira inicialização. A chave de encriptação não tem mecanismo de recuperação, e o motivo está na lista de falhas mais abaixo.

Agora compose.yaml. Ele difere do exemplo upstream 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 upstream 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 que a cadeia de filtros do ufw veja o pacote. Por isso, ufw deny 3000 não fecha essa porta. Essa é a armadilha descrita em por que as portas do Docker ignoram 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 iniciar quando .env está ausente, em vez de iniciar com as credenciais sem encriptação. Manter os valores em .env, em vez de no ficheiro Compose, segue o padrão descrito em ficheiros env e secrets 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 deve imprimir 127.0.0.1:3000. Uma linha com 0.0.0.0:3000 significa que o mapeamento de portas ainda é o do upstream e que o gateway está a responder diretamente para toda a Internet. Uma ligação recusada no health check significa que o container ainda não está a escutar. Consulte os logs antes de alterar o proxy.

Labels 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 alcança o container pela 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 é iniciado sem certificado.

Porque o OAuth exige um nome de host real

OOMOL_CONNECT_ORIGIN é a definição que as pessoas ignoram, e ignorá-la quebra o OAuth de uma forma que parece um erro do provider. 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 provider 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 provider OAuth redireciona o browser de volta para esse URI. Por isso, o URI tem de ser um endereço acessível a partir da Internet. Os providers rejeitam http:// simples para qualquer endereço que não seja localhost. Essa é a razão pela qual esta implementação precisa de um nome de host e de um certificado. Defina a origem antes do primeiro arranque, porque o valor é lido durante o arranque. Depois de editar .env ou compose.yaml, execute docker compose up -d novamente para aplicar a alteração.

Conecte o primeiro provider por 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 a URL de callback de autorização como https://connect.example.com/oauth/callback. Guarde o client ID e o client secret.

Cada chamada /api inclui 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 origem foi aplicada. Se ainda indicar localhost, o container está a executar com o valor antigo e o fluxo OAuth falhará no último passo.

Armazene 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 redirecionará o browser para /oauth/callback. Nesse ponto, o runtime troca o código e armazena 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 usam uma API key simples ignoram todo este processo: PUT /api/connections/<service> com {"authType":"api_key","values":{"apiKey":"..."}} armazena a chave diretamente.

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

O agente autentica-se no gateway com um token de runtime, emitido pela API de administração.

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 inclui um token que começa 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 saudável é um envelope cujo campo success tem o valor true, com o payload do provedor 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 pequena 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. Assim, uma instalação sem autenticação de runtime configurada executará ações para qualquer pessoa que consiga alcançar a porta. Se a chamada sem autenticação for bem-sucedida, existem duas soluções: configurar tokens de runtime e confirmar que a chamada anónima passa a falhar, 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 para a Internet, porque esse é o único caminho de que o redirecionamento do browser do provedor necessita.

Reduza a lista de ações ao que o agente precisa

Um gateway com mil provedores por trás oferece uma superfície ampla para 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 SearXNG que responde às pesquisas web do agente pode conter instruções destinadas às ações disponíveis para o agente. 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 o conjunto reduzido de ações de que a tarefa realmente precisa, sem nada além disso. Há dois controlos para limitar esse acesso.

OOMOL_CONNECT_ALLOWED_ACTIONS aceita uma lista de permissões separada por vírgulas e compreende service.* e *. OOMOL_CONNECT_BLOCKED_ACTIONS é a lista de bloqueios, e a lista de bloqueios tem prioridade. 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 runtime têm as suas próprias regras de ações, além das regras globais, e a lista allowedProxies começa vazia. Por isso, POST /v1/proxy/:service é recusada até que lhe conceda permissão. 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 assume o valor false. Isso impede que uma ligação a um provedor autoalojado 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. Mantenha-o desativado. Ative-o apenas para um provedor que aloja sob o seu controlo.

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 o selamento. 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 entrar na 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 ser restaurada como uma base de dados corrompida.

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 projeto seguido de _connector-data. É por isso que o primeiro comando aparece aqui: cole o nome real no terceiro comando. Envie o arquivo para fora do VPS com backups restic a partir de um VPS. O restic encripta o arquivo antes de o enviar, porque esse arquivo é o repositório de credenciais.

O runtime mantém as execuções recentes das ações como registos de auditoria, 5,000 por padrão. Assim, a consola pode indicar qual agente executou cada ação e quando. Esse registo é 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 confusas. Saber que o gateway está indisponível poupa uma hora de análise da saída dos agentes.

O que falha e a mensagem apresentada

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.

Todas as chamadas /api devolvem 401. O cabeçalho do token de administrador 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 recusar o arranque. Confirme isto na sua própria instalação: ligue um fornecedor com uma chave de API que consiga reconhecer 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

Um valor superior a 0 significa que a chave não está em vigor. Confirme que .env está no mesmo diretório que compose.yaml e que docker compose config apresenta o valor. Com a chave definida, a mesma pesquisa devolve 0, porque o registo está protegido 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 mudou ou foi perdida. Por conceção, nunca é escrita junto dos dados. Por isso, não existe um caminho de recuperação nem um pedido de suporte que resolva 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. Consulte as notas da versão atual antes de rodar qualquer chave.

O agente apresenta um erro que identifica 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, altere 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 volte a executar a verificação de estado e uma ação real antes de voltar a confiar no sistema. Reverter significa repor a tag antiga. Isto só funciona porque a fixou.

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 com o seu hostname 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?

As credenciais armazenadas não podem ser desencriptadas e não existe recuperação. A chave nunca é armazenada deliberadamente junto dos dados, por isso ninguém que tenha a base de dados consegue lê-la, incluindo você. A única opção é definir uma chave nova e voltar a ligar todos os fornecedores. Guarde a chave num gestor de palavras-passe e inclua 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 consegue 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. Duas situações quebram essa propriedade: o endpoint /v1/proxy/:service, que encaminha pedidos em bruto com a sua credencial anexada e cujas permissões começam vazias por uma razão, e colar uma chave de API no próprio agente, contornando 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 exponham para além da sua 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 uso em produção?

Está licenciado sob 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 considere todos os números de versão deste guia como um retrato de 1 August 2026. Execute-o fixado numa release tag, nunca em latest ou tip, leia as notas da release antes de cada atualização e mantenha uma cópia de segurança de um volume que já tenha restaurado uma vez. O design é sólido para um servidor que você controla; o risco está na mudança frequente das versões, não na arquitetura.