SSD Nodes Learn 8GB di RAM — $66/anno
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-02

Open Connector self-hosted per agenti AI

Esegui Open Connector sul tuo VPS: immagine fissata, origine TLS, callback OAuth e backup. Gli agenti usano il gateway senza conservare token SaaS.

Cosa fa Open Connector per un agente AI

L'hosting autonomo di Open Connector inserisce un unico gateway di autenticazione tra gli agenti AI e tutte le API software as a service (SaaS) che chiamano. In questo modo l'agente non conserva mai un token del provider. È un gateway open source di OOMOL Lab, distribuito con licenza Apache 2.0. Viene eseguito in un unico container, conserva lo stato in un singolo file SQLite ed espone le azioni dei provider tramite HTTP e MCP (model context protocol).

Il problema inizia con la seconda integrazione. Ogni provider ha un proprio flusso OAuth (open authorization), una propria durata del refresh token e propri nomi per gli scope. Integrare manualmente cinque provider in un agente significa creare cinque gestori di redirect, cinque archivi di credenziali e cinque cicli di refresh che devono essere eseguiti prima della scadenza di un token. Quasi nessuno scrive questo codice. Si crea invece un personal access token a lunga durata per ogni servizio e lo si inserisce nella configurazione dell'agente, in un file di ambiente o direttamente nel prompt. Quel token può quindi essere letto da ogni tool eseguito dall'agente e finisce nella trascrizione. È questo il problema descritto da tenere i segreti fuori dagli agenti AI.

Un gateway di autenticazione separa la credenziale in due parti. Il gateway conserva la credenziale del provider ed esegue il flusso OAuth. L'agente riceve un token di runtime valido solo per il gateway. Quando l'agente chiama un'azione, il gateway carica la credenziale conservata, la inserisce nella richiesta in uscita dal lato server e restituisce solo il corpo della risposta. L'agente non riceve mai l'access token del provider. Una trascrizione dell'agente che viene divulgata compromette quindi un solo token di runtime revocabile, non l'account GitHub.

Il catalogo dichiara più di 1,000 provider e 10,000 azioni predefinite. Questo dato proviene dal progetto e non può essere verificato dall'esterno. È invece possibile verificarne la struttura: un endpoint HTTP per ogni azione, una connessione conservata per ogni provider e un token per ogni agente.

Perché ospitare autonomamente Open Connector invece di usare un servizio di connettori gestito

Un servizio di connettori gestito svolge lo stesso lavoro e conserva i token di aggiornamento per ogni provider a cui lo colleghi. Un token di aggiornamento per Google o GitHub è una chiave a lunga durata per accedere alla posta e ai repository e, di solito, resta valido anche dopo la modifica della password. Se il loro servizio viene compromesso, viene compromesso anche il tuo accesso. L'hosting autonomo sposta questi dati in SQLite su una macchina che noleggi e amministri, protetti da una chiave che non lascia mai il tuo server.

Valuta esplicitamente il costo prima di iniziare. Questo VPS diventa il server più importante che gestisci. Contiene le credenziali operative per una dozzina di servizi in un unico file, quindi richiede lo stesso livello di protezione di un host per un gestore di password: un firewall che espone solo la porta 443, nessun accesso condiviso, un backup che hai effettivamente ripristinato almeno una volta e un avviso quando il server smette di rispondere. Se non metteresti il tuo archivio di password su questa macchina, non metterci neppure il connettore.

Blocca una versione prima di installare qualsiasi componente

Open Connector è recente. Il repository è comparso per la prima volta il 29 giugno 2026 e, al 1 agosto 2026, la release con il tag più recente è v1.3.3, pubblicata il 30 luglio 2026 e contrassegnata anche con il tag latest. Il registry pubblica inoltre un tag tip, creato a partire dal commit più recente su main.

