Ollama senza password: rischi e 3 soluzioni
L'API di Ollama non richiede autenticazione: chi raggiunge la porta 11434 può eseguire, scaricare ed eliminare modelli. Ecco 3 soluzioni, in ordine.
L'API di Ollama non ha una password
L'API di Ollama non dispone di autenticazione. Nel server in esecuzione non esistono utente, password, verifica di una chiave o allowlist. Qualsiasi sistema in grado di aprire una connessione TCP alla porta 11434 può elencare i modelli, eseguirli, scaricarne di nuovi ed eliminare quelli presenti.
La documentazione ufficiale lo dichiara chiaramente: «Non è richiesta alcuna autenticazione quando si accede localmente all'API di Ollama tramite http://localhost:11434». La parola localmente definisce l'intero modello di sicurezza. Per impostazione predefinita, Ollama si associa a 127.0.0.1; su un laptop, quindi, l'interfaccia loopback svolge il controllo degli accessi. Spostando il listener su un indirizzo pubblico, il controllo degli accessi scompare, perché non viene sostituito da alcun altro meccanismo.
Questo è il motivo per cui la situazione è importante su un VPS (server privato virtuale). La configurazione predefinita è sicura. La prima modifica che molti applicano, cioè aprire il listener affinché una seconda macchina possa usare il modello, rimuove contemporaneamente tutte le protezioni.
Cosa rivela una porta 11434 aperta
Tutti gli endpoint. Non esiste una modalità di sola lettura né una porta amministrativa separata. Queste sono le richieste reali, indirizzate all'indirizzo del server anziché a localhost:
# List every model on the box
curl http://SERVER_IP:11434/api/tags
# See what is loaded into memory right now
curl http://SERVER_IP:11434/api/ps
# Run a prompt on your hardware
curl http://SERVER_IP:11434/api/generate -d '{"model":"llama3.2","prompt":"Why is the sky blue?"}'
# Write several gigabytes to your disk
curl http://SERVER_IP:11434/api/pull -d '{"model":"llama3.2"}'
# Remove a model
curl -X DELETE http://SERVER_IP:11434/api/delete -d '{"model":"llama3.2"}'Dal punto di vista operativo, si verificano quattro problemi:
- La CPU o la GPU esegue inferenze per conto di altri. Con un piano che prevede un'allocazione CPU a consumo equo, un carico prolungato consuma l'allocazione a beneficio di uno sconosciuto. Inoltre, tenere sotto controllo i costi dei carichi di lavoro AI su un VPS diventa molto più difficile quando non sei l'unico client.
/api/pullscrive sul disco. I modelli occupano da due a quaranta gigabyte ciascuno. Una sequenza di pull riempie il volume e un disco pieno interrompe tutti gli altri servizi sul server, non solo Ollama.- Le richieste arrivano nel processo e vengono registrate. Al livello di log predefinito, Ollama registra solo i metadati: endpoint, stato, latenza e indirizzo del client, non il testo del prompt. È comunque una traccia di chi ha usato il server e per quale scopo, salvata nel journal, senza che tu abbia scelto di raccoglierla.
/api/deleterimuove i modelli. Per recuperarli devi scaricarli di nuovo usando la tua larghezza di banda.
Niente di tutto questo richiede un exploit. È l'API documentata che si comporta esattamente come previsto.
La chiave Ed25519 non è un controllo degli accessi
Cerca "Ollama API key" e trovi due elementi diversi. Nessuno dei due è una password per il tuo server. Distinguerli elimina gran parte della confusione.
Il primo è la coppia di chiavi di identità. Ollama genera una coppia di chiavi Ed25519 al primo avvio. Su Linux, lo script di installazione crea un utente di sistema denominato ollama con directory home in /usr/share/ollama, quindi la coppia si trova qui:
/usr/share/ollama/.ollama/id_ed25519
/usr/share/ollama/.ollama/id_ed25519.pubQuesta chiave viene usata verso l'esterno. ollama signin registra la parte pubblica con il tuo account ollama.com. La chiave autorizza il push di un modello nel registry o il pull di un modello privato. Dimostra a ollama.com l'identità della tua macchina. Non richiede nulla ai client che si connettono alla tua macchina. Eliminarla, sostituirla o non crearla non modifica in alcun modo chi può chiamare la tua API.
Il secondo è OLLAMA_API_KEY. Questa variabile contiene una chiave che crei in https://ollama.com/settings/keys. Il client la invia come Authorization: Bearer $OLLAMA_API_KEY quando chiama l'API ospitata in https://ollama.com/api. È una credenziale per il loro servizio, usata da te come client. Il tuo ollama serve non la legge mai. Impostare OLLAMA_API_KEY sul tuo VPS non applica una password al tuo VPS.
Quindi non esiste un'impostazione da attivare. Le tre difese seguenti funzionano tutte allo stesso modo: mantieni la porta irraggiungibile e configura davanti a essa un componente che esegua effettivamente i controlli.
Controllare su quali indirizzi il server è attualmente in ascolto
sudo ss -tlnp | grep 11434Il risultato sicuro mostra l'indirizzo di loopback:
LISTEN 0 4096 127.0.0.1:11434 0.0.0.0:* users:(("ollama",pid=812,fd=3))Il risultato esposto mostra tutte le interfacce:
LISTEN 0 4096 0.0.0.0:11434 0.0.0.0:* users:(("ollama",pid=812,fd=3))0.0.0.0 indica tutti gli indirizzi IPv4 del server, incluso quello pubblico. *:11434 e [::]:11434 indicano lo stesso per IPv6.
Ora verifica dall'esterno. Esegui questo comando sul laptop, non sul server:
curl -m 5 http://YOUR_SERVER_IP:11434/api/versioncurl: (28) Connection timed out after 5001 milliseconds è il risultato atteso, così come curl: (7) Failed to connect ... Connection refused. Un oggetto JSON che contiene un campo version indica che l'intera API è raggiungibile da chiunque invii una richiesta. Eseguire il test con curl direttamente sul server non dimostra nulla, perché il loopback risponde sempre.
L'esposizione avviene in genere in uno di due modi. Il primo è una modifica esplicita, necessaria perché un secondo computer possa raggiungere il modello:
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"Quella singola riga è sufficiente a esporre il servizio. Il secondo metodo usa Docker e non richiede alcuna modifica manuale. È descritto nella sezione seguente.
Difesa 1: mantenerlo su localhost e accedere tramite tunnel
Usa questa soluzione per prima. Non richiede nuovo software e non crea credenziali che potrebbero fuoriuscire. La porta non è mai presente su un'interfaccia pubblica, quindi le scansioni non possono rilevarla.
Imposta esplicitamente l'indirizzo di bind invece di affidarti al valore predefinito:
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_HOST=127.0.0.1:11434"Questo scrive /etc/systemd/system/ollama.service.d/override.conf. Applica la modifica e verifica:
sudo systemctl daemon-reload
sudo systemctl restart ollama
sudo ss -tlnp | grep 11434ss dovrebbe ora mostrare 127.0.0.1:11434. Se mostra ancora 0.0.0.0, prevale un secondo file drop-in. Esegui systemctl cat ollama.service per elencare l'unità e tutti i file drop-in con il relativo percorso, quindi elimina quello obsoleto.
Per usare il modello dal laptop, inoltra la porta tramite SSH:
ssh -N -L 11434:127.0.0.1:11434 you@your-server-L 11434:127.0.0.1:11434 apre la porta 11434 sul laptop e invia a 127.0.0.1:11434 tutto ciò che vi arriva, visto dal server. -N indica a SSH di non eseguire un comando remoto, quindi il processo mantiene semplicemente aperto il tunnel. Mentre il tunnel è attivo, sul laptop funziona:
curl -s http://localhost:11434/api/tagsSi verificano due errori comuni. bind [127.0.0.1]:11434: Address already in use significa che sul laptop è in esecuzione una propria istanza di Ollama su quella porta. Scegli quindi una porta locale diversa con -L 11500:127.0.0.1:11434 e configura il client per usare 11500. Una risposta vuota attraverso un tunnel che si è connesso correttamente significa che SSH funziona, ma Ollama non è in ascolto sul lato server. Prima di modificare il comando SSH, verifica quindi ss sul server.
Per più macchine client, una rete privata è preferibile a un tunnel per ogni utente. Collega le macchine tramite WireGuard o Tailscale, quindi associa Ollama all'indirizzo di quella rete invece che a 0.0.0.0:
[Service]
Environment="OLLAMA_HOST=10.8.0.1:11434"La porta sarà quindi presente soltanto su un'interfaccia alla quale è necessario accedere con una chiave. Questa configurazione resiste anche a un errore del firewall, perché una regola che consente accidentalmente l'accesso a Internet non può comunque esporre un listener che non è presente sull'interfaccia pubblica.
Defence 2: un proxy reverse che verifica un bearer token
Quando qualcosa su Internet deve chiamare il modello, mantieni Ollama in ascolto sul loopback e inserisci un proxy davanti. Il proxy termina TLS (transport layer security) e rifiuta le richieste prive dell'header corretto. Ollama continua ad accettare connessioni soltanto da 127.0.0.1, quindi il proxy è l'unico percorso di accesso.
Genera prima un token reale. Non inventarlo manualmente:
openssl rand -base64 36Un sito nginx che verifica il token:
map $http_authorization $ollama_ok {
default 0;
"Bearer PASTE_YOUR_GENERATED_TOKEN_HERE" 1;
}
server {
listen 443 ssl;
server_name llm.example.com;
ssl_certificate /etc/letsencrypt/live/llm.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/llm.example.com/privkey.pem;
location = /api/pull { return 403; }
location = /api/delete { return 403; }
location = /api/push { return 403; }
location / {
if ($ollama_ok = 0) { return 401; }
proxy_pass http://127.0.0.1:11434;
proxy_set_header Host 127.0.0.1:11434;
proxy_buffering off;
proxy_read_timeout 600s;
}
}In questo blocco, cinque righe svolgono un lavoro effettivo e impediscono ciascuna un errore che altrimenti si verificherebbe.
if all'interno di un blocco location è in genere una scelta errata in nginx, ma un body esattamente uguale a return è una delle due forme che si comportano in modo prevedibile, quindi questo utilizzo è sicuro.
location = /api/pull è una corrispondenza esatta e nginx assegna alle corrispondenze esatte una priorità superiore rispetto al prefisso location /. Di conseguenza, questi tre endpoint vengono rifiutati prima ancora che il token venga verificato. Un token valido consente quindi di eseguire l'inferenza, non di riempire il disco.
proxy_set_header Host 127.0.0.1:11434; è importante perché Ollama analizza gli header Host e Origin in ingresso. Inoltrare direttamente il nome host pubblico del proxy può produrre un 403 Forbidden proveniente da Ollama anziché da nginx, rendendo il troubleshooting più difficile. OLLAMA_ORIGINS è l'altro parametro utile per un client browser che deve consentire un'origine specifica.
proxy_buffering off; è importante perché Ollama trasmette la risposta un token alla volta. Con il buffering attivo, nginx trattiene lo stream e lo consegna interamente al termine. Il client sembra quindi bloccato per tutta la durata della generazione.
proxy_read_timeout 600s; è importante perché nginx usa per impostazione predefinita 60 secondi. Una generazione lunga eseguita sulla CPU supera facilmente questo limite, il client riceve 504 Gateway Time-out e /var/log/nginx/error.log registra upstream timed out (110: Connection timed out) while reading response header from upstream. La richiesta era ancora in esecuzione. nginx l'ha interrotta.
Ricarica la configurazione e verifica entrambi i percorsi:
sudo nginx -t && sudo systemctl reload nginx
curl -s -o /dev/null -w '%{http_code}\n' https://llm.example.com/api/tags
curl -s -H "Authorization: Bearer YOUR_TOKEN" https://llm.example.com/api/tagsIl primo comando dovrebbe stampare 401. Il secondo dovrebbe stampare l'elenco dei modelli. Se anche il primo restituisce l'elenco dei modelli, il blocco map si trova nell'ambito errato. Deve trovarsi al livello http. Inseriscilo quindi in un file sotto /etc/nginx/conf.d/ oppure sopra il blocco server, mai all'interno di server.
Caddy svolge lo stesso compito con l'autenticazione di base in quattro righe. Per un client browser è spesso più adatta di un bearer token:
llm.example.com {
basic_auth {
apiuser PASTE_BCRYPT_HASH_HERE
}
reverse_proxy 127.0.0.1:11434
}Esegui caddy hash-password per generare l'hash bcrypt richiesto. Attenzione al nome della direttiva: prima di Caddy v2.8 era basicauth, mentre ora è basic_auth. Una configurazione copiata da una guida precedente non viene caricata e Caddy indica la direttiva non riconosciuta.
Qualunque proxy tu scelga, si tratta di un unico secret condiviso da tutti. Ogni client che lo possiede ha lo stesso livello di accesso. Per revocarlo devi modificare la configurazione e aggiornare contemporaneamente tutti i client.
Difesa 3: un gateway che rilascia chiavi per client
Quando più di una persona o applicazione chiama il modello, un token condiviso non è più sufficiente. Non è possibile sapere quale client ha generato il carico né bloccarne uno senza bloccarli tutti. Il gateway si colloca al posto del proxy, usa la stessa API compatibile con OpenAI, rilascia una chiave separata per ogni client e registra l'utilizzo associato a ciascuna chiave. Un gateway LiteLLM self-hosted è la soluzione più comune e aggiunge budget per chiave e log delle richieste al controllo degli accessi.
La regola della difesa 1 non cambia. Ollama è in ascolto su 127.0.0.1, il gateway è l'unico processo che comunica con Ollama e il gateway è l'unico servizio con un listener pubblico. Un gateway installato su un host in cui la porta 11434 è ancora aperta a Internet è solo un elemento decorativo, perché i client possono aggirarlo direttamente.
La trappola del firewall: una porta del container pubblicata bypassa UFW
Questo spiega perché sui server esistono istanze esposte anche quando i proprietari hanno configurato correttamente il firewall.
UFW (uncomplicated firewall) scrive le proprie regole nella catena INPUT della tabella filter del kernel, mentre INPUT gestisce i pacchetti indirizzati direttamente all'host. Il flag -p di Docker scrive una regola di NAT di destinazione (network address translation) nella catena PREROUTING della tabella nat, che il kernel valuta prima di decidere dove instradare il pacchetto. Quando avviene la decisione di routing, la destinazione è già stata riscritta con l'indirizzo del container. Il pacchetto viene quindi inoltrato anziché consegnato localmente e attraversa FORWARD invece di INPUT. Le regole INPUT di UFW non vengono mai consultate, quindi il pacchetto aggira il firewall invece di attraversarlo.
Per questo la sequenza seguente lascia la porta 11434 aperta a Internet:
sudo ufw default deny incoming
sudo ufw enable
docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollamae sudo ufw status continua a indicare che il firewall è attivo con una policy predefinita di rifiuto. Entrambe le informazioni sono corrette contemporaneamente. È proprio questo che porta a fidarsi del controllo sbagliato. Puoi vedere la regola responsabile:
sudo iptables -t nat -L DOCKER -nLa correzione consiste nell'indicare un indirizzo nel flag di pubblicazione:
docker rm -f ollama
docker run -d -v ollama:/root/.ollama -p 127.0.0.1:11434:11434 --name ollama ollama/ollama-p 11434:11434 è una forma abbreviata di -p 0.0.0.0:11434:11434. Specificando 127.0.0.1 associ il lato host della mappatura all'interfaccia di loopback. Il tunnel SSH e il reverse proxy possono quindi raggiungerlo, mentre Internet no. Ricreare il container è sicuro in questo caso perché i modelli risiedono nel volume denominato ollama, non all'interno del container.
Verifica che le due visualizzazioni coincidano:
docker port ollama
sudo ss -tlnp | grep 11434docker port ollama dovrebbe stampare 11434/tcp -> 127.0.0.1:11434. Se stampa 0.0.0.0:11434, il servizio è ancora esposto. Dopo aver compreso questo meccanismo, puoi applicarlo a ogni container che pubblichi: perché le porte pubblicate da Docker bypassano UFW descrive la catena DOCKER-USER e le regole che restano attive dopo il riavvio di Docker. Se stai ancora definendo la policy del server, le regole UFW necessarie per un nuovo VPS descrive la configurazione di base su cui si basa questa soluzione.
Con quale account viene eseguito il processo
Lo script di installazione di Linux crea un account dedicato ed esegue il servizio con quell'account:
useradd -r -s /bin/false -U -m -d /usr/share/ollama ollamaL'unità in /etc/systemd/system/ollama.service imposta quindi User=ollama e Group=ollama. Non modificare questa configurazione. Un rapido ollama serve avviato manualmente in un terminale viene eseguito con l'account dell'utente con cui hai effettuato l'accesso. Se l'account è root, un'API non autenticata scrive file con i privilegi di root. Verifica quale sia la situazione:
ps -o user= -C ollamaIl risultato dovrebbe essere ollama. Qualsiasi altro risultato indica che un processo avviato manualmente è in esecuzione insieme all'unità oppure al suo posto. Lo stesso principio vale per ogni daemon aggiunto in seguito e eseguire i servizi con utenti dotati del minimo privilegio consente di applicarlo correttamente.
Come verificare che l'endpoint API di Ollama sia sicuro
Qualunque soluzione tu abbia scelto, un solo test è sufficiente e deve essere eseguito da un'altra macchina:
curl -m 5 http://YOUR_SERVER_IP:11434/api/version
curl -m 5 http://YOUR_SERVER_IP:11434/api/tagsEntrambi i tentativi devono andare in timeout o essere rifiutati. Se hai configurato un proxy, gli stessi due percorsi sul nome host del proxy devono restituire 401 senza credenziali e JSON reale con le credenziali.
Quindi leggi una volta il log degli accessi, perché indica se qualcuno ha individuato la porta mentre era aperta:
journalctl -u ollama --since "-30 days" | grep GIN | grep -v 127.0.0.1Ollama scrive una riga per ogni richiesta e include l'indirizzo del client:
[GIN] 2026/08/12 - 14:01:10 | 200 | 103.965898ms | 127.0.0.1 | POST "/api/generate"Dopo che Ollama è in ascolto sull'interfaccia di loopback, ogni riga deve mostrare 127.0.0.1, perché questo è l'unico indirizzo da cui può arrivare una connessione. Un indirizzo pubblico in quella colonna indica una richiesta proveniente dall'esterno; il timestamp mostra quando è arrivata. Il risultato desiderato è che il comando non produca alcun output. Se non hai familiarità con la parte relativa ai modelli, eseguire Ollama su un VPS illustra l'installazione, il dimensionamento del modello e i limiti di memoria che determinano quali modelli verranno effettivamente caricati.
FAQ
Ollama ha una chiave API o una password?
No. Il server eseguito non dispone di alcun tipo di autenticazione e la documentazione ufficiale specifica che non è richiesta alcuna autenticazione per raggiungere l'API. Entrambe le cose chiamate "chiave API di Ollama" indicano invece il contrario. La coppia Ed25519 in /usr/share/ollama/.ollama/ autentica la macchina presso ollama.com, così puoi eseguire il push dei modelli e il pull di quelli privati. OLLAMA_API_KEY è una credenziale che il client invia all'API ospitata in https://ollama.com/api. Il tuo ollama serve non legge nessuna delle due, quindi il controllo degli accessi deve essere fornito dalla rete o da un proxy davanti al servizio.
OLLAMA_HOST=0.0.0.0 è sicuro se ho un firewall?
Solo finché nessun altro componente scrive regole firewall su quel server. 0.0.0.0 indica che il listener è effettivamente presente sull'interfaccia pubblica e che ti affidi al solo firewall per impedirne l'accesso. Questa fiducia viene meno nel momento in cui Docker pubblica una porta, perché la regola DNAT aggiunta da Docker alla tabella nat viene valutata prima che il pacchetto raggiunga la catena INPUT, dove opera UFW; il pacchetto viene quindi inoltrato e UFW non lo vede mai. Il binding a 127.0.0.1 o a un indirizzo di un tunnel privato rimuove il listener dall'interfaccia pubblica, quindi un errore nella configurazione del firewall non lascia nulla da esporre.
Come verifico se la porta di Ollama è aperta a Internet?
Esegui sudo ss -tlnp | grep 11434 sul server e curl -m 5 http://YOUR_SERVER_IP:11434/api/version da un'altra macchina. La combinazione ss che mostra 127.0.0.1:11434 e del curl remoto che va in timeout è il risultato che vuoi ottenere. Se ss mostra 0.0.0.0:11434 o *:11434 mentre il curl remoto restituisce JSON, l'API completa è raggiungibile. Non eseguire mai il test con curl direttamente sul server, perché il loopback risponde indipendentemente dall'indirizzo di binding configurato.
Posso semplicemente spostare la porta da 11434 a una porta casuale?
No, ed è importante chiarire il motivo. Una porta diversa rallenta soltanto la scansione di quella singola porta. Gli scanner percorrono l'intero intervallo e una richiesta a /api/tags identifica il servizio indipendentemente dalla porta utilizzata. Spostare la porta inoltre invalida le impostazioni predefinite di tutti i client e rende più difficile comprendere la configurazione in seguito. Usa invece il binding sul loopback: in questo modo rimuovi il listener anziché spostarlo.
Qualcuno ha raggiunto la mia istanza Ollama esposta. Che cosa devo controllare?
Esegui prima il binding a 127.0.0.1 e riavvia il servizio, così interrompi l'esposizione prima di iniziare l'analisi. Esegui quindi journalctl -u ollama --since "-30 days" | grep GIN | grep -v 127.0.0.1 per vedere quali indirizzi esterni hanno chiamato quali endpoint e quando. Confronta ollama list con i modelli che intendevi avere, perché /api/pull non richiede autenticazione e un modello che non hai scaricato rappresenta sia spazio occupato su disco sia una prova dell'accesso. Controlla lo spazio libero con df -h. Ollama non registra il testo dei prompt al livello di log predefinito, quindi disponi di una registrazione di chi ha effettuato la richiesta e per quale modello, ma non di ciò che è stato generato.