# Setting up a DGX Spark for AI Development

> Source: <https://gist.github.com/manifestinteractive/48c2fa52cd74a97f115ee9bbddae9df6>
> Published: 2026-08-19 22:58:27+00:00

[Initial DGX Spark Setup](#initial-dgx-spark-setup)[DGX Spark Dependencies](#dgx-spark-dependencies)[Ollama](#ollama)[OpenCode CLI](#opencode-cli)[AI Coding in IDE](#ai-coding-in-ide)[Open WebUI](#open-webui)[Security Considerations](#security-considerations)[Privacy Considerations](#privacy-considerations)[Optional Hardware Recommendations](#optional-hardware-recommendations)

After completing any system updates, the first real thing you would want to do is open the DGX Dashboard application.

- Connect to the DGX Spark using a keyboard, mouse and monitor
- Click
`Show Apps`

icon in bottom left - Search for and Open the
**DGX Dashboard** application - Visit
**Updates** and apply any updates - Visit
**Settings** and update a**Hostname**`*`

if desired ( our documentation uses`dgx-spark`

as the Hostname ) and disable**Telemetry** if desired ( recommended )

`*`

You will need to restart the DGX Spark after changing the Hostname.

You will need to run the following while connected to the DGX Spark.

```
sudo apt update
sudo apt install -y build-essential curl git libbz2-dev libffi-dev liblzma-dev libncursesw5-dev libreadline-dev libsqlite3-dev libssl-dev libxml2-dev libxmlsec1-dev tk-dev uuid-dev xz-utils zlib1g-dev
```

You are likely going to want different versions of Python, other than the 3.12 version that comes with the DGX Spark.

```
curl https://pyenv.run | bash
```

Then add pyenv to your shell startup configuration. Since DGX OS normally uses Bash:

```
cat >> ~/.bashrc <<'EOF'

# pyenv
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"
EOF
```

Also add it to your login profile:

```
cat >> ~/.profile <<'EOF'

# pyenv
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
EOF
```

Reload the shell:

```
exec "$SHELL"
```

Then verify:

```
pyenv --version
```

Connect to DGX Spark

Replace

`aidev`

with you actual username and`dgx-spark`

with your Hostname

```
ssh aidev@dgx-spark.local
```

Install/Update Ollama:

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

Verify Ollama installation:

```
ollama --version
ollama pull qwen3.8:27b
ollama pull qwen2.5-coder:7b
ollama pull nomic-embed-text
```

Verify Ollama models:

```
ollama list
```

| Model | Why this model |
|---|---|
`qwen3.8:27b` |
Primary reasoning/agent model. The ~27B size provides substantially better reasoning, instruction following, code understanding, and multi-step problem solving than a small autocomplete model, while remaining practical to run locally on the DGX Spark. It's intended for chat, code analysis, edits, and agentic work. |
`qwen2.5-coder:7b` |
Dedicated autocomplete model. Autocomplete needs very low latency and is invoked constantly. A specialized 7B coding model is fast enough for interactive completion while still being strong at predicting code, avoiding the latency and compute cost of invoking the 27B model on every keystroke. |
`nomic-embed-text` |
Dedicated embedding/retrieval model. It's purpose-built to turn text and source code into embeddings for semantic search. It's small, fast, and inexpensive to keep available, making it a better choice for codebase indexing/retrieval than using a generative LLM. |

```
sudo systemctl edit ollama
```

Add the following:

```
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
Environment="OLLAMA_CONTEXT_LENGTH=262144"
Environment="OLLAMA_KEEP_ALIVE=-1"
Environment="OLLAMA_NUM_PARALLEL=1"
Environment="OLLAMA_MAX_LOADED_MODELS=3"
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=f16"
Environment="OLLAMA_NO_CLOUD=1"
```

Reload Ollama:

```
sudo systemctl daemon-reload
sudo systemctl restart ollama
```

| Setting | What it does / Why it matters |
|---|---|
`OLLAMA_HOST=0.0.0.0:11434` |
Binds Ollama to all network interfaces instead of localhost only. This allows trusted LAN clients such as the MacBook running VS Code/Continue to reach the DGX Spark. |
`OLLAMA_CONTEXT_LENGTH=262144` |
Sets the model context window to 262K tokens, matching the full context capacity of Qwen 3.8 27B. This gives coding agents maximum working space for repository context, conversation history, tool definitions, command output, diffs, and retrieved code, reducing the need for context compaction during complex or long-running development tasks. |
`OLLAMA_KEEP_ALIVE=-1` |
Keeps loaded models resident in memory indefinitely rather than unloading them after inactivity. This eliminates model reload/cold-start delays during intermittent development work. |
`OLLAMA_NUM_PARALLEL=1` |
Limits each model to one concurrent request. For a primarily single-user coding server, this prioritizes memory efficiency and large-context capacity over request concurrency. |
`OLLAMA_MAX_LOADED_MODELS=3` |
Allows up to three models to remain loaded simultaneously. This matches the intended workload: primary coding/chat model, autocomplete model, and embedding model. |
`OLLAMA_FLASH_ATTENTION=1` |
Enables Flash Attention, an optimized attention implementation that reduces memory usage and can improve performance, particularly with large context windows such as 64K. |
`OLLAMA_KV_CACHE_TYPE=f16` |
Stores the attention KV cache in 16-bit floating-point form. This uses roughly twice the memory of q8_0, but avoids KV-cache quantization and preserves maximum precision, making it preferable when memory capacity is not a constraint. |
`OLLAMA_NO_CLOUD=1` |
Disables Ollama's cloud functionality. This ensures the DGX is configured as a local-only inference server, which is desirable for privacy, security, and predictable data flow. |

Now we are going to preload our largest model into memory on boot. The `qwen3.8:27b`

model has the expensive cold-start penalty. The 7B autocomplete model and Nomic embed model are much smaller and will load comparatively quickly, and will remain in memory after being loaded.

First, let's create our loader script:

```
sudo nano /usr/local/bin/ollama-preload.sh
```

Then enter the following code:

``` bash
#!/bin/bash

set -e

OLLAMA_URL="http://127.0.0.1:11434"
MAX_ATTEMPTS=30
SLEEP_SECONDS=2

for ((attempt=1; attempt<=MAX_ATTEMPTS; attempt++)); do
    if curl -sf "${OLLAMA_URL}/api/tags" >/dev/null; then
        echo "Ollama is ready."
        break
    fi

    if (( attempt == MAX_ATTEMPTS )); then
        echo "ERROR: Ollama did not become ready within 60 seconds." >&2
        exit 1
    fi

    sleep "${SLEEP_SECONDS}"
done

echo "Preloading qwen3.8:27b..."

curl --fail --silent --show-error \
    "${OLLAMA_URL}/api/generate" \
    -H "Content-Type: application/json" \
    -d '{"model":"qwen3.8:27b","keep_alive":-1}'

echo "Model preload complete."
```

Now let's make that executable:

```
sudo chmod +x /usr/local/bin/ollama-preload.sh
```

Create systemd service:

```
sudo nano /etc/systemd/system/ollama-preload.service
```

Use the following code:

```
[Unit]
Description=Preload Ollama      
Requires=ollama.service
After=ollama.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/ollama-preload.sh
TimeoutStartSec=120
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
```

Reload System:

```
sudo systemctl daemon-reload
sudo systemctl enable ollama-preload.service
sudo systemctl start ollama-preload.service
```

One you have setup your DGX Spark, you can use [OpenCode](https://opencode.ai/) in your terminal on any machine that has access to the DGX Spark.

```
curl -fsSL https://opencode.ai/install | bash
```

Then you can confirm it is installed:

```
opencode --version
```

Create a directory:

```
mkdir -p ~/.config/opencode
```

Create your config file:

```
nano ~/.config/opencode/opencode.json
```

Paste in the JSON from [openconfig.json](#file-openconfig-json)

Create agents folder:

```
mkdir -p ~/.config/opencode/agents/
```

Create agent files inside that folder:

In your terminal, you can now run:

```
opencode models ollama
```

You should see:

```
ollama/qwen2.5-coder:7b
ollama/qwen3.8:27b
```

Now you can change to any project directory where you want to work, and run:

```
cd /path/to/your/project
opencode
```

Then to test OpenCode you can just ask a starter question like:

```
What can you tell me about this project?
```

If you would like to use your DGX Spark in your IDE:

Install the [Continue.dev](https://docs.continue.dev/ide-extensions/install) IDE Extension.

Create your config file:

```
nano ~/.continue/config.yaml
```

Paste in the following:

```
name: DGX Spark
version: 1.0.0
schema: v1
models:
  - name: Qwen 3.8 27B
    provider: ollama
    model: qwen3.8:27b
    apiBase: http://dgx-spark.local:11434
    roles:
      - chat
      - edit
      - apply
    capabilities:
      - tool_use
      - image_input
  - name: Qwen 2.5 Coder 7B
    provider: ollama
    model: qwen2.5-coder:7b
    apiBase: http://dgx-spark.local:11434
    roles:
      - autocomplete
  - name: Nomic Embed
    provider: ollama
    model: nomic-embed-text
    apiBase: http://dgx-spark.local:11434
    roles:
      - embed
context:
  - provider: code
  - provider: codebase
  - provider: currentFile
  - provider: diff
  - provider: docs
  - provider: folder
  - provider: open
  - provider: problems
  - provider: terminal
  - provider: tree
```

Now all you need to do is Open the Continue Extension in your IDE ( restart your IDE if it was already open ).

Connect to DGX Spark

```
ssh aidev@dgx-spark.local
```

Install required version of Python

```
pyenv install 3.11.13
```

Create a dedicated Open WebUI environment

```
mkdir -p ~/apps/open-webui
cd ~/apps/open-webui
```

Tell pyenv that this directory should use Python 3.11:

```
pyenv local 3.11.13
```

Now create the virtual environment:

```
python -m venv .venv
```

Activate it:

```
source .venv/bin/activate
```

Upgrade packaging tools:

```
python -m pip install --upgrade pip setuptools wheel
pip install open-webui
```

Test that this runs as expected:

```
export OLLAMA_BASE_URL="http://localhost:11434"
export DO_NOT_TRACK="true"
export SCARF_NO_ANALYTICS="true"
export ANONYMIZED_TELEMETRY="false"

open-webui serve --host 0.0.0.0 --port 8080
```

This DGX Spark configuration is designed for flexible development use across both trusted home networks and direct-wired travel environments. The appropriate security posture depends on how the Spark is connected, with additional firewall protections recommended whenever it must operate on an untrusted or unknown network.

When the DGX Spark is connected to a trusted private home Wi-Fi network, a host-level firewall such as UFW is generally optional. The home router/firewall provides the primary security boundary against unsolicited Internet traffic.

For travel, a direct Ethernet connection between the development laptop and DGX Spark provides a simple private network. This avoids placing the DGX Spark directly on hotel, conference, airport, or other untrusted Wi-Fi networks.

If the DGX Spark must connect directly to a network that is public, shared, or not fully trusted, enable a host firewall.

When administering the Spark remotely, verify that SSH is permitted **BEFORE** enabling UFW to avoid locking yourself out.

Ubuntu's UFW provides a straightforward baseline:

```
sudo ufw default deny incoming
sudo ufw default allow outgoing
```

Then explicitly permit only required services. For example:

```
# SSH
sudo ufw allow 22/tcp

# Ollama
sudo ufw allow 11434/tcp

# Example development server
sudo ufw allow 3000/tcp
```

Enable and verify the firewall:

```
sudo ufw enable
sudo ufw status verbose
```

**Important**: When default deny incoming is enabled, every remotely accessible service must be explicitly permitted. Developers running dynamic Node.js applications, Vite servers, Jupyter, debugging tools, or other services will need to add rules for their respective ports.

Prevent submitting hardware configuration, RAM/disk sizes, timezone, language, etc.

```
ubuntu-report -f send no
```

Disable VS Code telemetry

- Open VS Code.
- Press
`Cmd`+`,` to open Settings. - In the search box, enter:

```
telemetry
```

- Find Telemetry: Telemetry Level.
- Set it to:

```
off
```

You an also uncheck everything else you want to disable.

```
{
    "allowAnonymousTelemetry": false
}
```

In your `~/.config/opencode/opencode.json`

file:

```
{
  "share": "disabled"
}
```

**External USB-C SSD (2–4 TB+)**- Useful for storing training datasets, RAG collections, media, model exports, checkpoints, and other bulk data while reserving the DGX Spark's internal NVMe for frequently accessed models, caches, applications, and performance-sensitive AI workloads.**USB-C to Ethernet Adapter**- Provides the laptop with a dedicated wired Ethernet connection to the DGX Spark when Wi-Fi is unavailable, untrusted, or undesirable. Particularly useful for laptops without built-in Ethernet.**CAT6 Cable (3 ft)**- Enables a simple, fast direct connection between the development laptop and DGX Spark without relying on hotel, conference, or other external network infrastructure.**HDMI Dummy Plug**- A DGX Spark can operate completely headless and does not require a monitor for SSH, Ollama, Jupyter, NVIDIA Sync, or other network-based development workflows. However, an inexpensive HDMI dummy plug can be useful if you plan to use the Ubuntu graphical desktop remotely, as it causes the system to detect a persistent display and can avoid resolution, remote-desktop, or display-session issues sometimes encountered on fully headless systems.**Compact Keyboard w/ Trackpad**- Primarily a recovery tool. Useful if you need local console access and can't restore networking remotely.** USB-C to USB-A Adapter**- The DGX Spark provides USB-C ports but no traditional USB-A ports. A compact adapter is useful for connecting common keyboards, mice, USB flash drives, recovery media, and other legacy USB peripherals, particularly when troubleshooting or performing system recovery.**Compact HDMI Cable**- Worth carrying as a recovery option. If networking, SSH, or remote desktop configuration fails, you can connect the Spark to a hotel TV or other available HDMI display for troubleshooting.