In un progetto così recente, i tag mobili cambiano spesso. Un docker compose pull che passa da una release all'altra può modificare un endpoint da cui dipende il tuo agent, e passerai la serata a eseguire il debug attribuendo il problema all'agent. Blocca l'immagine su un tag di release ed esegui l'upgrade quando lo decidi, dopo aver letto le note di rilascio.

Eseguire Open Connector dietro TLS sul proprio VPS

Prima dell'avvio del container sono necessari:

  • Docker con il plugin Compose, su Ubuntu 24.04 o una versione simile
  • un hostname il cui record A punti a questo VPS, ad esempio connect.example.com
  • un reverse proxy che termini già TLS (Transport Layer Security) per quell'hostname
  • due segreti casuali, generati di seguito

La guida reverse proxy Traefik per più applicazioni Docker Compose illustra la configurazione del proxy. La guida n8n su un VPS con Docker e HTTPS descrive la stessa configurazione dei certificati dall'inizio alla fine per una singola applicazione.

Generare prima i segreti. La chiave di crittografia protegge le credenziali archiviate. Il token amministratore protegge la console web e l'intera superficie /api. Nessuno dei due ha un valore predefinito e il runtime si avvia comunque senza di essi.

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

Copiare subito entrambi i valori nel password manager, prima del primo avvio. Non è possibile recuperare la chiave di crittografia. Il motivo è spiegato più avanti nell'elenco degli errori.

Ora compose.yaml. Differisce dall'esempio upstream in due punti, ed entrambi sono importanti.

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:

La prima modifica è il tag bloccato invece di latest. La seconda riguarda la porta. Il file upstream pubblica 3000:3000, associandola a tutte le interfacce dell'host. Docker scrive le porte pubblicate nella tabella NAT (Network Address Translation) prima che il pacchetto raggiunga la catena di filtraggio ufw. Di conseguenza, ufw deny 3000 non chiude quella porta: questo è il problema descritto in perché le porte Docker bypassano ufw. Scrivendo 127.0.0.1:3000:3000, la porta viene pubblicata solo sull'interfaccia loopback e il reverse proxy si connette dallo stesso host.

:? indica ogni variabile come obbligatoria. In questo modo lo stack rifiuta di avviarsi quando manca .env, invece di avviarsi con le credenziali non crittografate. Conservare i valori in .env anziché nel file Compose segue il modello descritto in file env e segreti di 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 verifica { "ok": true } quando il runtime è attivo. ss deve stampare 127.0.0.1:3000. Una riga con 0.0.0.0:3000 indica che la mappatura della porta è ancora quella upstream e che il gateway risponde direttamente all'intera Internet. Un rifiuto della connessione durante il controllo dello stato indica che il container non è ancora in ascolto. Leggere quindi i log prima di modificare il proxy.

Etichette Traefik per lo stesso servizio
    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 Traefik viene eseguito in Docker sullo stesso host, collegare questo servizio alla rete Traefik ed eliminare il blocco ports:. Traefik raggiunge infatti il container tramite la rete interna e non è necessario pubblicare alcuna porta sull'host. certresolver=le deve corrispondere al nome del resolver nella configurazione statica di Traefik. In caso contrario, il router viene avviato senza certificato.

Perché OAuth richiede un hostname reale

OOMOL_CONNECT_ORIGIN è l'impostazione che spesso viene ignorata. Se viene ignorata, OAuth non funziona e l'errore può sembrare un problema del provider. Il runtime costruisce l'URI di reindirizzamento a partire da quell'origine, nel formato <origin>/oauth/callback. Se non viene impostata, l'origine predefinita è http://localhost:3000. Di conseguenza, il runtime invia al provider l'URI di reindirizzamento http://localhost:3000/oauth/callback, mentre nell'app OAuth è registrato https://connect.example.com/oauth/callback. Le due stringhe sono diverse, quindi GitHub risponde:

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

