SSD Nodes Learn Hosting plans →
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-27

Configurare dsh: chiavi API, modelli ed endpoint

Scopri dove dsh salva la configurazione su Linux, come usare una chiave DeepSeek o un endpoint Ollama locale e cosa esce dal sistema in ciascuna modalità.

Dove dsh conserva la configurazione

dsh (DeepSeek Harness) conserva la configurazione in una sola directory: $DSH_HOME, che per impostazione predefinita è ~/.dsh. Tutto ciò che si configura nella Web UI viene scritto lì come file di testo. Copiando questa directory su un altro server, il nuovo sistema si comporta come quello originale.

Quattro percorsi contengono tutto ciò che verrà modificato.

  • ~/.dsh/settings.yaml contiene le impostazioni scritte manualmente e tramite la UI, inclusi i route del provider e del modello.
  • ~/.dsh/.credentials.yaml contiene i secret. Le impostazioni conservano soltanto un riferimento a una credenziale, quindi il valore della chiave si trova in un unico file.
  • ~/.dsh/profiles/ contiene i profili denominati e ~/.dsh/storages/ contiene le sessioni salvate.
  • ~/.dsh/cordis.patch.yml è il livello di personalizzazione. Viene applicato sopra la configurazione integrata per ogni profilo.

DeepSeek ha annunciato l'harness come developer preview con licenza MIT il 17 agosto 2026 e il README specifica che sono previste modifiche che possono interrompere la compatibilità. I nomi dei campi e i percorsi riportati in questa guida corrispondono alla documentazione del repository disponibile ad agosto 2026. Prima di copiare la configurazione da una guida, inclusa questa, confrontali con la documentazione della versione installata, perché una preview può rinominare gli elementi tra una release e l'altra.

Il minimo onesto per ottenere il primo output

dsh richiede Node.js 22.19 o versione successiva nella serie 22, oppure la versione 24 o successiva. Node 23 non rientra nell’intervallo supportato. Controlla prima la versione, perché una versione incompatibile causa un errore all’avvio che può sembrare un problema del pacchetto.

node -v
npx @deepseek-ai/dsh web

npx scarica il pacchetto dal registro npm e avvia la Web UI su http://127.0.0.1:3080. Si associa all’indirizzo di loopback; quindi la porta non è raggiungibile da un’altra macchina anche se il firewall la consente. Su un VPS, inoltra la porta tramite SSH invece di esporre 3080 a Internet. Se l’URL visualizzato crea confusione, perché dsh si avvia su quell’indirizzo spiega cosa protegge l’associazione a loopback e cosa non protegge.

ssh -N -L 3080:127.0.0.1:3080 you@your-server

Apri http://127.0.0.1:3080 sul laptop, quindi vai in Settings e Models. La scheda DeepSeek contiene un solo campo per la chiave API. Incolla la chiave ottenuta da platform.deepseek.com e salvala. Il percorso del modello diventa subito utilizzabile, senza riavvio, perché il server in esecuzione memorizza la credenziale e risolve il riferimento in tempo reale. Raggiungere la Web UI di dsh su un server remoto descrive il caso del tunnel e del reverse proxy, mentre installare DeepSeek Harness su un VPS descrive la preparazione del server prevista da questa guida.

Dopo il salvataggio, controlla cosa ha creato l’applicazione.

ls -la ~/.dsh
stat -c '%a %n' ~/.dsh/.credentials.yaml

Dovresti vedere settings.yaml, .credentials.yaml e profiles/. Se stat restituisce una modalità diversa da 600, esegui chmod 600 ~/.dsh/.credentials.yaml. Un file delle credenziali leggibile dal gruppo o da tutti gli utenti espone la chiave a ogni altro account del sistema.

Per la prima esecuzione senza browser basta un comando.

npx @deepseek-ai/dsh --profile headless "summarise the files in this directory"

Il profilo headless esegue una singola sessione e stampa la risposta finale.

Variabili d'ambiente o file di configurazione

Esistono due modi per fornire una chiave a dsh, e non sono intercambiabili.

