Skip to main content
← All writingAI Infrastructure

How I Use My DGX Spark From My Phone With Tailscale and Termius

Tony KipkemboiTony Kipkemboi··10 min read

A plain-English guide to running your home AI computer from your phone, keeping your work alive when the connection drops, and stopping your AI agents from fighting over one GPU.

I'm writing this from my hotel in Providence, Rhode Island. It's my first time here, and I'm at Brown University for the residential week of my master's program. My DGX Spark, a small AI computer, is at home. Leaving it behind felt a little like dropping a dog off at the kennel: I was pretty sure it would be fine, and I still wanted to check on it.

Lately the Spark has been where I run small experiments and fine-tune models (teaching an existing AI model new tricks). An idea comes up, I queue it, check the results, and move on. For the experiments I'm running, computing power isn't what slows me down, and a trip shouldn't change that.

At the airport I was connected to the Spark from my laptop. Then I boarded and had to put the laptop away, and I wondered whether my phone could do the same job. The machine was still running at home. I just needed another way in.

It can. Here's how I set it up, one problem at a time.

Link to The short versionThe short version

Four tools do the work. Here's what each one does, in plain English:

ToolWhat it does
TailscaleBuilds a private road between my phone and the computer at home
TermiusAn app that lets my phone type commands into that computer
tmuxKeeps my work running on the computer even when my phone drops out
CodexAn AI assistant that runs the commands for me, so I can ask in plain English
Phone connecting to Codex on the Spark, with hosted and optional local inference

One thing to know up front: Codex sends its questions to OpenAI. The work it does (running commands, editing files, starting experiments) happens on my Spark, but the thinking happens on OpenAI's computers. So the hardware is mine, the brain is rented, and anything Codex sees can leave my machine.

Hold onto that last part. We'll come back to it.

Link to Reaching the SparkReaching the Spark

The first problem was the simplest one to state: my phone and the Spark needed to find each other without me opening the Spark to the whole internet, which is not how I like to live.

The Spark was already on Tailscale from when I set it up to run models at home. That gives me a private connection between my devices. On my phone, I signed in to Tailscale with the same account as the Spark. Once both devices showed up, I could reach the Spark from Termius using its Tailscale address.

Tailscale has a setting called Exit Node, which would send all my phone's internet traffic through my house. I left it set to None. I only need to reach one machine, and browsing the web through my own house would be a strange hobby. Tailscale explains the setting in its exit-node documentation.

In Termius, I added a host with:

SettingWhat I entered
AddressThe Spark's Tailscale address
ConnectionSSH
Port22
UsernameMy Linux username on the Spark
AuthenticationMy Spark login credentials

Those are the credentials for the Spark, not the password for my laptop or my Tailscale account. SSH keys work too if that's how you normally connect.

Masked Tailscale and Termius setup screens

The network and host settings I worked through. Account details and addresses are masked. Every screenshot in this post is an AI-edited composite that illustrates the screens rather than reproducing them pixel for pixel.

One thing worth knowing: the Tailscale SSH quickstart in the screenshots covers Tailscale's own SSH feature. You can also use regular SSH over the Tailscale network, and you don't need to turn on the separate feature just because you're using Termius.

Once connected, I had a terminal on the Spark. I ran:

bash
hostname
nvidia-smi

That told me which machine I was on and what was using the GPU. The first time, I typed nvidia-sim. The only witness was my phone.

So I could reach the machine. But I was still typing every command by hand on a phone keyboard, and I didn't want to look up a Linux command for every task.

Link to Talking to the Spark in plain EnglishTalking to the Spark in plain English

The fix was to put an assistant on the Spark, so I could describe a task the way I would on my laptop and let it work out the commands.