Un provider OAuth reindirizza il browser a quell'URI. L'URI deve quindi essere un indirizzo raggiungibile dall'esterno. I provider rifiutano http:// semplice per qualsiasi destinazione diversa da localhost. Per questo questa distribuzione richiede un hostname e un certificato. Imposta l'origine prima del primo avvio, perché il valore viene letto all'avvio. Dopo aver modificato .env o compose.yaml, esegui di nuovo docker compose up -d per applicare la modifica.

Collega il primo provider tramite OAuth

Crea prima l'app OAuth presso il provider. Su GitHub, il percorso è Settings, poi Developer settings, quindi OAuth Apps e infine New OAuth App. Imposta l'URL di callback per l'autorizzazione su https://connect.example.com/oauth/callback. Conserva il client ID e il client secret.

Ogni chiamata /api include il token di amministrazione, quindi esportalo una volta per la sessione della shell.

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

Questo elenco mostra l'URI di reindirizzamento previsto dal runtime per ogni provider. È quindi il controllo più rapido per verificare che l'origine sia stata applicata. Se continua a mostrare localhost, il container è in esecuzione con il valore precedente e il flusso OAuth non riuscirà nell'ultimo passaggio.

Memorizza le credenziali del client, quindi avvia un'autorizzazione.

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"}'

La seconda chiamata restituisce un authorizationUrl. Aprilo in un browser, approva gli ambiti e il provider rimanda il browser a /oauth/callback. A questo punto il runtime scambia il codice e memorizza la credenziale. La console web all'origine segue gli stessi passaggi tramite un modulo, usando lo stesso token di amministrazione. I provider che usano una semplice API key ignorano tutto questo: PUT /api/connections/<service> con {"authType":"api_key","values":{"apiKey":"..."}} memorizza direttamente la chiave.

Assegna a ogni agente un token di runtime, mai la credenziale

L'agente esegue l'autenticazione al gateway con un token di runtime, generato dall'API di amministrazione.

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"}'

La risposta contiene un token che inizia con oct_. Emettine uno per ogni agente e assegnagli il nome dell'agente, perché revocare un token che non puoi identificare significa revocarli tutti. L'agente invoca quindi le azioni tramite HTTP ordinario.

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":{}}'

Una risposta corretta è un envelope il cui campo success è true, con il payload del provider in data. Il token GitHub non compare in alcun punto della risposta. Per un client MCP, indirizzalo a https://connect.example.com/mcp usando lo stesso header bearer; il gateway offre strumenti di discovery come search_actions e execute_action invece di uno strumento per ogni API, mantenendo così ridotto l'elenco degli strumenti dell'agente. Eseguire server MCP su un VPS illustra la parte relativa al client di questa configurazione.

Esegui un'ulteriore verifica prima di considerare conclusa la configurazione. Ripeti la chiamata all'azione dopo aver eliminato l'header authorization. Il quickstart del progetto invoca /v1 senza alcun bearer; pertanto, un'installazione in cui non è configurata l'autenticazione di runtime eseguirà le azioni per chiunque possa raggiungere la porta. Se la chiamata non autenticata ha esito positivo, hai due possibilità: configurare i token di runtime e verificare che la chiamata anonima ora fallisca, oppure limitare /api, /v1 e /mcp nel reverse proxy agli indirizzi da cui provengono gli agenti. Solo /oauth/callback deve rimanere aperto a Internet, perché è l'unico percorso necessario al redirect del browser del provider.

Ridurre l'elenco delle azioni a quelle necessarie all'agente

Un gateway con mille provider disponibili offre a un modello linguistico una superficie di attacco ampia. Due controlli la restringono.

