SSD Nodes Learn Hosting plans →
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-09-06

Ollama su VPS: come ospitare un LLM in sicurezza

Un modello 7B richiede 8 GB di RAM e produce 4-10 token al secondo su CPU. Usa un VPS e 127.0.0.1:11434/v1, lasciando chiusa la porta 11434.

Cosa si sta configurando

Un singolo modello linguistico open-weight eseguito su un server di proprietà, accessibile tramite un'API HTTP e, se necessario, tramite una pagina di chat nel browser. Ollama scarica il modello, lo carica in memoria e gestisce le richieste su http://127.0.0.1:11434. L'installazione richiede un solo comando. La parte complessa è altrove: scegliere un modello che il VPS riesca effettivamente a contenere in RAM e non pubblicare per errore su Internet un server di inferenza privo di autenticazione.

Prima di iniziare, è importante considerare due aspetti. Un VPS che usa soltanto la CPU esegue lentamente i modelli di piccole dimensioni. Inoltre, l'API non include alcun meccanismo di autenticazione integrato. Entrambi gli aspetti sono descritti in dettaglio più avanti, perché sono le principali cause di problemi in questa configurazione.

Verifica delle dimensioni, con numeri concreti

L'ingombro in memoria di un modello corrisponde approssimativamente alle dimensioni del relativo file, più circa un gigabyte di overhead di runtime e un'ulteriore quantità per la finestra di contesto. I modelli predefiniti di Ollama sono quantizzati a 4 bit (indicati con Q4). Questa configurazione richiede circa mezzo gigabyte di RAM per ogni miliardo di parametri. Il calcolo è quindi semplice e determina tutto.

Un modello 3B come llama3.2:3b richiede un download di circa 2 GB e circa 4 GB di RAM libera per l'esecuzione. Un modello 7B o 8B come mistral:7b o llama3.1:8b occupa circa 5 GB su disco e richiede circa 8 GB di RAM; con 16 GB si lavora senza problemi. Un modello 13B o 14B richiede circa 16 GB. Qualsiasi modello nella fascia da 30B a 70B richiede un server con molta RAM o, più realisticamente, una GPU. Su una VPS con CPU, il modello potrebbe non entrare in memoria oppure rispondere così lentamente da risultare inutilizzabile.

Consideriamo ora la velocità, perché questo aspetto viene spesso sottovalutato. L'inferenza su CPU dipende dalla larghezza di banda della memoria, non dalla frequenza di clock, e una VPS con vCPU condivise offre una larghezza di banda moderata. Prevedi da una cifra a poche decine di token al secondo: un modello Q4 da 7-8B può raggiungere da 4 a 10 token al secondo, mentre un modello 3B può raggiungere da 10 a 25. Una GPU è all'incirca un ordine di grandezza più veloce. Si tratta volutamente di valori indicativi. La scelta corretta consiste nel misurare il proprio server, come mostra il passaggio di esecuzione seguente. Fidati del tuo eval rate, non del numero riportato in un articolo, incluso questo.

La conclusione pratica è questa: i modelli quantizzati di piccole dimensioni su CPU sono realmente utili per redigere testi, creare riepiloghi e svolgere classificazioni, se puoi accettare questi tempi di risposta. Per modelli più grandi o prestazioni superiori, prevedi nel budget un'istanza con GPU.

Per confrontare un modello specifico con un server specifico, stima qui il relativo ingombro in memoria:

ToolLLM VRAM and model-size calculator

Install Ollama

Esistono due metodi semplici. Lo script ufficiale è la soluzione più rapida su un VPS senza altri servizi:

curl -fsSL https://ollama.com/install.sh | sh

Questo crea un utente di sistema denominato ollama, installa il binario in /usr/local/bin/ollama e registra un servizio systemd denominato ollama.service, avviato al boot e in ascolto su 127.0.0.1:11434. Verifica che sia attivo:

systemctl status ollama
ollama --version

Se usi già Docker, utilizza invece il container:

docker run -d --name ollama \
  -p 127.0.0.1:11434:11434 \
  -v ollama:/root/.ollama \
  --restart always \
  ollama/ollama

Nota il prefisso 127.0.0.1: nella mappatura della porta. In questo modo la porta è associata soltanto a localhost. Se scrivi -p 11434:11434, la porta viene pubblicata su tutte le interfacce: è l'errore descritto nella sezione sulla sicurezza. Scegli un solo metodo di installazione. Non eseguire contemporaneamente lo script e il container, altrimenti due processi entrano in conflitto per la stessa porta.

