DEV Community

Alex Kernel
Alex Kernel

Posted on

Homelab Fleet Management with AI: 7 remote-agents Recipes (2026)

If your idea of homelab fleet management is currently five terminal tabs, a sticky note with IP addresses, and the dawning horror of remembering which Pi runs apt and which runs dnf — this guide is for you. We'll wire up a real mixed-architecture homelab (NAS, two Raspberry Pis, a Docker media box, and your desktop) so you can drive the whole thing from one AI chat instead of hopping between SSH sessions. The engine is the open-source MCP server remote-agents.

In short: a lightweight agent runs on every machine and dials outbound into an encrypted relay room. Your AI assistant (Claude or opencode) sees the whole homelab as one computer and calls tools like fleet_exec, fleet_read, schedule_add, exec, and set_mode. Command payloads are end-to-end encrypted (AES-GCM-256) — the relay only ever forwards ciphertext, never plaintext, never keys.

Table of Contents

  1. Architecture: five hosts, one room
  2. Recipe 1 — Install agents and tag the homelab
  3. Recipe 2 — One-command system updates across every Linux host
  4. Recipe 3 — Nightly backups to the NAS that survive a relay outage
  5. Recipe 4 — Whole-fleet health, disk, and temperature sweep
  6. Recipe 5 — Docker management on the media host
  7. Recipe 6 — Safe read-only inspection with plan mode and the denylist
  8. FAQ
  9. Wrapping up

Architecture: five hosts, one room

A homelab is rarely uniform. You've got x86 boxes, ARM boards, mostly Linux with maybe a stray macOS mini, and a wild mix of stacks. That heterogeneity is exactly what makes manual self-hosted server management painful — every host wants a slightly different incantation. Tags and OS-family targeting smooth that over: you address a group of machines in a single call, and the failures stay per-host instead of sinking the whole batch.

Here's the topology we'll use for the rest of this guide:

Host Role Tag Stack
nas Storage, backup target, shares storage TrueNAS / Linux, ZFS, NFS/SMB
pi-1 DNS / ad-block, light services pi Raspberry Pi (ARM64), Debian
pi-2 Sensors / home automation pi Raspberry Pi (ARM64), Debian
media Jellyfin / Plex, Docker host media x86 Linux, Docker Compose
desk Your main desktop / workstation workstation x86 Linux (or macOS mini)

Every agent joins the same relay room (say, homelab). It's a flat peer network — there's no controller node and no agent node, every machine joins as an equal peer that can both execute and dispatch. Tags let you fan out: target="pi" hits both Raspberry Pis, target="os:linux" hits every Linux box, and target="all" hits the entire fleet.

            ┌───────────── AI (Claude / opencode) ──────────────┐
            │            remote-agents (MCP, stdio)              │
            └──────────────────────┬────────────────────────────┘
                                   │ wss:// (E2E encrypted)
                           ┌───────┴────────┐  relay (CF Worker or self-hosted)
                           │   room=homelab  │
        ┌──────────┬───────┴────┬───────────┬──────────────┐
      nas         pi-1        pi-2        media           desk
   (storage)      (pi)        (pi)       (media)      (workstation)
    x86/ZFS       ARM64       ARM64      x86/Docker      x86 desktop
Enter fullscreen mode Exit fullscreen mode

The neat part: that relay can be Cloudflare's hosted Worker, or your own self-hosted Rust relay (remote-agents-relay --bind 0.0.0.0:8080) running on the NAS itself. For a homelab that never wants to phone home to a cloud, self-hosting the relay keeps the entire control plane inside your own four walls.

Quick summary: the 6 recipes at a glance

# Recipe What it does
1 Install & tag Put an agent on every host and tag it (storage, pi, media, workstation)
2 Fleet updates Patch every Linux host with one fleet_exec; refresh the agents with fleet_update_check
3 Nightly backups schedule_add a 6-field on-host cron that backs up to the NAS even if the relay drops
4 Health sweep fleet_exec df -h / sensors / uptime with per-host results across x86 and ARM
5 Docker exec docker compose pull && up -d and prune on the media host
6 Safe inspection plan mode for read-only audits, plus the E2E + denylist guarantees

Why manage a homelab fleet this way