OOMOL_CONNECT_ALLOWED_ACTIONS accetta una lista di elementi consentiti separati da virgole e supporta service.* e *. OOMOL_CONNECT_BLOCKED_ACTIONS è la lista di elementi negati e ha la precedenza. Impostare la lista di elementi consentiti su github.get_current_user,github.list_issues significa rifiutare ogni altra azione, indipendentemente da ciò che richiede l'agente. Questa è la differenza tra un errore e un incidente. I token di runtime applicano regole sulle azioni aggiuntive rispetto a quelle globali. La relativa lista allowedProxies è inizialmente vuota, quindi POST /v1/proxy/:service viene rifiutata finché non la autorizzi. Quell'endpoint proxy inoltra una richiesta non elaborata a un provider usando le tue credenziali. Lascialo quindi vuoto, a meno che non sia necessario per un agente specifico.

OOMOL_CONNECT_ALLOW_PRIVATE_NETWORK è impostato per impostazione predefinita su false. Impedisce a una connessione a un provider self-hosted di puntare a un indirizzo privato, ad esempio il servizio di metadati cloud su 169.254.169.254 o il database sulla stessa rete. Lascialo disattivato. Attivalo solo per un provider gestito direttamente da te.

Eseguire il backup del volume che contiene tutti i token

Contano due elementi, e ciascuno è inutilizzabile senza l'altro. Il database in /app/data/connect.sqlite, all'interno del volume connector-data, contiene le credenziali sigillate. La chiave di cifratura in .env le sblocca. Un backup del volume senza la chiave non consente di ripristinare nulla, e la chiave senza il volume non consente di ripristinare nulla. Perciò la chiave deve essere conservata nel password manager e il volume deve rientrare nella normale rotazione dei backup.

Arrestare il container mentre si copia il file SQLite, perché una copia eseguita durante un'operazione di scrittura può essere ripristinata come database danneggiato.

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

Il nome del volume è la directory del progetto seguita da _connector-data. Per questo il primo comando si trova lì: incollare il nome effettivo nel terzo comando. Trasferire l'archivio fuori dal VPS usando backup restic da un VPS. restic lo cifra prima del trasferimento, perché l'archivio contiene il repository delle credenziali.

Il runtime conserva le esecuzioni recenti delle attività come record di audit, 5,000 per impostazione predefinita. In questo modo la console può indicare quale agente ha eseguito ogni attività e quando. Questo log è il primo elemento da esaminare quando un agente si comporta in modo anomalo. Configurare anche una pagina di stato Uptime Kuma per https://connect.example.com/health. Quando il gateway smette di rispondere, gli agenti hanno errori difficili da interpretare. Sapere che il gateway è inattivo evita un'ora di analisi dell'output degli agenti.

Cosa si rompe e quale messaggio verrà visualizzato

redirect_uri_mismatch presso il provider. L'origine e l'URL di callback registrato non corrispondono. Confronta la stringa esatta di /api/oauth/configs con le impostazioni dell'app presso il provider, inclusi https e http e l'eventuale barra finale.

Ogni chiamata /api restituisce 401. L'header del token amministrativo manca oppure contiene un errore di ortografia. L'header è Authorization: Bearer <token> e la console web richiede lo stesso token.

Il container è in esecuzione e le credenziali sono memorizzate in testo in chiaro. Questo accade quando OOMOL_CONNECT_ENCRYPTION_KEY non raggiunge il container, perché il runtime memorizza i record delle credenziali senza crittografia invece di rifiutarsi di avviarsi. Verificalo nella tua installazione: collega un provider con una API key che puoi riconoscere, quindi cerca la chiave nel database.

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

Un conteggio superiore a 0 indica che la chiave non è applicata. Verifica quindi che .env si trovi nella stessa directory di compose.yaml e che docker compose config mostri il valore. Quando la chiave è impostata, la stessa ricerca restituisce 0, perché il record è protetto con AES-256-GCM (Advanced Encryption Standard, chiave a 256 bit, modalità Galois/counter).

