Come fare self-hosting di OpenSEO su Cloudflare
Guida completa, con i problemi reali che ho risolto — incluso un bug silenzioso su Google Search Console che sembrava un problema di token e non lo era.
Pubblicato: 31 agosto 2026
I tool SEO seri costano cari. Semrush e Ahrefs partono da un centinaio di euro al mese e salgono in fretta se ti servono davvero rank tracking, keyword research e audit tecnici insieme. Se sei un freelancer che sta iniziando, quella cifra fissa ogni mese, prima ancora di aver fatturato qualcosa, è spesso il motivo per cui rinunci a tracciare i contenuti o fai keyword research a occhio.
Configurare OpenSEO su Cloudflare non è stato immediato. Alcune sezioni della documentazione ufficiale danno per scontate cose che, se non hai mai gestito un deploy su Cloudflare o un flusso OAuth con Google, non sono affatto ovvie: mi sono bloccato più di una volta su passaggi che con due righe di spiegazione in più si sarebbero risolti in cinque minuti invece che in ore. Scrivo questa guida soprattutto per chi si affaccia per la prima volta a strumenti del genere. Se hai già dimestichezza con Workers e OAuth, salta pure alle sezioni che ti servono.
Cos'è OpenSEO
OpenSEO è un tool SEO open source (codice su GitHub), pensato come alternativa a Semrush e Ahrefs. La differenza principale è nel modello di costo: non paghi un abbonamento mensile fisso, paghi solo i dati che consumi tramite una chiave API DataForSEO tua.

