La macchina si è bloccata invece di rallentare
Il modello più la sua cache del contesto ha superato la RAM, e il kernel ha iniziato a fare paging dei pesi a ogni token. O ci sta in memoria, o si scende di dimensione — non c'è una via di mezzo.

Sei passi per il self-hosting di un LLM sul suo hardware — il calcolo che prevede i token al secondo prima di comprare la macchina, quale modello entra in 4, 8, 16 o 32 GB, l'autenticazione che Ollama non include, e un elenco onesto dei compiti che non ci stanno. Testato su Debian 12.
Dimensione
Banda, non core
Installare
Ollama
Misurare
I suoi token/s
Proteggere
TLS + un token
Connettere
Un solo base URL
Limitarlo
Contesto, RAM, disco
Quasi tutto ciò che viene scritto sull'eseguire modelli linguistici in locale riguarda le schede grafiche, il che non aiuta se quello che si ha è una macchina virtuale. Il modello mentale utile è più semplice di quanto il discorso sulle GPU suggerisca, e sta in una frase: per produrre un singolo token, un modello denso deve leggere dalla memoria ognuno dei suoi pesi. Non alcuni — tutti, una volta per ogni token.
Questo singolo fatto risolve l'intera questione delle prestazioni. La velocità di generazione non è decisa da quanti core affitta; è decisa da quanto velocemente la macchina può far scorrere il modello fuori dalla RAM. Il che le dà un tetto che può calcolare su due piedi prima di spendere qualsiasi cosa:
tokens per second ≈ memory bandwidth (GB/s) ÷ model size (GB)
Un modello 8B quantizzato occupa circa 5 GB. Su un host virtualizzato dove si può realisticamente trasferire qualcosa nell'ordine di 20 GB/s, il tetto è di circa quattro token al secondo, e il numero che si osserva davvero sarà forse la metà o i due terzi di quello. All'incirca tre parole al secondo. Lo legga come un dato di fatto sul carico di lavoro, non come una delusione: è lento per una finestra di chat ed è del tutto adeguato per un compito che classifica un documento e restituisce una riga di JSON.
I core contano ancora, solo non per il motivo che si crede di solito. Più thread aiutano finché non saturano il percorso verso la memoria, cosa che su queste macchine accade presto — spesso tra i quattro e gli otto thread. Superato quel punto, i core extra restano inattivi mentre tutto aspetta la RAM. Questo è il motivo per cui una macchina a sedici core non è quattro volte più veloce di una a quattro core nel generare testo, e perché pagare per i core sperando in più velocità è il modo più comune di comprare il piano sbagliato.
Leggere è veloce, scrivere è lento. Ci sono due fasi in ogni richiesta e non si comportano affatto allo stesso modo. Elaborare il prompt — il prefill — è un'operazione matriciale vincolata dal calcolo su tutto l'input in una volta, e gira molte volte più veloce della generazione. Produrre la risposta è la parte vincolata dalla memoria descritta sopra, un token alla volta. Quindi dare al modello un documento di duemila parole e chiedere tre frasi in risposta è un carico comodo, mentre chiedergli un saggio di duemila parole non lo è. Progetti i suoi prompt intorno a quell'asimmetria e una macchina CPU sembra molto migliore di quanto suggerisca il suo ritmo di token.
| Livello | Memoria | Modello più grande comodo | Ordine di grandezza | A cosa serve |
|---|---|---|---|---|
| Sentinel · $3.90 | 4 GB | 3B a Q4 (~2 GB) | una frase al secondo | Classificazione, etichettatura, instradamento, embedding |
| Garrison · $7.90 | 8 GB | 8B a Q4 (~5 GB) | poche parole al secondo | Il default. Riassunti, estrazione JSON, risposte RAG |
| Ravelin · $16.90 | 16 GB | 14B a Q4 (~9 GB) | circa la metà di quanto sopra | Ragionamento più complesso, contesto lungo, pipeline in batch |
| Bulwark · $32.90 | 32 GB | 32B a Q4 (~20 GB) | meno di una parola al secondo | Qualità sopra velocità. Solo lavoro asincrono |
| Citadel · $62.90 | 64 GB | 70B a Q4 (~40 GB) | minuti per risposta | Ci sta. Non è interattivo. Lavori notturni |
Le dimensioni dei modelli sono le solite quantizzazioni Q4_K_M, che scambiano una quantità piccola e generalmente impercettibile di qualità con meno della metà della memoria. La colonna della velocità è un ordine di grandezza derivato dalla divisione qui sopra, non un benchmark — il punto del passo 03 è che lei misuri la sua macchina invece di fidarsi di una tabella, inclusa questa.
La versione onesta di questa sezione vale più di una entusiasta, perché il modo più rapido per abbandonare un modello self-hosted è puntarlo sull'unico compito in cui è peggiore e concludere che l'intera idea era sciocca.
Ci sta comodamente. Qualsiasi cosa in cui l'output sia breve e il valore stia nel giudizio più che nella prosa. Classificare un messaggio in una di poche categorie. Decidere se un ticket di supporto è urgente. Estrarre cinque campi da una fattura come JSON. Riassumere una conversazione in tre frasi. Etichettare un documento. Riscrivere una descrizione di prodotto. Tradurre una stringa breve. Rilevare se due record descrivono la stessa persona. Oscurare i nomi in un paragrafo prima che vada altrove. Ognuno di questi casi consuma un input lungo e produce un output breve, che è esattamente l'asimmetria che una CPU gestisce bene.
Ci sta, con pazienza. Lavoro senza nessun essere umano in attesa. Batch notturni, worker di coda, una passata notturna sui documenti della giornata, un report programmato. Se nulla resta bloccato in attesa della risposta, un ritmo di token che sarebbe intollerabile in una finestra di chat smette del tutto di contare — un lavoro che gira per sei minuti alle tre di notte è semplicemente un lavoro che è girato.
Non ci sta. Un assistente interattivo che le persone usino davvero con piacere: a questi ritmi il cursore striscia e l'esperienza è peggiore di nessun assistente. La generazione lunga — mi scriva duemila parole — dove l'intero output è la parte lenta. Agenti di coding che iterano su un repository ampio, dove sia il contesto sia il livello di qualità richiesto superano ciò che un modello piccolo può reggere. Qualsiasi cosa richieda un contesto di centomila token, dove la sola cache supera la macchina. E i modelli per immagini o video, che sono una disciplina completamente diversa e vogliono davvero una GPU.
Se il suo carico di lavoro rientra in quest'ultimo gruppo, la risposta sensata non è comprare una macchina CPU più grande — è un ibrido. Mantenga un modello locale per il grosso delle chiamate e instradi le poche che richiedono un ragionamento di frontiera verso un'API ospitata, esattamente la forma che la guida sull'eseguire un agente AI 24 ore su 24 descrive per la parte runtime. Quella guida ha deliberatamente lasciato il modello fuori campo. Questa è la metà mancante.
Parta a ritroso dal compito. Decida cosa deve fare il modello, scelga la dimensione più piccola che lo fa, verifichi quanto occupa quella dimensione a Q4_K_M, poi aggiunga i sovraccarichi:
RAM needed = model file + KV cache + ~2 GB for the system
3B Q4_K_M ≈ 2.0 GB KV cache at 8k context ≈ 0.5–1 GB
8B Q4_K_M ≈ 4.9 GB KV cache at 32k context ≈ 2–4 GB
14B Q4_K_M ≈ 9.0 GB
32B Q4_K_M ≈ 20.0 GB
70B Q4_K_M ≈ 40.0 GB
La cache key-value è il sovraccarico che le persone dimenticano. Ogni token già presente nella conversazione viene tenuto in memoria perché il modello non lo debba ricalcolare, e quella riserva cresce con il contesto che si consente. Raddoppiare il contesto la raddoppia all'incirca. Un modello che ci sta con un contesto di 4k può non starci più a 32k, e fallirà alla decima richiesta anziché alla prima, il che lo fa sembrare un mistero invece di un errore aritmetico.
Qui non c'è degrado controllato. Quando il totale supera la RAM il kernel non rallenta educatamente: inizia a fare paging dei pesi del modello da e verso il disco, a ogni singolo token. Una generazione da quattro secondi diventa quattro minuti, il load average sale nelle decine, e tutto il resto sulla macchina — il database, il web server, la sua sessione SSH — ne soffre insieme. Stare in memoria non è un'ottimizzazione. È il requisito.
Nel pannello: Ordina → VPS → il piano indicato dal calcolo, immagine Debian 12. Non serve alcun indirizzo email per aprire l'account, non viene richiesto alcun documento d'identità in nessun momento, e la fattura si salda in Monero, Bitcoin, Lightning o negli altri asset supportati — cosa che qui conta più che su un normale web server, per le ragioni che la guida pilastro sull'hosting VPS anonimo espone, e che il capitolo sulla privacy più sotto applica nello specifico ai prompt.
Metta in sicurezza la macchina per prima cosa — SSH solo a chiave, un firewall che non lascia passare nulla che non abbia chiesto, aggiornamenti di sicurezza automatici. La checklist della prima ora richiede circa un'ora, ed è una macchina che a breve conterrà ogni domanda che le farà.
Poi installi il runner. Ollama è llama.cpp con un registro di modelli, un'API REST e una unit systemd intorno, e l'installer a una riga configura tutti e tre:
apt update && apt install -y curl
curl -fsSL https://ollama.com/install.sh | sh
systemctl status ollama --no-pager
ss -ltnp | grep 11434
# → 127.0.0.1:11434 — loopback only. Leave it that way.
Quell'ultima riga è quella da leggere due volte. Di default il servizio ascolta sull'interfaccia di loopback, il che è esattamente corretto, e l'errore più comune commesso nei dieci minuti successivi è impostare OLLAMA_HOST su 0.0.0.0 perché qualcosa su un'altra macchina non riusciva a raggiungerlo. Il passo 04 spiega come raggiungerlo correttamente; non esiste una versione di questa storia in cui la porta 11434 guarda direttamente verso internet.
Due impostazioni vale la pena metterle a posto ora invece di scoprirle dopo. I modelli vengono archiviati di default sotto /usr/share/ollama e sono grandi, quindi la punti verso dove ha spazio. E il default mantiene un modello residente in RAM per cinque minuti dopo l'ultima richiesta, il che è generoso su una macchina che fa anche altro lavoro:
systemctl edit ollama
[Service]
Environment="OLLAMA_MODELS=/var/lib/ollama/models"
Environment="OLLAMA_KEEP_ALIVE=30m"
Environment="OLLAMA_NUM_PARALLEL=1"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
systemctl daemon-reload && systemctl restart ollama
Le richieste parallele e i modelli caricati contemporaneamente moltiplicano entrambi l'uso di memoria, e su una macchina dimensionata per contenere esattamente un modello non c'è un gigabyte di scorta per una seconda copia. Serializzare la coda non è un limite su questo hardware; è l'unica configurazione che non crolla.
Scarichi un modello. Va bene uno qualsiasi degli attuali modelli instruct di classe 8B per una prima misurazione — sono abbastanza vicini in dimensione che il tempo le dice qualcosa sull'hardware più che sul modello:
ollama pull llama3.1:8b # ~4.9 GB at Q4_K_M
ollama list
ollama ps # nothing resident yet
Ora esegua una generazione con i tempi attivati. Il numero che conta è l'eval rate — i token prodotti al secondo, una volta letto il prompt:
ollama run llama3.1:8b --verbose "Reply with exactly one sentence about the Baltic Sea."
total duration: 14.2s
load duration: 3.1s
prompt eval count: 24 token(s)
prompt eval rate: 92.11 tokens/s ← reading: fast
eval count: 38 token(s)
eval rate: 3.42 tokens/s ← writing: the real ceiling
Due righe, due mondi diversi. La lettura girava a poco più di novanta token al secondo; la scrittura a tre e mezzo. Quel rapporto è l'asimmetria del capitolo sull'aritmetica, misurata sul suo hardware, ed è il fatto singolarmente più utile che raccoglierà oggi. Dice: dia a questa macchina input lunghi e chieda output brevi.
La stessa misurazione tramite l'API, che è ciò che vuole davvero se intende scriptare il confronto tra due o tre dimensioni di modello:
apt install -y jq
curl -s http://127.0.0.1:11434/api/generate -d '{
"model": "llama3.1:8b",
"prompt": "List three Nordic capitals.",
"stream": false
}' | jq '{
tokens: .eval_count,
seconds: (.eval_duration / 1000000000),
rate: (.eval_count / (.eval_duration / 1000000000))
}'
Misuri la dimensione sotto e la dimensione sopra, poi si fermi. Scarichi un 3B e un 14B, faccia passare lo stesso prompt su entrambi, e annoti i tre ritmi. Ora sa esattamente quanto costa lo scambio su questa macchina — di solito qualcosa vicino a un raddoppio in ciascuna direzione — e può scegliere in base al compito invece che all'opinione. Poi rimuova i modelli che non tiene, perché ognuno pesa diversi gigabyte.
Un avvertimento sulla prima esecuzione di ogni modello: la load duration in quell'output è il tempo speso a leggere i pesi dal disco in RAM. Si paga solo quando il modello non è già residente, ed è esattamente ciò che controlla OLLAMA_KEEP_ALIVE. Non la includa quando confronta i ritmi, e non se ne allarmi — su NVMe sono secondi, e accade una sola volta.
Questa è la parte della guida che impedisce che accada qualcosa di brutto, quindi va detta senza mezzi termini: l'API di Ollama non ha password, non ha token, non ha modello utente e non ha sistema di permessi. Qualsiasi cosa possa aprire una connessione TCP verso la porta 11434 può generare testo sulla sua CPU, elencare i modelli che ha scaricato, scaricarne di nuovi ed eliminare quelli che usa. Non c'è un'impostazione da attivare, perché non c'è alcun meccanismo da attivare.
La porta 11434 viene scansionata di continuo, per il motivo ovvio: un motore di modelli aperto è calcolo gratuito che appartiene a qualcun altro. Il sintomo non è un allarme. È una macchina che sembra lenta per due settimane e un grafico di banda che non corrisponde a nulla di ciò che ha fatto. Mantenga il servizio sul loopback, e metta davanti qualcosa che chieda chi sta chiamando.
Se nulla al di fuori di questa macchina ha bisogno del modello, si fermi qui — ha già finito. Loopback più un firewall sono una risposta completa, e un agente, uno stack di automazione o una web app in esecuzione sullo stesso VPS raggiungono il modello tramite 127.0.0.1 senza bisogno di nulla di quanto segue. Continui solo se qualcosa su un'altra macchina deve chiamarlo.
Il proxy, e il token. Generi un token casuale lungo, punti un record A verso la macchina, e lasci che Caddy gestisca sia il certificato sia la porta d'ingresso:
openssl rand -hex 32 # → the bearer token, store it in a password manager
apt install -y caddy
/etc/caddy/Caddyfile
llm.example.com {
@unauthorised not header Authorization "Bearer PASTE_THE_HEX_TOKEN_HERE"
respond @unauthorised "unauthorised" 401
reverse_proxy 127.0.0.1:11434 {
# Generation is slow by nature — do not let the proxy give up first.
transport http {
read_timeout 10m
}
}
}
systemctl reload caddy
ufw allow 80,443/tcp
ufw status # 11434 must appear nowhere
C'è una piccola eleganza nello scegliere un bearer token invece dell'autenticazione basic. Ollama espone un'API compatibile con OpenAI, ogni client OpenAI invia la propria chiave esattamente in quell'header, e così il token che ha appena generato diventa la chiave API che le sue applicazioni già sanno portare. Niente ha bisogno di un header personalizzato, e ruotare l'accesso è una riga nel Caddyfile e una variabile d'ambiente lato chiamante.
Verifichi da una macchina diversa dal server. La prima chiamata dovrebbe essere rifiutata e la seconda dovrebbe rispondere:
curl -s -o /dev/null -w '%{http_code}\n' https://llm.example.com/api/tags
# → 401
curl -s https://llm.example.com/api/tags -H "Authorization: Bearer THE_TOKEN" | jq '.models[].name'
# → the list of models you pulled
Se il modello verrà chiamato da agenti piuttosto che da lei, la questione dell'esposizione merita il trattamento più completo nella guida sull'hosting di un server MCP remoto — lo stesso ragionamento su TLS, token e cosa dovrebbe essere raggiungibile da dove, applicato a un servizio che distribuisce strumenti anziché token.
Ollama espone un'interfaccia compatibile con OpenAI su /v1 accanto alla propria API. È tutta qui la storia dell'integrazione: qualsiasi cosa costruita per OpenAI — gli SDK ufficiali, i wrapper dei framework, i nodi di automazione — funziona cambiando il base URL e la chiave, e nient'altro cambia.
curl -s https://llm.example.com/v1/chat/completions \
-H "Authorization: Bearer THE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "llama3.1:8b",
"messages": [{"role":"user","content":"Reply with the word OK."}]
}' | jq -r '.choices[0].message.content'
Da Python, le uniche righe che differiscono da una configurazione ospitata sono le due in cima:
from openai import OpenAI
client = OpenAI(
base_url="https://llm.example.com/v1",
api_key="THE_TOKEN",
)
r = client.chat.completions.create(
model="llama3.1:8b",
messages=[{"role": "user", "content": "Classify: 'the invoice is overdue'"}],
)
print(r.choices[0].message.content)
Chieda JSON, e ottenga JSON. La funzione singolarmente più utile per l'automazione è l'output vincolato. Ollama può forzare la risposta a essere JSON valido invece di sperare che il modello si comporti bene, il che trasforma un modello piccolo da narratore inaffidabile a parser affidabile — ed è la differenza tra un workflow che gira incustodito e uno che si rompe ogni quaranta elementi:
curl -s http://127.0.0.1:11434/api/generate -d '{
"model": "llama3.1:8b",
"prompt": "Extract the total and the currency: Invoice 4021, 1 249,90 EUR due 30 days.",
"format": "json",
"stream": false
}' | jq -r .response
# → {"total": 1249.90, "currency": "EUR"}
In uno stack di automazione vale lo stesso: n8n include un nodo Ollama dedicato, e il suo nodo OpenAI accetta un base URL personalizzato, quindi un workflow esistente passa all'inferenza locale modificando una sola credenziale. La guida al self-hosting di n8n copre il motore di automazione in sé; se può, faccia girare i due su macchine separate, perché un motore che sta inattivo a 700 MB e un modello che vuole cinque gigabyte sono vicini scomodi su una macchina da otto gigabyte.
E l'endpoint degli embedding, dove questa macchina si guadagna da vivere. I modelli di embedding sono due ordini di grandezza più piccoli dei modelli di generazione ed eseguono un solo passaggio per chunk senza nulla da generare, quindi una CPU li gestisce a una velocità che sembra istantanea:
ollama pull nomic-embed-text # ~275 MB
curl -s http://127.0.0.1:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": ["the first chunk of a document", "the second chunk"]
}' | jq '.embeddings | length'
Limiti il contesto. La lunghezza del contesto è la manopola principale sull'uso di memoria, e il valore predefinito è più generoso di quanto una macchina piccola desideri. La imposti globalmente a ciò che il suo prompt realistico più lungo richiede davvero — la maggior parte del lavoro di classificazione ed estrazione sta comoda entro quattromila token — e la alzi per singola richiesta nella rara chiamata che ne ha bisogno di più:
Environment="OLLAMA_CONTEXT_LENGTH=4096"
curl -s http://127.0.0.1:11434/api/generate -d '{
"model": "llama3.1:8b",
"prompt": "…a long document…",
"options": { "num_ctx": 16384 },
"stream": false
}'
Decida per quanto tempo il modello resta in memoria. Un modello residente risponde all'istante e tiene in ostaggio diversi gigabyte. Su una macchina dedicata all'inferenza, lo mantenga caricato per sempre; su una condivisa, lo lasci scaricare dopo un po'. Il valore viaggia anche per singola richiesta, quindi un batch notturno può fissare il modello per la durata dell'esecuzione e rilasciarlo alla fine:
OLLAMA_KEEP_ALIVE=-1 # resident until the service restarts
OLLAMA_KEEP_ALIVE=30m # a sensible default on a shared box
OLLAMA_KEEP_ALIVE=0 # unload immediately after each request
ollama ps # what is resident right now, and how much it holds
Serializzi la coda. Due richieste concorrenti contro un solo modello non vanno due volte più veloci; competono per lo stesso percorso di memoria saturo e ognuna rallenta, e se Ollama decide di caricare una seconda copia per servirle la macchina finisce la RAM. Su questa classe di hardware, una richiesta alla volta, con una coda davanti, è sia la configurazione più veloce sia l'unica sicura — ed è per questo che OLLAMA_NUM_PARALLEL e OLLAMA_MAX_LOADED_MODELS sono stati fissati a uno già nel passo 02.
Tenga d'occhio il disco. Confrontare quattro modelli lascia dietro quattro modelli, e a cinque gigabyte l'uno è un disco che si riempie in silenzio mentre nulla si lamenta. Faccia della pulizia parte del confronto, non un compito per dopo:
ollama list
du -sh /var/lib/ollama/models
ollama rm mistral:7b qwen2.5:14b
Infine, faccia il backup di ciò che non è riproducibile. I pesi del modello non lo sono: un pull li riporta indietro. Ciò che merita un repository è la configurazione, il Caddyfile, il token, i prompt che ha affinato in tre settimane e, se ne ha costruito uno, l'indice vettoriale dietro il suo retrieval. La guida sui backup cifrati ne copre la meccanica; l'elenco da includere per questa macchina è breve e vale la pena annotarlo.
Tutto quanto sopra riguardava la generazione, la parte che una CPU fa lentamente. Il retrieval è l'altra metà della maggior parte dei sistemi utili e ribalta completamente il quadro — ed è per questo che il piano più economico di questa pagina può fare qualcosa di genuinamente prezioso anche se non ci genera mai un token.
Un modello di embedding trasforma un pezzo di testo in un vettore. Si misura in centinaia di megabyte anziché in gigabyte, esegue esattamente un forward pass per chunk, e non c'è alcun ciclo token per token da vincolare alla larghezza di banda della memoria. Sulla stessa macchina dove un modello 8B scrive tre parole al secondo, un modello di embedding attraverserà una libreria di documenti a una velocità che sembra una semplice copia di file.
La sua forma. Divida i suoi documenti in chunk di poche centinaia di parole. Calcoli l'embedding di ogni chunk una volta e ne conservi il vettore. Al momento della domanda, calcoli l'embedding della domanda, trovi la manciata di chunk più vicini, e li passi a un modello insieme alla domanda. L'archiviazione non richiede nulla di esotico: un database SQLite con un'estensione vettoriale basta per decine di migliaia di chunk su un singolo VPS, e PostgreSQL con pgvector la copre ben oltre quello. Un database vettoriale dedicato è una buona cosa da volere più avanti e una dipendenza inutile al primo giorno.
Perché questo conta più della velocità. Guardi cosa tocca ciascuna metà. Il passaggio di generazione vede una domanda e qualche paragrafo. Il passaggio di embedding vede <em>ogni documento che lei possiede</em> — l'intero archivio, ogni contratto, ogni nota, ogni messaggio, fatto passare attraverso il modello un chunk alla volta. Se quel passaggio gira su un endpoint ospitato, il suo intero corpus è stato trasmesso a terzi per essere indicizzato. Se gira sulla sua macchina, non si è mosso nulla.
Questo dà un ibrido genuinamente valido per chi non vuole rinunciare alla qualità di frontiera: indicizzi in locale, faccia il retrieval in locale, e invii solo la domanda e i tre chunk recuperati a un modello ospitato quando la risposta deve essere eccellente. Il corpus resta a casa; ne viaggia solo una fetta sottile, e solo su richiesta.
Due vicini su questo sito rendono concreto lo schema. Un'istanza SearXNG self-hosted dà al livello di retrieval un front-end privato per il web aperto invece che un corpus; un archivio documentale self-hosted gli dà il corpus. Entrambi, più il modello, stanno su piani che costano meno al mese di un singolo posto ospitato.
Le persone ragionano sulla privacy del modello come se il rischio fosse nell'output. Non lo è. L'output è testo generico; altre mille persone hanno ottenuto qualcosa di simile. L'elemento rivelatore è l'input — e un anno di input è un ritratto sorprendentemente completo di un'organizzazione.
Consideri cosa contiene davvero un log delle richieste. Il contratto che ha incollato per farlo riassumere. L'email del cliente che ha chiesto di classificare, con il cliente dentro. La lettera medica, la cifra dello stipendio, le dimissioni che stava scrivendo, il codice di un repository non pubblico. Poi i metadati intorno: quali domande, in che ordine, a che ora, da quale indirizzo, nell'arco di quanti mesi. Nessuno firma un documento che dice "ecco la nostra strategia" — ma la sequenza delle domande è proprio quel documento, assemblato onestamente, da lei, una chiamata alla volta.
Livello uno — cosa conserva l'endpoint. I fornitori seri pubblicano policy serie, e quelli buoni davvero non addestrano sul traffico API business. Ma non è la stessa promessa di non conservarlo. Le richieste vengono tipicamente archiviate per un certo periodo per il monitoraggio degli abusi, sono raggiungibili dal personale in condizioni definite, e sono producibili in sede legale — che è esattamente il modo giusto di gestire una grande piattaforma ed esattamente il posto sbagliato per un testo che non manderebbe via email a uno sconosciuto. Un modello sulla sua macchina non ha alcun log del genere, a meno che non ne scriva uno lei stesso.
Livello due — l'identità a cui il log viene associato. La sola conservazione è solo metà dell'esposizione. L'altra metà è la chiave a cui si associa: un account, il nome di un'azienda, un indirizzo di fatturazione, una carta. È quell'associazione a trasformare "qualcuno ha chiesto di acquisire un concorrente" in "questa azienda ha chiesto, quel martedì". Togliere il modello dall'equazione toglie la conservazione; togliere l'identità dalla macchina toglie l'associazione. Un VPS aperto senza indirizzo email né documento d'identità, in una giurisdizione nordica, saldato in Monero, è la seconda metà della stessa mossa.
Livello tre — i log che scrive lei stesso. Il self-hosting sposta il rischio invece di eliminarlo, e vale la pena essere lucidi su dove ricade. La sua applicazione probabilmente registra i propri prompt. Il suo reverse proxy registra ogni riga di richiesta. Una sessione di debug di due mesi fa ha lasciato output dettagliato nel journal. Il modello in sé non conserva nulla tra una chiamata e l'altra, ma i meccanismi intorno possono conservare tutto — quindi decida deliberatamente cosa viene scritto, imposti una conservazione, e tenga quel log allo stesso standard che non era disposto ad accettare da qualcun altro.
Nulla di tutto ciò rende un modello locale una garanzia di privacy di per sé. Lo rende l'unica architettura in cui è lei a poter dare quella garanzia: il testo resta su un hardware che lei affitta, sotto una giurisdizione che ha scelto, dietro un token che ha emesso lei, e non risponde a nient'altro.
Il modello più la sua cache del contesto ha superato la RAM, e il kernel ha iniziato a fare paging dei pesi a ogni token. O ci sta in memoria, o si scende di dimensione — non c'è una via di mezzo.
OLLAMA_HOST è stato impostato su 0.0.0.0 per far funzionare un client. L'API non ha alcuna autenticazione, e l'11434 viene scansionata. Loopback più un proxy che controlla un token.
È stato scelto un modello 32B per un assistente interattivo. Faccia corrispondere la dimensione all'interazione: l'interattività vuole il piccolo, la qualità vuole l'asincrono.
Una conversazione che cresce fa crescere la cache, e l'intera cronologia viene riletta a ogni turno. Limiti il contesto, e ne inizi una nuova invece di continuare ad aggiungere all'infinito.
Il modello resta residente dopo l'ultima chiamata per progettazione. Imposti OLLAMA_KEEP_ALIVE in base alla macchina, e legga ollama ps prima di dare la colpa a qualcos'altro.
Quattro candidati da cinque gigabyte l'uno, nessuno rimosso. Faccia di ollama rm parte del confronto, e controlli la directory dei modelli quando scattano gli allarmi disco.
Dieci domande che decidono se un modello solo-CPU è lo strumento giusto per il compito che ha in mente.
Sì, con un avvertimento onesto sulla velocità. Un modello quantizzato gira perfettamente bene su normali CPU da server — i pesi stanno in RAM, il calcolo è ampiamente alla portata, e nulla nel processo richiede una scheda grafica. Ciò che una GPU compra è la larghezza di banda della memoria, ed è la banda a determinare la velocità di generazione. Quindi una macchina solo-CPU risponderà, correttamente e completamente, a un ritmo tra poche e qualche dozzina di parole al secondo a seconda del modello. È lento per una finestra di chat e del tutto adeguato per il lavoro che la maggior parte delle persone automatizza davvero: classificare un messaggio, estrarre JSON strutturato da un documento, riassumere una pagina, calcolare embedding di testo per la ricerca, riscrivere un paragrafo. La domanda non è mai "ce la fa" — è "a che ritmo, e quel ritmo conta per questo compito".
Faccia il calcolo invece di fidarsi del benchmark di chiunque, incluso il nostro. Un modello denso legge ognuno dei suoi pesi dalla memoria per produrre un token, quindi il tetto è all'incirca la larghezza di banda della memoria divisa per la dimensione del modello. Un modello 3B quantizzato a circa 2 GB, su una macchina con un throughput effettivo di 20 GB/s, ha un tetto vicino a 10 token al secondo; un 7B da 4,4 GB è vicino a 4,5; un 32B da 20 GB è sotto 1. I numeri reali si collocano sotto il tetto — diciamo dal 50 al 70 per cento — e variano con l'host, i vicini di macchina e il numero di thread. L'elaborazione del prompt è tutta un'altra faccenda: è vincolata dal calcolo, gira molte volte più veloce, ed è per questo che riassumere un documento lungo è comodo mentre chattare con un modello grande non lo è.
Un modello instruct di classe 8B in Q4_K_M, che si attesta tra 4,5 e 5 GB e lascia spazio per il sistema operativo e la cache del contesto. Quella dimensione è l'attuale punto di equilibrio: abbastanza buono da seguire le istruzioni in modo affidabile, produrre JSON valido su richiesta, riassumere, classificare e riscrivere; abbastanza piccolo da restare reattivo. Al di sotto, un modello 3B è genuinamente utile per classificazione, etichettatura e instradamento, ed è circa il doppio più veloce. Al di sopra, un 14B è nettamente migliore nel ragionamento a più passaggi e circa la metà più lento, uno scambio ragionevole per il lavoro in batch e uno scarso per qualsiasi cosa interattiva. Inizi con l'8B, misuri, poi si muova nella direzione indicata dalla misurazione.
La dimensione del file quantizzato, più la cache del contesto, più lo spazio per il sistema — e il totale deve starci, perché la modalità di guasto non è la lentezza ma il collasso. Quando il modello non ci sta, il kernel inizia a fare swap dei pesi del modello su disco e una generazione che dovrebbe richiedere quattro secondi ne richiede quattro minuti mentre il load average sale nelle decine. Come regola pratica a Q4_K_M: un modello 3B pesa circa 2 GB, un 8B circa 5 GB, un 14B circa 9 GB, un 32B circa 20 GB, un 70B circa 40 GB. Aggiunga due gigabyte per Debian e i suoi servizi, e da uno a quattro in più per la cache key-value a seconda di quanto contesto consente. Poi compri il piano sopra la risposta, non quello che la eguaglia esattamente.
Ollama è llama.cpp, con un registro di modelli, un'API REST e un servizio systemd intorno. Usi Ollama a meno che non abbia una ragione specifica per non farlo: un solo comando di installazione, ollama pull invece di andare a caccia di file GGUF, un endpoint compatibile con OpenAI, e valori predefiniti ragionevoli per numero di thread e memoria. Passi a llama.cpp direttamente quando vuole un flag che Ollama non espone, quando vuole fissare una build esatta per la riproducibilità, o quando fa girare un modello con una configurazione per sempre e preferisce non avere un demone che gestisce nulla. Entrambi eseguono gli stessi pesi alla stessa velocità; la differenza sta interamente nell'operatività.
No, e far finta del contrario le fa perdere il pomeriggio. Un modello di frontiera dietro un'API è più grande di qualsiasi cosa entri in una macchina virtuale e sarà migliore nel ragionamento complesso, nel contesto lungo e nel codice. Ciò in cui un piccolo modello locale è genuinamente competitivo è l'enorme fascia intermedia del lavoro reale: decidere a quale delle sei categorie appartiene un'email, estrarre cinque campi da una fattura, riassumere una conversazione di supporto, riscrivere una descrizione, etichettare un documento, giudicare se due record descrivono la stessa persona. Per quella classe di compiti il divario tra un 8B e un modello di frontiera è piccolo, la differenza di costo è totale, e la differenza di privacy è assoluta. La posizione produttiva non è "sostituire l'API" ma "smettere di mandarle il novanta per cento che non doveva mai uscire".
No — nessuna, proprio nessuna, e questo è il fatto operativo più importante di questa guida. Non c'è password, non c'è token, non c'è modello utente. Chiunque possa aprire una connessione TCP verso la porta 11434 può generare testo, elencare i suoi modelli, scaricarne di nuovi ed eliminare quelli esistenti. Quella porta viene scansionata di continuo, e le istanze non protette vengono trovate e usate come calcolo gratuito da sconosciuti, cosa che si manifesta prima come un load average misterioso e poi come una bolletta di banda. Mantenga Ollama vincolato a 127.0.0.1, metta un reverse proxy davanti, termini lì il TLS, e richieda un bearer token o un certificato client sul proxy. Se nulla al di fuori della macchina ha bisogno del modello, non lo esponga affatto.
Sì, e di solito basta un campo. Ollama espone un'API compatibile con OpenAI su /v1, quindi qualsiasi client che le permetta di impostare un base URL — gli SDK OpenAI, LangChain, il nodo OpenAI di n8n, la maggior parte dei framework per agenti — ci parlerà puntando a https://your-host/v1 e inviando una qualsiasi stringa non vuota come chiave. n8n include anche un nodo Ollama dedicato. Lo schema che funziona bene in pratica è ibrido: instradi le chiamate massicce, noiose e ad alto volume verso il modello locale e riservi l'API ospitata per la manciata di passaggi che richiedono davvero un ragionamento di frontiera, con un fallback se quello locale rifiuta di produrre JSON valido.
Sono la cosa con il miglior rapporto qualità-prezzo di tutta questa pagina. I modelli di embedding sono minuscoli — da decine a centinaia di megabyte anziché gigabyte — ed eseguono un solo forward pass per chunk senza generazione token per token, quindi una CPU li macina con piacere. Questo significa che l'intera metà retrieval di un sistema RAG — indicizzare i suoi documenti, calcolare l'embedding della query, trovare i chunk più vicini — gira comodamente sul piano più economico, ed è anche la metà che tocca ogni documento che possiede. Anche se decide che il passaggio di generazione appartiene a un'API ospitata, spostare il passaggio di embedding sulla sua macchina tiene il suo corpus fuori dalle mani altrui.
Tre ragioni, in ordine crescente di quanto contano. Il costo ha una forma: un'API è più economica finché non lo è più, e un workflow che classifica cinquantamila messaggi al mese ha una bolletta che cresce mentre un VPS da $7.90 no. La disponibilità: nessun rate limit, nessuna dismissione del modello su cui ha costruito, nessun'interruzione sulla status page di qualcun altro. E quella che decide — i suoi prompt sono il testo più rivelatore che produce. Non le risposte, le domande. Cosa ha chiesto, su chi, in che giorno, in che ordine. Un endpoint ospitato vede tutto questo, associato a un'identità di fatturazione. Un modello in esecuzione su una macchina affittata senza documento d'identità, in una giurisdizione nordica, pagata in Monero, vede lo stesso testo e non lo riferisce a nessuno.
Garrison (4 vCPU, 8 GB, 240 GB NVMe, $7.90/mese) fa girare un modello 8B con spazio per la cache del contesto e per il sistema — il piano da cui la maggior parte delle persone dovrebbe partire. Ravelin raddoppia la memoria per il 14B e per contesti lunghi. Nessuna email in fase di iscrizione, nessun documento d'identità, e nessuna bolletta per token.
Ultima revisione · 2026-08-24 · Fonti · Documentazione e riferimento API di Ollama, documentazione di llama.cpp, documentazione del reverse proxy Caddy, model card pubblicate per le build quantizzate citate · Cadenza · annuale
This guide is one spoke of a larger series. The pillar walks the three privacy layers end to end — the sibling spokes below dive into the specifics.
Three independent layers — signup, payment, network — explained, legal context included, common mistakes flagged.
Deploy your own MCP server on a no-KYC VPS — TLS, streamable HTTP, OAuth.
Host an MCP server with no ID — the privacy stack, crypto-paid.
Sposta l'agente fuori dal tuo laptop — dimensionamento, systemd, segreti, tetti di spesa.
Docker Compose, PostgreSQL, webhook funzionanti — l'automazione che possiede.