Dopo un ripristino non viene decrittografato nulla. La chiave di crittografia è cambiata oppure è stata persa. Per progettazione, non viene mai scritta accanto ai dati. Non esiste quindi alcun percorso di ripristino e nessun ticket di supporto può risolvere il problema. Ricollega ogni provider. La rotazione è supportata tramite una variabile separata per la chiave e un comando dati nel runtime. Leggi quindi le note sulla versione corrente prima di ruotare qualsiasi chiave.

L'agent restituisce un errore che indica un'azione visibile nel catalogo. Rilevamento ed esecuzione sono separati. Un'azione può apparire in search_actions e venire comunque rifiutata da OOMOL_CONNECT_ALLOWED_ACTIONS, dalla denylist o dalle regole proprie del token del runtime.

Aggiornamenti. Esegui il backup del volume, modifica l'image tag impostandolo sulla nuova release, quindi docker compose pull && docker compose up -d. Monitora docker compose logs -n 50 connector per individuare una riga relativa alla migrazione, quindi esegui di nuovo il controllo di integrità e un'azione reale prima di considerare il sistema nuovamente affidabile. Per eseguire il rollback, ripristina il vecchio tag. Funziona solo perché lo hai fissato.

FAQ

È necessario un dominio pubblico per eseguire autonomamente Open Connector?

Per i provider che usano una chiave API, no: è sufficiente un gateway su 127.0.0.1. Per OAuth, invece, nella pratica sì. Il provider reindirizza un browser all'URL di callback, quindi l'URL deve essere risolvibile da Internet pubblico, e i provider rifiutano http:// in chiaro al di fuori di localhost. Imposta OOMOL_CONNECT_ORIGIN sul tuo hostname https:// prima del primo avvio e registra <origin>/oauth/callback nell'app OAuth del provider.

Cosa succede se perdo la chiave di cifratura di Open Connector?

Le credenziali memorizzate non possono essere decifrate e non esiste alcun recupero. La chiave non viene mai memorizzata insieme ai dati, quindi nessuno può leggere il database, nemmeno tu. L'unica opzione consiste nell'impostare una nuova chiave e ricollegare ogni provider. Conserva la chiave in un gestore di password e includi il database nella rotazione dei backup, perché per un ripristino servono entrambi.

Il mio agente AI può vedere il token di accesso del provider?

Non quando effettua le chiamate tramite il gateway. L'agente esegue l'autenticazione con un token di runtime che inizia con oct_, mentre il gateway inserisce la credenziale del provider nella richiesta in uscita sul server e restituisce solo la risposta. Questa proprietà viene meno in due casi: l'endpoint /v1/proxy/:service, che inoltra richieste non elaborate con la credenziale associata e i cui permessi iniziano vuoti per un motivo preciso, e l'inserimento manuale di una chiave API nell'agente, che aggira completamente il gateway.

Il gateway deve essere raggiungibile da Internet pubblico?

Deve esserlo solo /oauth/callback. Pubblica la porta del container su 127.0.0.1, in modo che le regole NAT di Docker non possano esporla oltre il firewall, e posiziona il reverse proxy davanti al gateway. Quindi testa una chiamata a un'azione senza l'header authorization. Se la chiamata riesce, limita /api, /v1 e /mcp nel proxy agli indirizzi usati dai tuoi agenti, finché le uniche chiamate funzionanti non saranno quelle autenticate.

Open Connector è pronto per l'uso in produzione?

È distribuito con licenza Apache 2.0 e lo sviluppo procede rapidamente: il repository è comparso il 29 giugno 2026 e la versione v1.3.3 è stata rilasciata il 30 luglio 2026, quindi considera ogni numero di versione in questa guida come un'istantanea del 1 agosto 2026. Eseguilo fissando un release tag, mai su latest o tip, leggi le note di rilascio prima di ogni aggiornamento e conserva un backup del volume che hai già ripristinato almeno una volta. Il design è solido per un sistema che gestisci direttamente; il rischio riguarda il rapido susseguirsi delle versioni, non l'architettura.