One Command to Hand Your VPS to an AI Agent: Ditch Manual SSH with daimon-mcp
Buying a VPS has never been cheaper — or more common. But the step right after "pay for it" hasn't changed in years: most people still SSH in and type commands one by one, or grab a random automation script and hand-edit the parameters.
The setup pain is only half of it. The bigger problem is debugging when something breaks: you can't remember which commands you ran or which config file you touched, and you end up wading through .bash_history and pages of logs — more work than the setup itself.
This post introduces a new approach: on a fresh VPS, install the processd service with one command, then connect Claude Code, Codex, or other agents via MCP and let the AI operate that remote VPS from your local machine.
Why the old way hurts
The mainstream flow today:
- Manual SSH configuration: log in, change the SSH port, install Docker, configure the firewall, pull code, start services — every step typed by hand, easy to miss, easy to break.
- Automation scripts: one-liner scripts are fast, but to be "generic" they stuff in a ton of things you don't need, and when something goes wrong you don't even know what the script did.
Both share the same flaw: setup and debugging all fall on you. An AI agent, by contrast, is exactly good at "follow the docs, run a sequence of commands, and read logs when something fails." It just needs a stable, safe channel to send commands into the VPS.
The new way: MCP remote ops
processd (publicly branded daimon-mcp) does one simple thing: it runs an MCP server on your VPS that exposes the same tools Claude Code has built in — Bash, Read, Write, Edit, Glob, Grep, WebFetch, plus an interactive PTY.
Point Claude Code, Codex, or Cursor at that MCP endpoint, and the agent drives the remote VPS's terminal and filesystem as if they were local.
The key difference in experience: you don't need to install Codex on the remote VPS. Your agent runs on your local machine; the VPS only keeps a lightweight processd-mcp service acting as the agent's "hands" reaching in.
- Setting up: you tell the local agent "configure this VPS for me," and it executes commands one by one over MCP — no SSH — reading output as it goes.
- Debugging: the agent sees full command context and error output, so it follows the logs downward instead of you retyping everything from scratch.
Install the processd service with one command
On a fresh VPS (Debian / Ubuntu, systemd), SSH in once and run this:
curl -fsSL https://github.com/daimon-hq/release/releases/latest/download/install-processd-kernel.sh | sudo bash -s -- install
It will:
- write the binary
/usr/local/bin/processd-mcp(static musl, available for amd64 / arm64); - create a systemd unit
processd-mcp.service; - create
/etc/processd-mcp/processd-mcp.env, bound to127.0.0.1:8080by default, with a randomPROCESSD_TOKEN.
Verify it:
sudo systemctl status processd-mcp --no-pager
curl -i http://127.0.0.1:8080/health # returns 204
sudo awk -F= '/^PROCESSD_TOKEN=/{print $2}' /etc/processd-mcp/processd-mcp.env
That last command prints the access token you'll need next.
Point the listen address at something your machine can reach
One easily-missed step: the installer defaults MCP_HOST to 127.0.0.1, i.e. it only listens on the VPS's own loopback. Your local machine's agent can't reach the remote VPS's 127.0.0.1. So you also need to change the listen address to one your computer can reach (the VPS's LAN IP, or a Tailscale IP), then restart:
sudo sed -i 's/^MCP_HOST=.*/MCP_HOST=<address your machine can reach>/' /etc/processd-mcp/processd-mcp.env
sudo systemctl restart processd-mcp
Replace <address your machine can reach> with the VPS's LAN IP or a Tailscale IP. For production, strongly prefer Tailscale (see the security note below) — do not use 0.0.0.0 to expose the port straight to the public internet.
Connect Claude Code / Codex
Back on your local machine, add this to your agent config (Claude Code uses .mcp.json; Codex uses its MCP settings):
{
"mcpServers": {
"daimon": {
"type": "http",
"url": "http://<VPS address>:8080/mcp",
"headers": {
"X-Access-Token": "<PROCESSD_TOKEN>"
}
}
}
}
Replace <VPS address> with your VPS IP (or Tailscale IP — see below) and the token with the value you just read. Reload the config, and the agent's tool list gains Bash, Read, Write, Edit, Glob, Grep, and friends.
From there it's natural language, e.g.:
"Install Docker on this machine and start an nginx container listening on port 80."
The agent runs commands through MCP Bash, reads logs and configs with Read/Grep, and keeps going until it's done.
Drive the remote VPS from the Codex App GUI locally
Codex ships a desktop GUI in addition to the CLI. You can launch the Codex App GUI on your local machine, configure the MCP endpoint, and issue instructions from the graphical interface to operate the remote VPS — no Codex installed on the VPS, just that lightweight processd-mcp service.
Local GUI handles "thinking + interaction," the remote processd-mcp handles "execution," and MCP ties the two together. To the VPS, it only sees local commands coming from processd-mcp — clean and controllable.
Advanced policy config: restrict which folders MCP can touch
processd-mcp is more than a pass-through: it ships a kernel-level sandbox whose policy file can precisely restrict which paths the agent may read and write, and whether it can reach the network. This matters a lot when handing an agent a production VPS — you don't want one careless move to touch /etc or ~/.ssh.
Enable the policy
Download an example policy to /etc/processd-mcp/policy.yaml:
sudo curl -fsSL https://github.com/daimon-hq/release/releases/latest/download/sandbox-policy.example.yaml \
-o /etc/processd-mcp/policy.yaml
sudo chmod 644 /etc/processd-mcp/policy.yaml
sudo $EDITOR /etc/processd-mcp/policy.yaml
Then point the env file at it and restart:
echo 'MCP_SANDBOX_POLICY_FILE=/etc/processd-mcp/policy.yaml' | \
sudo tee -a /etc/processd-mcp/processd-mcp.env
sudo systemctl restart processd-mcp
What the policy looks like
version: 2
filesystem_policy:
include_workdir: true # auto-add the process cwd as read-write
read_only:
- /var/log # readable, not writable
read_write:
- /workspace # replace with your real project dir
network:
mode: disabled # disabled | localhost_only | enabled
linux:
landlock:
compatibility: hard_requirement # hard_requirement | best_effort
process:
run_as_user: user # must exist, must not be root
run_as_group: user
Key points:
- Filesystem:
read_onlymeans readable-only,read_writemeans read-write. The agent can't touch anything outside the lists — leave your SSH private keys out, and it simply can't reach them. - Network:
disabledcuts networking entirely (strictest, good default),localhost_onlyallows loopback,enabledopens it up. - Identity:
run_as_user/run_as_groupdrop to a non-root account inside the sandbox; combined withhard_requirement, startup fails if Landlock can't attach — better to refuse to start than to run degraded.
The policy loads once at startup, so restart after edits. Use GetRuntimeContext afterward to see the active policy.
FAQ
Why not just have local Codex SSH in directly?
The most common question, and direct SSH has two real flaws:
1. Every command needs a long SSH prefix, and double-concatenation breeds errors.
With direct SSH, the agent emits something like:
ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=no -p 22 user@1.2.3.4 "ls -la /var/www"
The actual ls -la /var/www it wants to run is wrapped in a long SSH parameter list. Every command the agent generates has to first build the prefix, then build the real command — two layers of concatenation where quote escaping, variable expansion, and newline handling can each break the command. The more complex the command, the more likely it fails.
Over MCP, the agent emits just ls -la /var/www, and processd-mcp runs it remotely. No prefix, no escaping hell.
2. Each SSH is effectively a fresh window — no state is preserved.
SSH is stateless: you cd /workspace, but the next SSH is a brand-new shell, $PWD is back to home, and exported env vars, activated virtualenvs, and background processes are all gone. The agent either keeps re-cd-ing or stuffs everything into one giant command.
processd-mcp's Bash runs in a persistent shell session — working directory, environment variables, and background jobs all carry over, so the agent can naturally "cd, then git pull, then docker compose up" step by step, just like you sitting in that terminal.
How does this compare to installing Codex on the remote VPS?
Installing Codex remotely means squeezing a full agent runtime (models, tools, dependencies) into the VPS — more resource usage, more setup complexity, a bigger surface to debug when something breaks. processd-mcp is a single static binary on the VPS; the agent stays on your local machine, so the VPS stays lean and easy to maintain.
Security note: traffic is not encrypted — use Tailscale in production
One limitation that must be stated plainly: processd-mcp's wire is plain HTTP, with no TLS. The X-Access-Token is a shared secret for authentication, not encryption. So never set MCP_HOST=0.0.0.0 and expose port 8080 directly to the public internet.
The right move is Tailscale to bring the VPS and your local machine into the same tailnet:
TS_IP=$(tailscale ip -4)
sudo sed -i "s/^MCP_HOST=.*/MCP_HOST=${TS_IP}/" /etc/processd-mcp/processd-mcp.env
sudo systemctl restart processd-mcp
Then put that Tailscale IP in your agent's url. Traffic rides inside Tailscale's encrypted tunnel, and no port needs to open to the public. You can also keep the loopback bind and forward with tailscale serve. Bottom line: use Tailscale in production, don't run naked.
Summary
- Traditional VPS ops: manual SSH or one-liner scripts — tedious to set up, worse to debug.
- The new way: install
processd-mcpwith one command, expose the remote terminal to Claude Code / Codex over MCP. - Better experience: no Codex needed on the VPS; run the agent (even a GUI) locally to drive the remote box.
- Control: a kernel-level policy file restricts which folders the agent can access or modify, and whether it can reach the network.
- Safety floor: plain HTTP — use Tailscale for anything real.
Full details (client setup, cluster mode, SDK, complete policy fields) live in the official docs: https://daimon-hq.github.io/ .