{"slug": "show-hn-pvewarden-let-an-ai-agent-patch-proxmox-vms-without-giving-it-a-shell", "title": "Show HN: pvewarden – let an AI agent patch Proxmox VMs without giving it a shell", "summary": "An author publishing under the GitHub handle matousfiser released pvewarden 0.1.x, an early-stage MCP server that lets an AI agent such as Claude Code check pending updates, take snapshots, install, reboot and verify services on Proxmox VE 8 or 9 guests without receiving a shell or root access. The server restricts the agent to a small fixed tool set, binds each guest's SSH key to a forced command accepting only fixed command words (check, status, upgrade-security), limits the Proxmox API token to a single pvewarden pool, and requires a human click in an MCP elicitation dialog for rollbacks, snapshot deletion and updates without a snapshot; it is tested on Proxmox VE 9 with Debian 12/13 and Ubuntu 22.04/24.04/26.04 containers and VMs. The tool matters because it constrains what an agent can do through Proxmox and server-side policy rather than the prompt, and it installs only from official distribution archives, reporting third-party repositories and held packages without installing them.", "body_md": "**Agent-safe patching of Proxmox VE guests over MCP.**\n\npvewarden lets an AI agent keep your Proxmox VMs and containers up to date. It works with Claude Code or any other MCP client. The agent checks pending updates, takes a snapshot, installs, reboots and verifies services. It never gets a shell or root. It can only call a small set of tools, and Proxmox and the server decide what it may do, not the prompt.\n\n[Quick start](#quick-start) · [Why it is safe](#why-it-is-safe-to-hand-to-an-agent) · [Tools](#tools) · [Docs](#documentation)\n\n**Status:** early (0.1.x), in daily use by its author. Tested on Proxmox VE 9 with Debian 12/13\nand Ubuntu 22.04/24.04/26.04 guests, containers and VMs. The server tells your agent when a new\nrelease is out. Feedback and issues are welcome.\n\n*Real calls and results from a home Proxmox server, drawn as a Claude Code session (guest names\nshortened, the agent's replies condensed). The rollback dialog comes from pvewarden, not from the\nagent: only you can confirm it.*\n\nYou need Proxmox VE 8 or 9, Debian or Ubuntu guests on storage that can take snapshots, and an MCP\nclient such as Claude Code ([full requirements](#requirements)). On a Proxmox node, as root:\n\n```\ncurl -fsSLO https://github.com/matousfiser/pvewarden/releases/latest/download/pvewarden-setup\nless pvewarden-setup        # a readable shell script, worth a look before running it as root\nbash pvewarden-setup install\n```\n\nIn about five minutes the wizard creates a small server container, a Proxmox token limited to one\npool, and enrolls the guests you pick. It ends with one command to paste on your computer to connect\nyour agent. Then ask it: *\"What updates are pending?\"*\n\n[What the installer does](#install) · [Step by step](https://github.com/matousfiser/pvewarden/blob/main/docs/install.md)\n\n| Risk | What pvewarden does | \n|---|---|\n| The agent touches guests it should not | It only sees guests in the `pvewarden` pool. Updates need the Proxmox tag`pvewarden-update` and reboots need`pvewarden-reboot` . Only you set the tags. | \n| The agent gets a shell | On guests, the server's SSH key is bound to a forced command that accepts a handful of fixed command words ( `check` ,`status` ,`upgrade-security` , …). No shell, no port forwarding. | \n| A compromised guest reaches others | Every guest has its own SSH key and accepts only that one. Whatever address a guest reports, the server cannot be sent to another guest. | \n| A stolen token unlocks Proxmox | The Proxmox API token has a role limited to the pool. It can see guests, take snapshots, roll back and power-manage them. It cannot create, delete, reconfigure or reach the host. | \n| A bad update breaks a guest | A snapshot comes first, automatically. If the snapshot fails, nothing is installed. | \n| The agent \"solves\" a problem its own way | Rollback, snapshot deletion and updates without a snapshot need *your* click in a dialog that the agent cannot answer (MCP elicitation). | \n| An update pulls in something unexpected | Only the distribution's official archives are used. Third-party repositories (Docker, PHP, …) and held packages are reported, never installed. No release upgrades. | \n| A backup or a dropped connection interrupts an update | Updates wait while Proxmox locks the guest, e.g. during a backup. They run detached on the guest, so a dropped connection does not stop dpkg halfway. | \n| Nobody knows what happened | Every call is written to an audit log with the client's name. Every update keeps its full apt output. | \n\nDetails: [docs/security.md](https://github.com/matousfiser/pvewarden/blob/main/docs/security.md).\n\n- Proxmox VE 8 or 9. You run the installer as root on a node (`sudo -i` first if you log in as a\nnormal user).\n- Guests: Debian 12/13 or Ubuntu 22.04+, as LXC containers or VMs.\n  - VMs need the QEMU guest agent, so pvewarden can find their address and enroll them\n([how to add it](https://github.com/matousfiser/pvewarden/blob/main/docs/install.md#before-you-start) ).\n  - Guest disks must be on storage that supports snapshots (ZFS, LVM-thin, Ceph RBD, qcow2). Updates of guests on plain LVM or raw files are refused.\n- VMs need the QEMU guest agent, so pvewarden can find their address and enroll them\n(\n- An MCP client that supports streamable HTTP. Claude Code works. For the confirmation dialogs the\nclient must support MCP elicitation. Without it, rollback and the other confirmed actions are\nrefused; see [configuration](https://github.com/matousfiser/pvewarden/blob/main/docs/configuration.md#policy) .\n- Network: the agent's computer must reach the pvewarden container on TCP 8765, on its LAN address\nor through a VPN inside the container ([VPN](https://github.com/matousfiser/pvewarden/blob/main/docs/vpn.md) ). The container must reach\nthe guests over SSH.\n\nThe commands are in [Quick start](#quick-start). `pvewarden-setup` checks the checksum of everything it downloads. Checking the script itself is\noptional: compare\n`sha256sum pvewarden-setup` with `SHA256SUMS` on the [release page](https://github.com/matousfiser/pvewarden/releases/latest).\nRelease files also carry a signed build provenance: with the GitHub CLI,\n`gh attestation verify pvewarden-setup -R matousfiser/pvewarden` proves the file was built by this\nrepository's release workflow.\n\nThe wizard asks a few questions and then:\n\n1. creates a pool, a minimal role and an API token limited to that pool,\n2. creates a small Debian container that runs the server (512 MB RAM),\n3. issues the server's HTTPS certificate, signed by your Proxmox CA,\n4. offers to **enroll guests** . Enrolling installs a restricted`pvewarden` user on each guest,\nadds it to the pool and sets the tags you pick.\n5. ends with a summary: the MCP address, a one-time token and a paste-ready command for your computer.\n\nNothing runs on the Proxmox host afterwards. Step by step, plus manual install, upgrade and removal:\n[docs/install.md](https://github.com/matousfiser/pvewarden/blob/main/docs/install.md).\n\nThe install summary prints everything you need. `pvewarden-setup connect` prints it again, without\nthe token. For Claude Code it comes down to:\n\n1. Trust the server's certificate once with the printed command. It downloads the CA, checks its\nfingerprint and sets `NODE_EXTRA_CA_CERTS` .\n2. Add the server:\n\n```\nclaude mcp add --scope user --transport http pvewarden https://<server>:8765/mcp --header \"Authorization: Bearer <token>\"\n```\n\n3. Restart Claude Code and ask: *\"What updates are pending?\"*\n\nOther clients, agents in containers and HTTP behind a VPN: [docs/clients.md](https://github.com/matousfiser/pvewarden/blob/main/docs/clients.md).\n\n| Tool | What it does | Needs | \n|---|---|---|\n| `list_guests` | Guests in the pool, their status, tags and permissions | – | \n| `check_updates` | Pending updates per guest: security or not, official or third-party, reboot needed, automatic updates on, Proxmox locks; also whether a newer pvewarden is out | – | \n| `check_services` | systemd state and failed units | – | \n| `list_snapshots` | Snapshots of a guest; marks the ones pvewarden took | – | \n| `snapshot_guest` | Take a snapshot | `pvewarden-update` | \n| `apply_updates` | Snapshot, install ( `security` or`all` ), compare services before and after | `pvewarden-update` ; your confirmation for`snapshot=false` | \n| `update_result` | Wait for an update that is still running and return its result | `pvewarden-update` | \n| `reboot_guest` | Reboot through Proxmox and wait until the guest answers | `pvewarden-reboot` | \n| `rollback_snapshot` | Roll back to a pvewarden snapshot and start the guest | `pvewarden-update` + your confirmation | \n| `delete_snapshot` | Delete one pvewarden snapshot | `pvewarden-update` + your confirmation | \n| `delete_old_snapshots` | Delete pvewarden snapshots older than N days | `pvewarden-update` + your confirmation | \n\npvewarden only rolls back or deletes snapshots it took itself (`pvewarden_*`).\n\nEnrolling a guest:\n\n- adds a system user `pvewarden` with one SSH key, made for this guest only. The key accepts only\nconnections from the server's address and only the forced command`/usr/local/sbin/pvewarden-gate` .\n- adds `/usr/local/sbin/pvewarden-guest` and`/etc/sudoers.d/pvewarden` , which allow exactly five\ncommands as root.\n- installs `unattended-upgrades` and`sudo` if they are missing. pvewarden uses`unattended-upgrade` to install only from official archives.\n- **automatic updates:** pvewarden does not change your setting unless you choose to. Installing`unattended-upgrades` turns on daily automatic updates on Debian, which then happen without a\npvewarden snapshot. The enroll dialog therefore asks:*keep* (default),*off* or*on* .*off* and*on* are written to`/etc/apt/apt.conf.d/52pvewarden-auto-upgrades` .`check_updates` always\nreports the current state.\n- keeps the last update's log in `/var/lib/pvewarden` .\n\n`pvewarden-enroll --uninstall <vmid>` removes all of it. It leaves `unattended-upgrades` and `sudo`\ninstalled, since other things may use them.\n\n- **Fixed server address.** The server listens on the address its container had at install time.\nGive the container a static IP or a DHCP reservation. After a change, reinstall or edit`listen` in\nthe config and run`pvewarden-setup renew-cert` .\n- **Avoid backup windows.** pvewarden waits while a guest is being backed up, but updates on a node\nthat is busy with a backup job are slow. Don't patch during your backup schedule.\n- **No browser clients.** Requests carrying an`Origin` header are refused (DNS-rebinding protection).\nDesktop and CLI agents are not affected.\n- **Debian and Ubuntu guests only.** Other distributions are refused, not guessed at.\n- **One guest per call.**`apply_updates` handles one guest at a time; the agent loops over them.\n- **Interactive use.** pvewarden has no scheduler. An agent patches when you ask it to.", "url": "https://wpnews.pro/news/show-hn-pvewarden-let-an-ai-agent-patch-proxmox-vms-without-giving-it-a-shell", "canonical_source": "https://github.com/matousfiser/pvewarden", "published_at": "2026-11-10 13:33:23+00:00", "updated_at": "2026-11-10 13:53:53.454821+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-tools", "ai-infrastructure", "developer-tools"], "entities": ["pvewarden", "Proxmox VE", "Claude Code", "MCP", "Debian", "Ubuntu", "matousfiser"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-pvewarden-let-an-ai-agent-patch-proxmox-vms-without-giving-it-a-shell", "markdown": "https://wpnews.pro/news/show-hn-pvewarden-let-an-ai-agent-patch-proxmox-vms-without-giving-it-a-shell.md", "text": "https://wpnews.pro/news/show-hn-pvewarden-let-an-ai-agent-patch-proxmox-vms-without-giving-it-a-shell.txt", "jsonld": "https://wpnews.pro/news/show-hn-pvewarden-let-an-ai-agent-patch-proxmox-vms-without-giving-it-a-shell.jsonld"}}