Un provider del catalogo (DeepSeek, Anthropic, OpenAI e gli altri provider dell'elenco integrato) riceve la chiave tramite la pagina Models. Il valore viene inserito in ~/.dsh/.credentials.yaml e nelle impostazioni viene conservato soltanto un riferimento. La Web UI non mostra più la chiave dopo il salvataggio.

Un provider personalizzato può invece specificare una variabile d'ambiente con apiKeyEnv. Questa è la struttura indicata dalla documentazione per ~/.dsh/settings.yaml.

llm-pi-ai:
  providers:
    my-gateway:
      apiKeyEnv: GATEWAY_API_KEY
      api: openai-completions
      baseURL: https://gateway.example/v1
      models:
        - id: legacy-chat
        - id: vision-preview
          input: [text, image]

Aggiungi prima un provider tramite la Web UI, quindi apri ~/.dsh/settings.yaml e copia la struttura che ha scritto. Durante un'anteprima per sviluppatori, la parte più soggetta a modifiche è la struttura annidata e il file appena scritto dall'applicazione è sempre aggiornato.

apiKeyEnv viene letto dall'ambiente del processo dsh, non dalla shell della sessione di login. Una chiave esportata in una sessione interattiva non è visibile a un'unità systemd. Di conseguenza, la stessa configurazione che funziona quando esegui manualmente dsh web restituisce MISSING_CREDENTIAL se il processo viene eseguito come servizio. Fornisci all'unità un file dedicato.

[Service]
EnvironmentFile=/etc/dsh/dsh.env

Imposta il file con i permessi 600 e assegnane la proprietà all'utente con cui viene eseguito il servizio.

Scelta dei modelli e ID che non può essere rinominato

Ogni provider configurato viene visualizzato nel selettore dei modelli. La selezione di un modello lo imposta anche come predefinito per le nuove sessioni. Le sessioni già esistenti mantengono il modello registrato al loro interno, quindi il cambio non modifica una conversazione precedente.

Il Provider ID è permanente. Le richieste, le sessioni salvate, i modelli predefiniti e i riferimenti alle credenziali puntano tutti a questo ID, quindi non esiste un pulsante per rinominarlo. Per modificarlo è necessario creare un nuovo provider ed eliminare quello precedente. Scegli un nome che non dovrai cambiare: local-ollama invece di test2.

I modelli supportano solo il testo, salvo diversa dichiarazione. Aggiungi input: [text, image] a una voce del modello per dichiarare il supporto alle immagini oppure imposta defaultInput a livello di route come fallback per i modelli non descritti dal catalogo. La route chat-completions di DeepSeek supporta solo il testo e non può essere configurata diversamente, quindi un'immagine allegata a questa route viene rifiutata prima dell'invio.

Indirizza dsh a un endpoint locale per mantenere il codice sul server

Ollama espone un'API compatibile con OpenAI su http://127.0.0.1:11434/v1. dsh può usare qualsiasi URL di base compatibile con OpenAI tramite un provider personalizzato, quindi i due componenti comunicano direttamente. Configura prima il model server: eseguire il self-hosting di un LLM con Ollama su un VPS descrive l'installazione e il download del modello.

Verifica che l'endpoint risponda prima di modificare dsh.

ollama list
curl -s http://127.0.0.1:11434/v1/models

ollama list stampa il tag esatto di ogni modello scaricato. Copia questa stringa. curl restituisce gli stessi modelli in formato JSON. Un elenco vuoto indica che Ollama è in esecuzione, ma non è stato scaricato alcun modello. Connection refused indica che Ollama non è in esecuzione oppure non è in ascolto sulla porta 11434.

Ora aggiungi il provider. Ollama richiede un campo per la API key, ma ne ignora il valore; è quindi sufficiente una stringa non vuota qualsiasi.

llm-pi-ai:
  providers:
    local-ollama:
      apiKeyEnv: OLLAMA_API_KEY
      api: openai-completions
      baseURL: http://127.0.0.1:11434/v1
      models:
        - id: <the exact tag printed by ollama list>

Esporta la variabile nell'ambiente in cui sarà visibile al processo dsh.

sudo install -d -m 700 /etc/dsh
printf 'OLLAMA_API_KEY=ollama\n' | sudo tee /etc/dsh/dsh.env
sudo chmod 600 /etc/dsh/dsh.env

Quasi tutti i tentativi non riusciti rientrano in tre casi. MISSING_CREDENTIAL indica che dsh non è riuscito a leggere la variabile indicata da apiKeyEnv; controlla quindi l'ambiente del processo, non quello del terminale. UNKNOWN_MODEL indica che id non corrisponde a un modello configurato; confrontalo con ollama list carattere per carattere, incluso il tag dopo i due punti. Un errore 401 durante il recupero dei modelli disponibili proviene dal rilevamento dei modelli, che chiama GET /models sull'URL di base; per gli endpoint che non espongono questo percorso, inserisci manualmente i modelli.

Esiste un altro problema comune relativo all'URL di base. Non includere /v1: in caso contrario, le richieste vengono inviate a percorsi che Ollama non espone, la chiamata restituisce un errore 404 e il modello non viene mai eseguito. Il suffisso fa parte dell'interfaccia compatibile con OpenAI, non è un elemento decorativo.

Se Ollama è in esecuzione su un altro computer, l'indirizzo di quel computer diventa l'URL di base e i prompt attraversano quindi la rete in chiaro tramite HTTP non cifrato. Mantieni Ollama sullo stesso host oppure pubblicalo dietro TLS (transport layer security) e autenticazione: proteggere un endpoint Ollama esposto.

Cosa lascia la macchina in ciascuna modalità

Con una chiave DeepSeek, ogni richiesta viene inviata all'API di DeepSeek. La richiesta contiene il prompt, il contenuto dei file letti dall'agente per rispondere, l'output dei comandi eseguiti e gli eventuali risultati degli strumenti che l'agente ha scelto di includere. Il codice sorgente si trova all'interno di questo payload ogni volta che l'agente apre un file. Questo è il funzionamento di un modello ospitato ed è il motivo per cui è importante valutare in quale directory avviare l'agente.

Con un altro provider del catalogo o con un gateway aziendale, lo stesso payload viene inviato a quel fornitore. L'URL di base indica esattamente la destinazione.

Con un endpoint locale, la richiesta al modello viene inviata a 127.0.0.1:11434 e resta sulla macchina. Nessuna parte del codice raggiunge un fornitore di modelli. Tuttavia, tre tipi di dati attraversano ancora la rete. npx scarica il pacchetto dal registro npm. Qualsiasi strumento eseguito dall'agente può accedere autonomamente a Internet, inclusi i server MCP (model context protocol) collegati; l'esecuzione di server MCP su un VPS tratta questo argomento in dettaglio. Un plugin rientra nella stessa categoria, perché installarne uno esegue il codice di un altro autore con i permessi dell'agente. Per questo conviene verificare a quali risorse può accedere un plugin prima di installarlo. Lo stesso vale per la telemetria, se la attivi.

La telemetria è disattivata finché non presti il consenso. DSH_TELEMETRY_MODE è l'impostazione per il consenso; i valori non impostati, vuoti o non riconosciuti vengono interpretati come DISABLED. In questo stato dsh non crea alcun provider, processore o exporter OpenTelemetry (OTel). Un profilo appena creato non effettua quindi alcuna richiesta di rete per la telemetria. FEEDBACK_ONLY abilita la condivisione dei log di sessione attivata dal feedback. FULL consente anche la reportistica del launcher. Il flusso della sessione può esportare contenuti della sessione, dati degli strumenti, prompt e percorsi dell'area di lavoro. Considera quindi FULL come un'impostazione che invia il tuo lavoro a DeepSeek.

Per un blocco completo che non dipenda dall'impostazione corretta della stringa della modalità, imposta DSH_TELEMETRY_DISABLED=1. Qualsiasi valore non vuoto costituisce un'esclusione esplicita e viene letto prima dell'avvio dell'esecuzione. Il codice del progetto non può quindi riattivare la funzione durante la sessione. L'indirizzo predefinito del collector è harness-telemetry.deepseeksvc.com. È utile conoscerlo quando analizzi i log del firewall.

Verifica invece di fidarti dell'impostazione. Con un'attività in esecuzione, elenca le connessioni in uscita mantenute dal processo.

sudo ss -tnp | grep -i node

In modalità modello locale dovresti vedere la connessione di loopback a 11434 e nessuna connessione verso un indirizzo pubblico. Qualsiasi altra connessione deve essere identificata prima di continuare. Cosa invia all'esterno un agente di coding esegue lo stesso controllo con altri harness e spiega come interpretare il risultato.

Dove non devono essere inseriti i secret

  • Cronologia della shell. export DEEPSEEK_API_KEY=sk-... viene scritto in ~/.bash_history in chiaro e rimane lì molto tempo dopo la rotazione della chiave. Anteponi uno spazio al comando quando è impostato HISTCONTROL=ignorespace, oppure evita la shell e scrivi direttamente il valore in un file con modalità 600.
  • File dot versionati. Una chiave in ~/.bashrc o ~/.zshrc può trovarsi a un solo git add di distanza da un repository pubblico se mantieni i file dot in git. Esegui git grep -I -n 'sk-' in quel repository prima del push.
  • settings.yaml. Usa apiKeyEnv per i provider personalizzati, in modo che il file contenga il nome di una variabile anziché un secret. I file di configurazione vengono copiati nei report dei problemi e nelle chat con il supporto. I file delle credenziali no.
  • Output di env e screenshot del terminale. Qualsiasi comando che stampa l'intero ambiente stampa anche la chiave.
  • Backup. Vale la pena eseguire il backup di ~/.dsh, ma .credentials.yaml al suo interno è un secret attivo. Escludi quel file oppure cifra l'archivio.

Queste regole non sono specifiche di dsh e tenere i secret fuori dai file env di Compose tratta lo stesso problema sul lato dei container dello stesso server.

Gestire una developer preview

Bloccare la versione verificata è importante, perché una preview può modificare una chiave di configurazione in una release di patch e impedire al provider di caricarsi. Se l’installazione con versione bloccata rifiuta di avviarsi o npx continua a fornirti una build diversa da quella richiesta, gli errori di installazione e versione generati da una preview descrive la cache di npx e la versione di npm inclusa in Node. Mantieni settings.yaml e cordis.patch.yml sotto controllo versione, escludendo il file delle credenziali, per poter verificare cosa è cambiato dopo un aggiornamento.

Due flag sono utili quando un profilo non si comporta come previsto. --dump-default-config stampa la configurazione predefinita composta senza avviare il servizio, mentre --dump-config stampa nello stesso modo la configurazione composta per il tuo profilo. Il confronto mostra cosa ha modificato effettivamente il tuo livello di patch. È più rapido che leggere manualmente tutti i livelli.

dsh --profile web --dump-config

Quando qualcosa si rompe dopo un aggiornamento, esegui prima questo comando. Se una chiave è stata spostata tra le release, nel dump compare un ramo mancante. La correzione consiste in una modifica di una riga, non in una reinstallazione.

FAQ

Dove archivia dsh la mia chiave API di DeepSeek?

In $DSH_HOME/.credentials.yaml, che corrisponde a ~/.dsh/.credentials.yaml, a meno che non si imposti manualmente DSH_HOME. La pagina Models scrive la chiave in quel file e le impostazioni contengono solo un riferimento, quindi il secret rimane in un unico file. Verificare i permessi con stat -c '%a %n' ~/.dsh/.credentials.yaml e impostarli su 600 se sono meno restrittivi. Un provider personalizzato può evitare del tutto il file specificando una variabile d'ambiente con apiKeyEnv.

Come posso fare in modo che dsh usi un modello locale invece dell'API di DeepSeek?

Aggiungere un provider personalizzato il cui URL di base punti al proprio endpoint locale compatibile con OpenAI. Per Ollama è http://127.0.0.1:11434/v1, con api: openai-completions e un modello id copiato esattamente da ollama list. Ollama richiede un valore per la chiave API ma lo ignora, quindi è sufficiente qualsiasi stringa non vuota. Verificare la risposta dell'endpoint con curl -s http://127.0.0.1:11434/v1/models prima di modificare la configurazione di dsh, perché un endpoint non raggiungibile e una configurazione errata producono errori simili.

dsh invia il mio codice da qualche parte per impostazione predefinita?

Con un modello ospitato, sì. Il prompt e il contenuto dei file letti dall'agent sono inclusi nella richiesta API inviata a quel provider. Con un endpoint locale, la richiesta viene inviata al loopback e rimane sulla macchina. La telemetria è un flusso separato ed è disabilitata per impostazione predefinita: DSH_TELEMETRY_MODE restituisce DISABLED quando non è impostata e, in questo stato, non viene creato alcun exporter. Impostare DSH_TELEMETRY_DISABLED=1 per escludere la telemetria; l'impostazione viene letta prima dell'avvio dell'esecuzione.

Perché dsh segnala MISSING_CREDENTIAL quando la mia variabile è impostata?

Perché dsh legge dall'ambiente del proprio processo la variabile indicata da apiKeyEnv. Una variabile esportata nella shell non è disponibile per un servizio systemd, per la sessione di un altro utente o per un processo avviato prima dell'esportazione. Inserire il valore in un EnvironmentFile con permessi 600 per l'unità, oppure esportarlo nella stessa shell da cui si avvia dsh. Verificare il valore effettivamente disponibile nel processo in esecuzione con sudo tr '\0' '\n' < /proc/$(pgrep -f dsh | head -1)/environ.

Quale versione di Node.js richiede dsh?

Node.js 22.19 o versioni successive della linea 22, oppure 24 e versioni successive. Node 23 non rientra nell'intervallo supportato. Eseguire node -v prima di qualsiasi altra operazione, perché un errore di avvio causato da un runtime non supportato può sembrare un'installazione danneggiata e indurre a reinstallare il pacchetto invece del runtime.