I installed Codex CLI directly on the Spark, following the official installation instructions, and signed in with my ChatGPT account. That uses my plan's Codex allowance instead of separate API-key billing. It still has usage limits, and installing it on another machine doesn't add another allowance. (You can't print more quota by adding computers.) See Codex pricing.

I also set it to use ChatGPT sign-in, so I can't accidentally start paying for API usage.

Codex running in Termius and the remote shell

Codex open on my phone, next to the shell and Termius settings.

Now I can type something like:

Check which models are running and how much memory is available. Don't stop or change anything.

I read the answer, ask a follow-up, and approve actions when needed. It's still a terminal, not the chat app, but I don't have to write every command myself.

It worked. Then my phone did what phones do.

Link to When my phone drops outWhen my phone drops out

Phones lose connections. It's part of their personality. I change networks, close Termius, or put the phone away, and a plain terminal session can end right along with the connection. I didn't want my work to end every time my phone wandered off.

tmux is the fix. It keeps the session running on the Spark, and when I reconnect, everything is where I left it. I wrote a small shortcut for it:

bash
~/.local/bin/spark-codex

It's a script I made for my setup, not a command that ships with Codex. It starts or attaches to a named tmux session, checks the login, and starts Codex.

If you're setting up your own, the basic pattern is:

bash
tmux new-session -A -s codex
codex

Run codex when you start a new shell in that session. If you reconnect and Codex is already open, keep going there. (The promise has fine print: tmux survives a disconnect, not a server reboot.)

I also added this to ~/.tmux.conf:

tmux
set -g mouse on

To apply it without restarting the session:

bash
tmux set -g mouse on

That turns on mouse support for scrolling, selecting panes, and resizing them. How finger gestures map to mouse actions depends on your phone terminal's settings. I checked that the option was on at the server.

With the session safe, the next problem wasn't the connection. It was the crowd.

Link to Two agents, one GPUTwo agents, one GPU

The Codex session on the Spark and my conversations on the laptop are like two colleagues who share a budget but not a memory. They share my account's allowance, but not their history. OpenAI covers the difference in its Work and Codex documentation.

I can connect from either device to the same running tmux session on the Spark, and that's how I pick the work back up. But a separate agent on my laptop knows nothing about what's happening on the Spark unless I tell it.

And the Spark was already busy. It has one GPU and, on a given day, several jobs that want it. I worried about an agent on my phone, acting with good intentions and no sense of ownership, freeing up memory by stopping something another session was using. It would be the AI version of a houseguest who reorganizes your kitchen to be helpful.

So I asked for a shared message board where agents check who's doing what before they start anything. That fixed one problem and created another: if every agent wrote long updates, the next one would waste its time reading them.

So the messages are short. Almost caveman short:

text
CLAIMS 1
gpu:gb10 | phone-session | Train speech model. PID 1234.
 
NOTES 1
mac-session>phone-session [conflict] Need GPU. Test 2m. Safe?

(Just an example of the format, not a real training run.)

The board lives on the Spark. Before new work, an agent checks it, claims the resources it needs, and posts a quick update when something changes. If another session owns a resource, the agent messages that session. Interrupting anything that's running still needs my explicit approval, which makes me the judge.

A few rules keep the board small:

  • Task descriptions max out at 120 characters and notes at 180.
  • A new note on the same topic replaces the old one, and notes normally expire after 24 hours.
  • Active work claims don't expire on their own.
  • Older history moves to an archive, so agents don't read the whole record just to find out whether the GPU is busy.

Nothing sits there checking the board all day and burning tokens to report that nothing changed. Agents look at task checkpoints, so replies aren't instant.

The board has a limit, too. It rejects conflicting claims, but it can't stop an agent that ignores it and runs a command anyway. It's a posted rule, not a locked door, and it works because my agents are required to follow it. Existing jobs are protected even if they never made it onto the board.

That left one piece of the setup I couldn't stop thinking about.

Link to Is the brain still rented?Is the brain still rented?

Earlier I said the hardware is mine and the brain is rented. That bothered me a little, because the Spark already runs models of its own. So: could the model run on the Spark too?

Maybe. Codex can use a model that runs right on the Spark, through tools called Ollama or LM Studio, instead of sending questions to OpenAI. I checked the installed CLI's --oss option against OpenAI's documentation and Ollama's integration guide. The phone side wouldn't change: Termius would still reach the Spark over Tailscale.

I haven't tested it, and having a model downloaded isn't enough. The model server has to speak the language Codex expects, and the model has to be good at the kind of tool use Codex asks for. Owning a guitar doesn't make you a band. I haven't tried my existing local language model in that role, and Qwen Image, which I run through ComfyUI, makes images, so it's no help here. A local setup would also compete with everything else for the Spark's GPU and memory, which brings us back to the board. For now, the diagram shows it as an option, not something I have working.

Link to Where this leaves meWhere this leaves me

I still prefer my laptop for plenty of things, and I won't spend hours reviewing code on my phone.

But when an idea hits while I'm away, I can reach the machine, check what's running, and ask it to start work. Later I can return to the same session instead of waiting until I'm home.

The Spark stays home, the experiments keep going, and my phone has been promoted to laptop.

Thanks for reading.← All writing

Discussion

via GitHub Discussions