Le funzioni principali:
- Keyword research: trovi le parole chiave giuste per un argomento, con volumi di ricerca e difficoltà.
- Rank tracking: monitori le posizioni delle tue pagine su Google nel tempo.
- Competitor Insights: vedi cosa fanno i tuoi competitor, quali keyword li portano traffico, dove sono più forti di te.
- Backlinks: analizzi chi linka un sito e la qualità di quei link.
- Site Audits: scansioni un sito per errori tecnici SEO (link rotti, meta tag mancanti, problemi di indicizzazione).
- AI Visibility: controlli come e quanto un sito viene citato dai motori di ricerca AI e dai modelli linguistici, non solo da Google.
Il progetto è pensato anche per lavorare insieme agli agenti AI: espone un server MCP (il protocollo che permette a un assistente come Claude di usare direttamente i tuoi dati e le tue funzioni, senza passare dall'interfaccia web) e delle skill pronte, cioè procedure guidate che l'agente segue per portare a termine un compito SEO.
C'è un vantaggio meno ovvio nell'appoggiarsi a DataForSEO come fonte dati. Google ha iniziato a instradare i link dei risultati di ricerca attraverso redirect google.com/goto, che offuscano l'URL reale nella SERP proprio per rendere più difficile a scraper e tool di terze parti leggerla, una mossa che sembra puntare in particolare a servizi come SerpApi. DataForSEO ha già trovato il modo di bypassare questo redirect, quindi il rank tracking e l'analisi SERP di OpenSEO continuano a restituire URL reali invece di link opachi. Non c'è garanzia che resti così se Google stringe ulteriormente, ma oggi è un punto a favore di chi si appoggia a DataForSEO invece che ad altri fornitori di dati SERP.
C'è anche una versione hosted a 10€/mese se non vuoi gestire nulla tu, su openseo.so. Questa guida però parla dell'altra strada: prendere il codice e farlo girare sulla tua infrastruttura.
Uno sguardo rapido alla dashboard
Prima di entrare nel setup, ecco cosa significa concretamente ognuna delle funzioni elencate sopra, presa dalla mia istanza self-hosted (nome del progetto/dominio del cliente oscurato per riservatezza).








Come scaricare OpenSEO
Il codice è su GitHub, repository every-app/open-seo. Lo clonerai nel passaggio 1 qui sotto. Se pensi di aggiornarlo spesso o di personalizzarlo, meglio partire da un tuo fork su GitHub e clonare quello, così hai un repository che controlli tu.
In entrambi i casi ti serve una chiave API DataForSEO, il servizio che fornisce i dati SEO veri e propri (volumi di ricerca, SERP, backlink). OpenSEO è l'interfaccia e la logica sopra quei dati, non la fonte dei dati. Questa guida dà per scontato che tu ne abbia già una: se non l'hai ancora creata, la guida ufficiale del progetto la copre in due minuti.
Due modi per fare self-hosting
Il self-hosting significa far girare il software sulla tua infrastruttura invece che pagare un servizio in abbonamento. OpenSEO supporta due percorsi, entrambi documentati nel repo:
- Docker, in locale. Gira sul tuo computer, nessuna esposizione su internet, autenticazione disattivata per design (
AUTH_MODE=local_noauth). È il punto di partenza più semplice se vuoi solo provarlo o usarlo da un unico dispositivo. - Cloudflare Workers, su internet. Un Worker è semplicemente un'applicazione che gira sui server di Cloudflare invece che sul tuo computer: resta raggiungibile da qualunque dispositivo, protetta da Cloudflare Access (il sistema di login che decide chi può entrare).
Io uso la strada Cloudflare, perché voglio avere OpenSEO a disposizione da telefono, da laptop, da qualunque posto io sia, non solo dal computer dove l'ho installato. È anche, va detto subito, la strada più complicata delle due: significa gestire un servizio esposto su internet, quindi autenticazione, secret, e un flusso OAuth per Google Search Console che ha più di un modo per rompersi in silenzio. Se vuoi solo iniziare a usarlo senza pensieri, parti da Docker.
Il resto di questa guida copre il percorso Cloudflare, passo per passo, incluso ogni punto dove mi sono bloccato.
Prerequisiti
- Node 22.6 o superiore e pnpm (
corepack enablelo attiva). - Un account Cloudflare con R2 abilitato. Attivare R2 richiede una carta di pagamento registrata, anche restando nel piano gratuito: se non hai mai usato R2, apri la sezione R2 nel dashboard Cloudflare una volta prima di procedere.
- Un account DataForSEO per la chiave API.
1. Come clonare il repository
git clone https://github.com/every-app/open-seo.git
cd open-seo
corepack enable
pnpm installSe hai fatto un fork per averne il controllo, clona quello al posto dell'upstream.
2. Come fare login su Cloudflare
pnpm alchemy login # rispondi sì a "Customize OAuth scopes?" e abilita access:write
pnpm alchemy cloudflare bootstrap # deploya il Worker di stato di alchemy sul tuo accountOpenSEO usa Alchemy per il deploy: uno strumento che, con un comando solo, crea ("provisiona") tutte le risorse Cloudflare che servono (database, storage, Worker, login) al posto tuo, invece di doverle configurare una per una da dashboard.
Durante il login, Cloudflare ti chiede quali permessi ("scope") dare ad Alchemy sul tuo account: access:write è quello che gli serve per poter creare da solo l'applicazione Cloudflare Access più avanti. Se hai già fatto login in passato senza quello scope, un secondo login normale non te lo richiede di nuovo. Usa pnpm alchemy login --configure per forzarlo.
3. Come configurare .env.selfhost
cp .env.selfhost.example .env.selfhostApri il file e imposta almeno queste due variabili, obbligatorie:
- DATAFORSEO_API_KEY: non è la chiave grezza che vedi nella dashboard DataForSEO, ma le tue credenziali email:password codificate in base64. Su app.dataforseo.com/api-access, clicca "Send by email" e usa il valore etichettato "Base64" che ricevi, non quello in chiaro.
- ACCESS_ALLOWED_EMAILS: le email autorizzate a fare login, separate da virgola. È la lista di chi può entrare nel tuo OpenSEO.
4. Come fare il deploy
pnpm deploy:selfhost --yesQuesto comando fa tutto: crea il database D1, i namespace KV, il bucket R2, applica le migrazioni, deploya il Worker e crea l'applicazione Cloudflare Access che lo protegge, con accesso limitato esattamente a ACCESS_ALLOWED_EMAILS. Se il tuo account non ha ancora un team Zero Trust, ne crea uno.
Se preferisci gestire tu l'applicazione Access invece di farla creare in automatico, imposta TEAM_DOMAIN e POLICY_AUD in .env.selfhost prima del deploy: in quel caso il comando non tocca le risorse Access.
5. Come verificare che tutto funzioni
- Apri l'URL del Worker stampato alla fine del deploy.
- Fai login con Cloudflare Access.
- OpenSEO dovrebbe caricare dopo il login.
Se qualcosa non va, https://<il-tuo-worker>/api/health mostra lo stato di configurazione e del database, e pnpm exec wrangler tail mostra i log in tempo reale.
6. Come collegare Google Search Console
Prima di entrare nei passaggi, vale la pena capire come funziona Google Search Console dietro le quinte: non è OpenSEO a "avere" i tuoi dati, li legge in tempo reale dal tuo account Google tramite un'autorizzazione OAuth che tu concedi una volta sola. Il flusso completo è documentato passo per passo nella guida ufficiale a Search Console. Qui ti segnalo il passaggio che, se salti, non ti dà nessun errore subito, ma ti fa perdere tempo dopo.
Creare le credenziali OAuth
- Su console.cloud.google.com, crea o riusa un progetto.
- Abilita la Google Search Console API per quel progetto (API e servizi → Libreria, cerca "Google Search Console API", clicca Abilita). Questo è il primo passaggio della guida ufficiale, ed è quello più facile da trattare come una formalità e saltare mentalmente. Non lo è: creare le credenziali OAuth e abilitare l'API sono due impostazioni separate nello stesso progetto Google Cloud.
- Configura la schermata di consenso OAuth (External, e se resti in modalità Testing aggiungi il tuo account come test user).
- Crea un ID client OAuth di tipo "Applicazione web", con redirect URI:
https://<il-tuo-worker>.workers.dev/api/gsc/oauth/callback - Salva Client ID e Client secret.
Configurare il deploy
In .env.selfhost, decommenta e imposta:
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
BETTER_AUTH_SECRET=BETTER_AUTH_SECRET è una stringa casuale di almeno 32 caratteri, generabile con openssl rand -base64 32: serve solo per Search Console, per cifrare i token salvati. Rilancia pnpm deploy:selfhost --yes per applicare le nuove secret, poi vai su Integrations e collega l'account.
Cosa succede se salti il passaggio 2
Questo è il punto dove ho perso più tempo, e vale la pena raccontarlo perché il sintomo non ha niente a che vedere con la causa.
Se le credenziali OAuth sono corrette ma l'API non è abilitata, il login con Google funziona lo stesso: consenso completato, redirect corretto, token salvato nel database con scadenza a un'ora, refresh token presente. Tutto sembra andato a buon fine. Poi apri Integrations e vedi comunque "Connection expired. Reconnect to continue.", anche subito dopo aver ricollegato.
Il consenso OAuth (login, permessi, token) è un servizio Google separato dalla singola API. Solo quando OpenSEO prova a leggere i dati reali (sites.list), Google risponde con un 403, perché l'API non è attiva sul progetto. Il codice tratta quel 403 come "grant scaduto o revocato" e mostra il messaggio di reconnect, che è tecnicamente corretto ma ti manda a cercare nel posto sbagliato: sembra un problema di token, è un problema di configurazione del progetto Google Cloud.
Fix: console.cloud.google.com → API e servizi → Libreria → Google Search Console API → Abilita. Poi riprova il reconnect, senza bisogno di rigenerare nessuna credenziale.
7. Come collegare i tool MCP (opzionale)
OpenSEO espone i suoi tool via MCP su /mcp, così puoi usarli direttamente da Claude, Claude Code o altri client MCP. Perché funzioni, l'applicazione Cloudflare Access che protegge il Worker deve avere il Managed OAuth attivo. Non lo è di default, nemmeno se l'hai creata in automatico col deploy.
- Zero Trust (one.dash.cloudflare.com) → Access controls → Applications.
- Apri l'app che protegge il tuo Worker, Edit.
- Additional settings → OAuth, attiva Managed OAuth.
- Nei redirect URI consentiti, aggiungi quelli dei client che userai: per CLI e desktop come Claude Code, i client locali che registrano
http://localhost:PORT/callback; per claude.ai, l'URL di callback che ti mostra la pagina di setup del connettore. - Salva.
Poi, da Claude Code:
claude mcp add --transport http --scope user openseo https://<il-tuo-worker>.workers.dev/mcpSe salti il passaggio Managed OAuth, il client riceve un errore di registrazione OAuth generico e non riesce a completare il collegamento.
Gestione ordinaria
Come aggiornare OpenSEO
git pull # oppure, se hai un fork: git fetch upstream && git merge upstream/main
pnpm install
pnpm deploy:selfhost --yesLe tue risorse Cloudflare restano identificate da .env.selfhost, non da valori dentro il repo, quindi un git pull normale seguito da un redeploy basta. Nessun backup manuale di file di configurazione da fare.
Come dare accesso ai colleghi
Aggiungi l'email in ACCESS_ALLOWED_EMAILS dentro .env.selfhost e rilancia pnpm deploy:selfhost --yes. Se modifichi la policy Access direttamente da dashboard invece che da qui, il prossimo deploy la sovrascrive: .env.selfhost resta l'unica fonte di verità.
Come disinstallare tutto
pnpm alchemy destroy --env-file .env.selfhost --stage selfhostCancella il Worker, il database D1, i namespace KV, il bucket R2 e l'applicazione Access, dati inclusi. Non c'è modo di tornare indietro dopo, quindi usalo solo se vuoi davvero ripartire da zero o abbandonare il progetto.
Come diagnosticare un problema senza modificare nulla
Un paio di comandi utili per capire cosa succede davvero, senza toccare codice o configurazione:
# Log in tempo reale del Worker, incluse le richieste che non generano eccezioni
pnpm exec wrangler tail
# Leggere una riga del database in produzione, in sola lettura
pnpm exec wrangler d1 execute <nome-db> --remote --command "SELECT * FROM account WHERE provider_id = 'google-search-console';"Il primo ti dice se una richiesta arriva davvero al Worker e se genera un'eccezione. Il secondo ti fa vedere lo stato reale dei dati salvati, invece di indovinare dal comportamento della UI.
Come farsi aiutare da Claude Code
Tutta la sezione precedente sulla Search Console, incluso il bug del 403 nascosto, l'ho diagnosticata insieme a Claude Code, dentro il repository di OpenSEO clonato in locale. Se non hai mai usato un agente AI per configurare qualcosa del genere, vale la pena provarci: a differenza di seguire una guida da solo, puoi fargli leggere il codice reale del progetto invece di fermarti a quello che dice la documentazione, e fargli eseguire comandi diagnostici al posto tuo.
Un punto di partenza concreto, dentro la cartella del repo clonato:
npx skills add every-app/open-seo --skill '*' --agent claude-codeInstalla le skill ufficiali del progetto (comprese quelle di setup e diagnostica) come comandi disponibili in Claude Code. Poi puoi semplicemente chiedere, in linguaggio naturale, cose come:
- "Aiutami a configurare .env.selfhost per il deploy su Cloudflare."
- "Ho questo errore durante il deploy, cosa significa?"
- "GSC dice 'Connection expired' anche dopo il reconnect, aiutami a capire perché."
Per la diagnostica, il pattern che ha funzionato con me è stato: fargli leggere il codice sorgente del punto che si rompe (non solo la documentazione, che può essere disallineata dal codice reale), controllare lo stato effettivo con comandi in sola lettura come wrangler tail o wrangler d1 execute --remote, e solo alla fine proporre una modifica. Se stai seguendo questa guida e qualcosa non torna, chiedi all'agente di verificare passo per passo prima di cambiare configurazione a caso: spesso la causa reale è due o tre passaggi più indietro di dove compare il sintomo.
FAQ self-hosting
Devo abilitare l’API di Google Search Console?
Sì, sempre, indipendentemente da come configuri le credenziali OAuth. È il passaggio 2 della sezione 6, ed è la causa più comune di connessioni che sembrano riuscite ma poi restano bloccate su "Connection expired".
Cloudflare Access è obbligatorio?
Sì, se scegli la strada Cloudflare. Il deploy lo crea automaticamente e limita l’accesso alle email in ACCESS_ALLOWED_EMAILS.
Posso evitare tutta questa complessità?
Sì: usa Docker in locale. Perdi la possibilità di accedere da qualunque dispositivo, ma salti autenticazione, secret e OAuth quasi del tutto.
Dove trovo altre risorse?
Il sito ufficiale è openseo.so, il codice e tutta la documentazione sono nel repository every-app/open-seo su GitHub.
Serve una mano con SEO o setup tecnico?
Un audit gratuito per capire da dove partire, senza impegno.