One Command to Hand Your VPS to an AI Agent: Ditch Manual SSH with daimon-mcp

·9 min read·BIGWONG Studio
AILinuxTailscale

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:

  1. 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.
  2. 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 to 127.0.0.1:8080 by default, with a random PROCESSD_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_only means readable-only, read_write means 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: disabled cuts networking entirely (strictest, good default), localhost_only allows loopback, enabled opens it up.
  • Identity: run_as_user / run_as_group drop to a non-root account inside the sandbox; combined with hard_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-mcp with 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/ .