Scaricare ed eseguire il primo modello

ollama pull llama3.2:3b
ollama run llama3.2:3b

pull scarica i layer del modello sul disco, circa 2 GB in questo caso. run li carica in memoria e apre un prompt >>>. Inserire una domanda. Il primo token può richiedere diversi secondi mentre i pesi vengono caricati dal disco nella RAM; quindi la risposta viene trasmessa in streaming. Inserire /bye per uscire dalla chat; Ollama continua a essere eseguito in background.

Verificare cosa è stato caricato e come viene utilizzato:

ollama ps

La colonna PROCESSOR mostra lo stato effettivo. 100% CPU significa che non viene utilizzata alcuna GPU; questa è la causa della lentezza. Misurare la velocità effettiva con il flag verbose:

ollama run --verbose llama3.2:3b "Write two sentences about Linux."

La riga eval rate visualizzata alla fine indica il numero di token al secondo ottenuto da questo hardware. Questo è il valore da considerare per la pianificazione.

Dove si trovano i modelli e quanto spazio su disco acquistare

Installati dallo script ed eseguiti come servizio, i modelli si trovano nella home dell'utente ollama:

sudo du -sh /usr/share/ollama/.ollama/models

Se li esegui interattivamente come utente personale, si trovano in ~/.ollama/models. Nel container si trovano nel volume denominato ollama. Questo aspetto è importante perché i pesi quantizzati occupano rapidamente molto spazio: un modello 3B occupa circa 2 GB, un modello 7-8B circa 5 GB e un modello 14B circa 9 GB. Se scarichi quattro modelli per confrontarli, puoi occupare 20 GB senza accorgertene. Dimensiona il disco in base ai modelli che intendi conservare ed elimina gli altri con ollama rm <model>. Se lo stesso VPS esegue già un altro servizio che richiede molto spazio, ad esempio PhotoPrism o Immich che conservano una libreria fotografica, sottrai prima quello spazio dalla capacità libera e considera ciò che rimane come il budget effettivo per i modelli.

Eseguilo come un servizio sotto il tuo controllo

Lo script di installazione ha già registrato ollama.service, quindi il servizio viene riavviato al boot senza altri interventi. La configurazione che conviene modificare determina per quanto tempo un modello rimane residente e, in alcune configurazioni, l'indirizzo di bind. Entrambe le impostazioni vanno inserite in un drop-in di systemd, così un aggiornamento di Ollama non le sovrascrive:

sudo systemctl edit ollama.service

Aggiungi questo contenuto sotto l'header [Service] mostrato dall'editor:

[Service]
Environment="OLLAMA_KEEP_ALIVE=30m"

OLLAMA_KEEP_ALIVE indica per quanto tempo un modello rimane in memoria dopo l'ultima richiesta (il valore predefinito è 5 minuti). Aumentalo su un server che interroghi per tutta la giornata per evitare di ricaricare ogni volta i pesi del modello. Impostalo su 0 su un server con poca memoria, per liberare la RAM appena termina una richiesta. systemctl edit ricarica i file dell'unità, quindi riavvia il servizio per applicare la modifica:

sudo systemctl restart ollama

Il punto di sicurezza più importante

Per impostazione predefinita, Ollama è in ascolto su 127.0.0.1:11434, quindi può essere raggiunto soltanto dai processi eseguiti sul VPS stesso. Questa impostazione predefinita è corretta. Mantienila.

L'API non dispone di autenticazione. Di nessun tipo. Non esistono chiavi API, accesso, rate limiting o allow-list. Chiunque possa raggiungere la porta 11434 può eseguire qualsiasi modello scaricato, scaricarne di nuovi, eliminarli e mantenere la CPU o la GPU al 100% indefinitamente. Scanner come Shodan indicizzano migliaia di istanze Ollama esposte. Un'istanza esposta viene individuata e sfruttata entro poche ore.

Quindi, ecco l’unico errore da non commettere: non impostare OLLAMA_HOST=0.0.0.0 e non aprire la porta 11434 nel firewall. In questo modo esponi su Internet un server di inferenza privo di autenticazione. Nessuna configurazione rende sicuro il servizio grezzo sulla porta 11434 di 0.0.0.0, perché in Ollama non c’è nulla da configurare: l’autenticazione semplicemente non esiste. Questa è una regola relativa a questo specifico servizio, non il divieto di aprire una porta in assoluto: un relay RustDesk self-hosted per il desktop remoto deve accettare traffico pubblico per poter funzionare, e lo fa perché integra un’autenticazione basata su chiavi e un elenco breve e documentato di porte. Ollama non offre nessuna di queste caratteristiche.