Before the recipes, it's worth being honest about when this approach earns its keep — and when it doesn't. Reach for AI-driven homelab automation when:

  • You're tired of SSH hopping. Patching five hosts by hand is five logins, five sudo prompts, and at least one "wait, was that the Pi or the NAS?" moment. One fleet_exec replaces all of it — roughly one command instead of N SSH sessions.
  • Your hardware is mixed. ARM Raspberry Pis and x86 boxes need different package managers and report sensors differently. OS-family targeting (os:linux) and tags let one request adapt per host without you branching by hand.
  • You want unattended, resilient automation. Scheduled backups should fire even if your laptop is closed and the relay is unreachable. On-host cron via schedule_add keeps running locally regardless of link state.
  • You want a single audit surface. A read-only plan-mode sweep across the whole fleet gives you a snapshot of every machine's disk, temperature, and uptime in one shot — perfect for the weekly "is anything quietly dying?" check.

It's not a replacement for Ansible playbooks or a Kubernetes orchestrator. Think of remote-agents as interactive plus autonomous access to shell, files, git, and cron across many hosts through one AI interface — ideal for small-to-medium fleets, dev/lab environments, and ad-hoc operations.


Recipe 1 — Install agents and tag the homelab

Everything starts with putting an agent on each box and giving it a tag. The package is a single Rust binary, so install is the same everywhere — only the --name and --tags change per host.

Step 1. Install and run on each machine. On 24/7 hosts like the NAS and the media box, use remote-agents install so the agent comes back as a background service (systemd on Linux, launchd on macOS) after a reboot. On the Pis and desktop you can do the same, or just run it interactively while you experiment.

# once on every machine
npm i -g remote-agents

# NAS — 24/7, install as a background service
remote-agents install --relay wss://<relay> --room homelab --token <secret> \
  --name nas --tags storage

# the two Raspberry Pis (ARM)
remote-agents install ... --name pi-1 --tags pi
remote-agents install ... --name pi-2 --tags pi

# Docker media host
remote-agents install ... --name media --tags media

# your desktop / workstation
remote-agents run ... --name desk --tags workstation
Enter fullscreen mode Exit fullscreen mode

Step 2. Confirm the whole fleet is online. In your AI chat, just ask:

"Show me the agents in the homelab room."

Under the hood that calls list_agents, which returns each peer's OS family, distro, kernel, shell, tags, and an update_available flag. This is your inventory — in one response you can see that pi-1 and pi-2 report aarch64/Debian while nas and media report x86_64, which is exactly the kind of detail that decides whether you use apt or dnf later.

Tip: Resolution order for settings is CLI flag > REMOTE_AGENTS_* env > config.toml > default. For 24/7 hosts, drop the relay/room/token into config.toml so the systemd unit stays clean and secrets aren't baked into the command line.


Recipe 2 — One-command system updates across every Linux host

This is the headline win for homelab fleet management: patching the entire fleet in a single call instead of logging into each box. Because your hosts span Debian-based Pis and possibly an RPM-based NAS, you'll target by OS family and let each host run its own package manager.