Esistono tre modi sicuri per raggiungere il modello da un sistema diverso dal VPS:

  • Mantienilo locale. Se l'unico chiamante è un altro programma sullo stesso VPS, uno script cron, un bot o un server MCP che collega i tuoi strumenti al modello, lascia il bind su 127.0.0.1 e configura quel programma per chiamare http://127.0.0.1:11434. Non viene esposto nulla e non serve altro.
  • Raggiungilo tramite un tunnel privato. Collega il VPS a una VPN WireGuard gestita da te, imposta OLLAMA_HOST sull'indirizzo del tunnel (ad esempio 10.8.0.1, non 0.0.0.0) e consenti la connessione soltanto ai peer della VPN. Su Internet non sarà visibile alcun servizio sulla porta 11434.
  • Metti un reverse proxy con autenticazione davanti al servizio. Termina TLS e richiedi una password o un token tramite nginx, Traefik o Caddy, quindi inoltra le richieste a 127.0.0.1:11434. Ollama mantiene il bind su localhost; il proxy è l'unico servizio in ascolto sulla porta pubblica. È lo stesso approccio usato per mettere un certificato Let's Encrypt su nginx davanti a qualsiasi servizio locale.

L'opzione con reverse proxy è esattamente quella che la chat UI configura nel passaggio successivo, con un accesso autenticato.

Aggiungere un'interfaccia chat con Open WebUI, protetta da TLS

Open WebUI è un'interfaccia chat self-hosted. Eseguilo in Docker e configuralo per usare l'istanza locale di Ollama:

docker run -d \
  --name open-webui \
  --network=host \
  -e OLLAMA_BASE_URL=http://127.0.0.1:11434 \
  -v open-webui:/app/backend/data \
  --restart always \
  ghcr.io/open-webui/open-webui:main

Il flag --network=host è il dettaglio importante su un VPS Linux. Inserisce il container nel namespace di rete dell'host, quindi 127.0.0.1 all'interno del container corrisponde al loopback dell'host e il container raggiunge Ollama su 127.0.0.1:11434 senza che Ollama sia in ascolto su altre interfacce. La configurazione con rete bridge, che vedrai altrove, --add-host=host.docker.internal:host-gateway con OLLAMA_BASE_URL=http://host.docker.internal:11434, non funziona in questo caso: quel nome viene risolto nell'indirizzo del gateway del bridge Docker e un servizio associato a 127.0.0.1 sull'host non è raggiungibile attraverso il bridge. Open WebUI resta quindi in attesa e segnala di non riuscire a connettersi a Ollama.

La rete dell'host comporta però un compromesso: Open WebUI ora è in ascolto sulla porta 8080 dell'host, su tutte le interfacce. Qualsiasi mapping -p viene ignorato e Docker stampa un avviso al riguardo. Chiudi quindi 8080 sia sul firewall dell'host sia su quello del provider e fai in modo che il reverse proxy TLS sia l'unico punto di accesso pubblico. Alla prima visita, Open WebUI chiede di creare un account amministratore. Questo account costituisce il livello di autenticazione, quindi scegli una password robusta.

Per aprire la chat dal laptop tramite HTTPS, configura un reverse proxy TLS davanti a 127.0.0.1:8080. Se sul server instradi già diverse applicazioni Docker, Traefik con TLS automatico per molte applicazioni è la soluzione più adatta: un unico blocco di label emette il certificato e instrada chat.example.com verso Open WebUI. La regola della sezione sulla sicurezza resta valida: il proxy gestisce la porta pubblica e l'autenticazione, mentre Ollama resta su localhost e la porta 8080 usata direttamente da Open WebUI rimane protetta dal firewall.

Usare l'endpoint compatibile con OpenAI dal codice

Ollama espone un sottoinsieme dell'API chat di OpenAI all'indirizzo /v1. La maggior parte delle librerie client OpenAI funziona dopo aver modificato due elementi: l'URL di base e una chiave temporanea.

from openai import OpenAI

client = OpenAI(base_url="http://127.0.0.1:11434/v1", api_key="ollama")