Step 1. Patch every Linux host at once. The target="os:linux" selector hits nas, pi-1, pi-2, media, and desk (if it's Linux) in one shot. Use a command that works regardless of distro by trying both managers:

fleet_exec  target="os:linux"
            command="(command -v apt-get >/dev/null && sudo apt-get update && sudo apt-get -y upgrade) || (command -v dnf >/dev/null && sudo dnf -y upgrade)"
            timeout_ms=600000
Enter fullscreen mode Exit fullscreen mode

Results come back per host: pi-1 and pi-2 report their apt upgrade, the NAS reports its own, and if one box is offline the others still complete — one failing host does not sink the batch. The Raspberry Pis, being ARM, pull arm64 packages while the x86 boxes pull amd64; you don't have to think about it, each host resolves its own architecture.

Note: Bump timeout_ms for upgrades — a big apt upgrade on a first-gen Pi over a slow SD card can easily run past the default. 600000 ms (10 minutes) is a safe ceiling for a homelab.

Step 2. Update the agents themselves. Software that manages your fleet should keep itself current. fleet_update_check reports which idle hosts are running an older version:

fleet_update_check
Enter fullscreen mode Exit fullscreen mode

Then refresh the ones that are behind:

fleet_exec  target="all"  command="npm i -g remote-agents@latest"
Enter fullscreen mode Exit fullscreen mode

Important: fleet_update_check deliberately only flags idle hosts. A host mid-task won't get yanked out from under a running job — you can patch it on the next pass.


Recipe 3 — Nightly backups to the NAS that survive a relay outage

Backups are the one job you absolutely cannot have depend on your laptop being awake. The trick here is schedule_add, which installs a cron job that runs on the host itself — so it fires every night even if the relay link is down, your AI client is closed, or your internet is out.

Step 1. Schedule a nightly pull from a Pi to the NAS. The cron spec is a 6-field string (sec min hour day month dow), which is one field more than classic crontab — the extra leading field is seconds. For 02:30 every night that's 0 30 2 * * *:

schedule_add  agent_id=pi-1  name=nightly-backup
              cron="0 30 2 * * *"
              command="rsync -aH --delete /home/pi/data/ nas:/mnt/tank/backups/pi-1/"
Enter fullscreen mode Exit fullscreen mode

Step 2. Do the same for the other Pi and the media box, pointing each at its own folder under the NAS backup pool:

schedule_add  agent_id=pi-2   name=nightly-backup  cron="0 35 2 * * *"  command="rsync -aH --delete /home/pi/data/ nas:/mnt/tank/backups/pi-2/"
schedule_add  agent_id=media  name=config-backup   cron="0 40 2 * * *"  command="tar czf - /srv/docker | ssh nas 'cat > /mnt/tank/backups/media/docker-configs.tgz'"
Enter fullscreen mode Exit fullscreen mode

Staggering the start times (02:30, 02:35, 02:40) keeps three machines from hammering the NAS at the same second. The backups land in ZFS-backed storage on TrueNAS, so you can layer snapshots on top for point-in-time recovery.

Step 3. Verify what's scheduled. List and prune jobs at any time:

schedule_list    agent_id=pi-1
schedule_remove  agent_id=pi-1  name=nightly-backup
Enter fullscreen mode Exit fullscreen mode

Tip: Because the schedule lives on the host, a schedule_add you set today keeps running even if you never open your AI chat again. Treat schedule_list as your "what cron jobs did past-me set up?" audit — run it across hosts occasionally so nothing becomes a forgotten mystery.


Recipe 4 — Whole-fleet health, disk, and temperature sweep

Once a week, you want a single answer to "is anything in my homelab quietly dying?" One fleet_exec gives you disk usage, temperature, and uptime from every host, with results grouped per machine.

Step 1. Disk usage across the whole fleet. Free space is the classic silent killer — a full / will brick a Pi and stall Docker on the media box:

fleet_exec  target="all"  command="df -h / /mnt 2>/dev/null"
Enter fullscreen mode Exit fullscreen mode

Step 2. Temperatures, accounting for x86 vs ARM. This is where the architecture split matters. On x86 boxes (nas, media, desk) the standard tool is sensors from lm-sensors. On the ARM Raspberry Pis, sensors often returns nothing useful — the canonical reading comes from vcgencmd instead. A command that adapts on each host:

fleet_exec  target="all"
            command="(vcgencmd measure_temp 2>/dev/null) || (sensors 2>/dev/null | grep -iE 'temp|core' | head -n 5) || echo 'no temp sensor'"
Enter fullscreen mode Exit fullscreen mode

The Pis will answer with something like temp=48.3'C from vcgencmd, while the x86 hosts answer with Core 0: +42.0°C from sensors. You get one tidy per-host readout despite two completely different sensor stacks.

Step 3. Uptime and load to spot the limpers:

fleet_exec  target="all"  command="uptime && free -h | head -n 2"
Enter fullscreen mode Exit fullscreen mode

Note: ARM Raspberry Pis and x86 hosts report differently almost everywhere — package managers, sensors, even the meaning of high load (a four-core Pi saturates faster than a desktop). When a per-host result looks weird, check whether you're reading a Pi (os:linux + tag pi, aarch64) before you panic. Throttling on a Pi (throttled=0x... from vcgencmd get_throttled) is the homelab equivalent of a check-engine light.

If you'd rather get the disk sweep separately for just the storage tier, swap target="all" for target="storage" and you'll only hit the NAS.


Recipe 5 — Docker management on the media host

The media box runs your Jellyfin/Plex stack under Docker Compose. Container lifecycle is a great fit for plain exec scoped to that single host — no need to fan out a fleet operation for a box-specific job.

Step 1. Pull updated images and recreate the stack. A pull followed by up -d is the standard zero-fuss update:

exec  agent_id=media
      command="cd /srv/docker/media && docker compose pull && docker compose up -d"
      cwd=/srv/docker/media
      timeout_ms=300000
Enter fullscreen mode Exit fullscreen mode

docker compose up -d only recreates the containers whose images actually changed, so unchanged services (and your active Jellyfin streams) stay up. The pull can be chunky on a media stack, hence the generous 300000 ms (5-minute) timeout.

Step 2. Check container health and recent logs:

exec  agent_id=media  command="docker compose ps"
exec  agent_id=media  command="docker compose logs --tail 50 jellyfin"
Enter fullscreen mode Exit fullscreen mode

Step 3. Reclaim disk after updates. Old image layers pile up fast on a media host. Prune them — but be deliberate about it:

exec  agent_id=media  command="docker image prune -f && docker builder prune -f"
Enter fullscreen mode Exit fullscreen mode

Important: Plain docker system prune -af will also remove all unused images and can nuke volumes if you add --volumes. On a media host where you cache large images, prefer the narrower docker image prune -f shown above so you don't re-download tens of gigabytes on the next up. Let the AI propose the command in plan mode first (next recipe) and read it before you let it run.


Recipe 6 — Safe read-only inspection with plan mode and the denylist

You should never have to choose between "convenient" and "safe" on machines that hold your photos, backups, and home automation. remote-agents gives every host a safety mode you set with set_mode:

  • plan — read-only. Only read_file, git_status, and safe exec are allowed. Perfect for inspecting a host without any chance of changing it.
  • edit — writes allowed, and the agent makes an automatic backup before overwriting any file.
  • bypass — unrestricted access.
  • disabled — the agent rejects everything.

The natural homelab workflow is: inspect in plan, then flip to edit only for the moment you actually need to change something, then flip back.

set_mode  agent_id=nas  mode=plan     # look around, change nothing
# ... you've decided a config needs editing ...
set_mode  agent_id=nas  mode=edit     # writes now allowed, with auto-backup
# ... done ...
set_mode  agent_id=nas  mode=plan     # back to read-only
Enter fullscreen mode Exit fullscreen mode

A read-only sweep pairs beautifully with this. Set the whole fleet to plan and ask the AI to report what it finds — it physically can't modify anything:

fleet_read  target="all"  path=/etc/os-release
fleet_search  target="storage"  query="zpool"
Enter fullscreen mode Exit fullscreen mode

Two guarantees hold no matter what mode you're in. First, every command and result payload is end-to-end encrypted (AES-GCM-256, key derived from your room token) — the relay forwards ciphertext blind and never sees your data or keys. Second, a hard deny-list (paths like /etc/shadow and /boot) is enforced even in bypass mode, so an over-eager AI literally cannot read your shadow file or scribble in your boot partition.

Tip: For a recurring "is anything wrong?" audit, keep the whole fleet in plan mode by default and only promote a single host to edit for the exact window you're making a change. It turns a slightly scary AI-with-shell-access into a read-only dashboard that you consciously unlock.


FAQ

How is this different from Ansible or a dashboard like Cockpit?

It's complementary, not a replacement. Ansible is great for declarative, repeatable provisioning; Cockpit is a per-host web UI. remote-agents gives you interactive and autonomous access to shell, files, git, and cron across your whole homelab through one AI conversation, with end-to-end encryption. It shines for ad-hoc operations, mixed x86/ARM fleets, and "just go do this across everything" tasks.

Do I need a cloud account to manage my home servers with AI?

No. You can use the hosted Cloudflare relay, or run the self-hosted Rust relay (remote-agents-relay --bind 0.0.0.0:8080) on a box you already own — the NAS is a natural home for it — and point every agent at ws://your-host:8080. The entire control plane then stays inside your LAN.

Will my Raspberry Pis and x86 boxes need different commands?

Often, yes — and that's handled for you. Use target="os:linux" or tags like target="pi" to address groups, and write commands that adapt per host (try apt then dnf, try vcgencmd then sensors). Each host runs the branch that fits its architecture, and results come back per-host so you can see exactly what each machine did.

What happens to my scheduled backups if the internet goes down?

They still run. schedule_add installs a 6-field cron job that lives on the host itself, so it fires on time even if the relay link drops, your AI client is closed, or your WAN is out. The relay is only needed when you want to issue or inspect commands live.

Is it safe to give an AI shell access to my homelab?

Start every host in plan mode (read-only). The hard deny-list on critical paths like /etc/shadow and /boot is enforced even in bypass mode, all payloads are end-to-end encrypted, and the relay forwards them blind. You promote a host to edit or bypass only for the specific window you need it, then drop it back.


Wrapping up

That's homelab fleet management without the tab-juggling: one AI chat patches every Linux host with a single fleet_exec, schedules NAS backups that survive an outage, sweeps disk and temperature across x86 and ARM in one readout, manages Docker on the media box, and keeps the dangerous stuff behind plan mode, end-to-end encryption, and an unbreakable deny-list. Five machines, zero manual SSH sessions, and a homelab that finally behaves like one computer you can talk to.

Install: npm i -g remote-agents
package on npm ·
source & docs on GitHub

Top comments (0)