resp = client.chat.completions.create(
    model="llama3.2:3b",
    messages=[{"role": "user", "content": "Name three Linux distributions."}],
)
print(resp.choices[0].message.content)

La api_key è richiesta dalla libreria client, ma Ollama la ignora. È quindi sufficiente una stringa qualsiasi. model deve corrispondere a un nome già scaricato con pull; un nome non riconosciuto restituisce model "x" not found, try pulling it first. Una semplice chiamata curl segue lo stesso principio:

curl http://127.0.0.1:11434/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"llama3.2:3b","messages":[{"role":"user","content":"Hello"}]}'

Questo è anche il modo per integrare il modello negli strumenti per agenti ed editor. Se sviluppi già sul server, un modello locale può supportare script e plugin insieme a Claude Code in esecuzione sul VPS dentro tmux, mantenendo le attività di stesura economiche e private fuori da un'API a pagamento, mentre il ragionamento più complesso resta affidato a un modello ospitato.

Modalità di errore, con le stringhe esatte visualizzate

Il processo viene «Killed» durante la generazione. Avvii un modello di grandi dimensioni e il terminale stampa Killed, oppure il log del server mostra llama runner process has terminated: signal: killed. Il killer OOM di Linux lo ha arrestato perché il modello richiedeva più RAM di quella disponibile sul server. Conferma la causa con sudo dmesg | grep -i oom: troverai una riga simile a Out of memory: Killed process ... (ollama). La soluzione consiste nell'usare un modello più piccolo o quantizzato in modo più aggressivo, llama3.2:3b invece di un 13B, oppure nell'aggiungere swap, così un carico che supera di poco la RAM fisica può completarsi lentamente invece di terminare con un errore. Lo swap trasforma un arresto immediato in una risposta lenta; non rende pratico eseguire un modello 70B su 4 GB. L'arresto è silenzioso se non stai osservando il terminale. Su un server che interroghi da un'altra macchina, associare un'unità OnFailure= a ollama.service, configurata per inviare notifiche a un server ntfy gestito da te per gli avvisi push, ti informa appena il processo termina, invece di lasciarti accorgere del problema solo alla richiesta successiva.

"Error: model requires more system memory". Ollama rifiuta di avviare il modello e stampa Error: model requires more system memory (X GiB) than is available (Y GiB). È la versione controllata dell'arresto precedente: Ollama ha calcolato il fabbisogno e ha interrotto l'avvio, invece di lasciare intervenire il killer OOM. Mostra anche i due valori. Scegli un modello il cui requisito sia inferiore alla RAM libera, verificata con free -h, riduci la lunghezza del contesto oppure passa a un VPS più grande. Nessun flag permette di far rientrare il modello: la memoria richiesta è effettiva.

Il primo token tarda molto, poi tutto funziona normalmente. Un modello a freddo non produce output per un intervallo compreso tra cinque e trenta secondi, quindi inizia lo streaming normalmente. Durante questa pausa, i pesi vengono caricati dal disco nella RAM per la prima volta. Uno storage lento peggiora il problema. Dopo il caricamento, il modello rimane residente per la durata di OLLAMA_KEEP_ALIVE, quindi il secondo prompt riceve una risposta immediata. Se il primo caricamento supera un timeout in un punto qualsiasi del percorso della chiamata, viene restituito un errore anziché una risposta lenta. Individuare quale livello ha segnalato il superamento della scadenza del contesto consente di capire se il client, il proxy o il caricamento stesso ha esaurito il tempo disponibile. Aumentare quel valore se gli intervalli di attesa risultano fastidiosi e usare ollama ps per verificare se un modello è attualmente caricato.

Tutto è semplicemente lento. Ottieni dieci token al secondo o meno, senza alcun errore. È l'inferenza su CPU che funziona secondo i suoi limiti. ollama ps mostra 100% CPU, indicando che non è disponibile alcuna GPU. Non si tratta di un bug e nessuna impostazione può risolvere il problema, perché il limite è la larghezza di banda della memoria, non una configurazione errata. Usa un modello più piccolo, accetta la velocità disponibile oppure passa a un'istanza con GPU. Prima di concludere che qualcosa non funziona, misura la velocità effettiva con --verbose.

Connessione rifiutata da un altro computer. Dal laptop ricevi curl: (7) Failed to connect to <ip> port 11434: Connection refused. Il comportamento è previsto: Ollama resta in ascolto solo su localhost. Non "risolvere" il problema associando il servizio a 0.0.0.0, perché sarebbe esattamente l'errore di esposizione descritto sopra. Raggiungi il modello tramite la VPN oppure tramite il proxy con autenticazione.

Hai esposto 11434 a Internet. Se hai impostato OLLAMA_HOST=0.0.0.0, aperto il firewall e ora vedi pull di modelli che non hai avviato oppure la CPU utilizzata al 100% da client sconosciuti, il server è stato individuato e utilizzato da terzi. Questo è l'errore principale, non un caso limite. Associa nuovamente il servizio a 127.0.0.1 o all'indirizzo della VPN, chiudi 11434 nel firewall e configura l'autenticazione davanti al servizio. Considera come interrogato da estranei qualsiasi servizio raggiungibile a quell'indirizzo mentre la porta era aperta.

Backup e aggiornamenti

C’è poco stato da perdere. I modelli possono essere scaricati di nuovo, quindi gli unici dati che vale la pena salvare sono il volume dei dati di Open WebUI, gli account, la cronologia delle chat, le impostazioni e qualsiasi override systemd creato manualmente. Esegui il backup del volume con un container temporaneo:

docker run --rm -v open-webui:/data -v "$PWD":/backup alpine \
  tar czf /backup/open-webui.tgz -C /data .

Aggiorna Ollama eseguendo di nuovo lo script di installazione; aggiorna Open WebUI con docker pull ghcr.io/open-webui/open-webui:main, quindi ricrea il container. Non bloccare le versioni a lungo termine: sia la qualità dei modelli sia il runtime cambiano rapidamente. Leggi le note di rilascio e ripeti i benchmark sul tuo server, invece di affidarti ai risultati dell’ultimo trimestre.

FAQ

Posso davvero eseguire un LLM su un VPS con la sola CPU?

Sì, entro certi limiti. I modelli quantizzati di piccole dimensioni, nella fascia da 3B a 8B, funzionano sulla CPU e sono effettivamente utili per redigere testi, creare riepiloghi e classificare contenuti, ma lentamente: su una vCPU condivisa raggiungono da pochi token al secondo fino a valori nella fascia bassa delle decine. I modelli da 13B in su sono estremamente lenti oppure non entrano affatto nella RAM disponibile. Per ottenere prestazioni reali o usare modelli più grandi serve un'istanza GPU.

Quanta RAM richiede ciascun modello?

Per i modelli quantizzati a 4 bit predefiniti, una regola approssimativa è di circa 0.5 GB di RAM per ogni miliardo di parametri per i pesi, più circa 1 GB di overhead e una quantità leggermente maggiore per il contesto. Un modello 3B richiede quindi circa 4 GB liberi, un modello 7-8B circa 8 GB e un modello 14B circa 16 GB. Controlla la memoria disponibile con free -h e lascia spazio per il sistema operativo e per gli altri servizi presenti sul server.

L'API di Ollama è autenticata?

No. Ollama non dispone di autenticazione integrata, chiavi API o rate limiting. Chiunque possa raggiungere la porta 11434 ne ha il pieno controllo. Per questo, per impostazione predefinita, si associa a 127.0.0.1 e non devi mai esporre la porta 11434 su 0.0.0.0 verso Internet. Puoi raggiungerla localmente, tramite una VPN privata oppure attraverso un reverse proxy che aggiunga un login.

Come posso aggiungere un'interfaccia web per la chat?

Esegui Open WebUI in Docker con --network=host, in modo che condivida il loopback dell'host e raggiunga Ollama nativo su http://127.0.0.1:11434. Quindi configura un reverse proxy TLS davanti alla porta 8080 per consentire l'accesso dal laptop. Mantieni 8080 chiusa sul firewall, così il proxy sarà l'unico punto di accesso pubblico. L'account amministratore di Open WebUI fornisce il login; imposta la relativa password al primo avvio.

Come posso chiamarlo dalla mia applicazione?

Usa l'endpoint compatibile con OpenAI disponibile su http://127.0.0.1:11434/v1. Configura qualsiasi SDK OpenAI con quell'URL di base, passa una stringa qualsiasi come chiave API, perché viene ignorata, e imposta model sul nome di un modello che hai scaricato. Il codice OpenAI esistente funziona generalmente senza modifiche, tranne per l'URL di base e la chiave.