I've been running my homelab on uptime kuma, a dashboard I refresh manually like some kind of caveman. That stops now. I deployed Pulse, an open-source, self-hosted monitoring workspace for Proxmox (plus Docker, Kubernetes, TrueNAS and vSphere if you're into that), on the little Alpine box I run in Oracle Cloud's free-tier Ampere A1 instance. It sits there, watches my Proxmox cluster, and now — because I'm apparently incapable of leaving well enough alone — it also runs an AI "Patrol" that pokes around my infrastructure on a schedule and tells me when something's quietly on fire.
This post is half tutorial, half "future me, this is how you set it up again after you inevitably nuke the container." Three parts: deploying Pulse on Docker, pointing it at Proxmox with a properly scoped API token, and switching on Patrol using OpenRouter so I'm not locked into a single model provider.
1. Deploying Pulse on Docker (Alpine + dockhand)
My OCI box is Alpine Linux, managed through dockhand for container lifecycle, so this is
just a normal docker run — nothing Alpine-specific to worry about, Pulse ships as a regular
multi-arch image and my instance is aarch64/ARM, which it happily supports.
The official one-liner looks like this:
docker run -d \
--name pulse \
-p 7655:7655 \
-v pulse_data:/data \
-e PULSE_DEPLOYMENT_METHOD=docker_run \
--restart unless-stopped \
rcourtman/pulse:latest
A couple of notes from actually doing this rather than just copy-pasting it blindly:
-
Pin an actual version tag (
rcourtman/pulse:vX.Y.Z) instead of:latestonce you're happy with a release. Makes rollbacks and "what changed" debugging way less annoying. -
The
pulse_datavolume is where your config, tokens and history live. Don't skip it, don't point it at/tmp, you will regret it. -
The Pulse server container does not need Docker socket access. If you also want it monitoring
your Docker host itself, that's a separate lightweight "unified agent" you install on the host — the
server container stays untouched and doesn't need
/var/run/docker.sockmounted in. - In dockhand I just added it as a standard compose-style service pointing at the same image/ports/volume — no surprises, it behaves like any other container.
Pulse is secure by default, so on first boot it doesn't just hand you an open dashboard. You grab a bootstrap token from inside the container:
docker exec pulse cat /data/.bootstrap_token
Then open http://<your-oci-instance-ip>:7655, paste the token in, and run through the
Quick Security Setup wizard — set an admin username/password (or let it generate one), and it'll spit out an
API token for automation. Copy that somewhere safe before you close the tab, because it won't show it to you
again.
If your OCI security list / iptables situation is anything like mine was, remember to actually open
7655/tcp on the instance's ingress rules and whatever local firewall Alpine is running,
or you'll be staring at a spinner wondering why the "quick" setup isn't quick at all. Another approach is to setup a cloudflare tunnel or similar to avoid exposing the port to the public internet, which is what I ended up doing.
2. Connecting Pulse to Proxmox via API Token
Pulse can auto-discover nodes on your network, but I prefer to do this by hand so I know exactly what permissions I'm handing out. The golden rule here: don't just slap the built-in PVEAuditor role on a token and call it a day — it can't be modified, and Pulse actually wants a couple of extra privileges depending on your Proxmox version. So we build a dedicated role.
On the Proxmox host, create a custom role — call it something obvious like PulseMonitor:
- Datacenter → Permissions → Roles → Create.
-
Name it
PulseMonitorand add the privileges Pulse needs for read-only monitoring: the standard audit set, plusVM.GuestAgent.Auditif you're on PVE 9, or the legacyVM.Monitorif you're still on PVE 8. If PVE offersSys.Auditseparately, add that too.
Now create a user and token dedicated to Pulse, rather than reusing your root account like an animal:
pveum user add pulse-monitor@pve
pveum aclmod / -user pulse-monitor@pve -role PulseMonitor
pveum user token add pulse-monitor@pve pulse-token --privsep 0
That last command hands you a Token ID (something like pulse-monitor@pve!pulse-token) and a
Token Secret. That secret is shown exactly once — copy it now.
Back in the Pulse UI:
- Settings → Nodes (or Infrastructure) → Add Node.
- Pick Proxmox VE, drop in your node's URL (e.g.
https://your-pve-host:8006). - Choose API Token auth, paste in the Token ID and Token Secret.
- Test the connection, save.
Give it a minute and your nodes, VMs, containers and storage should start populating. If VM disk usage shows
as zero, that's not Pulse being broken — the Proxmox API only reports it if the QEMU Guest Agent is installed
and running inside the VM (apt install qemu-guest-agent on Linux guests, enable it under
VM Options too).
If you're also monitoring Proxmox Backup Server, same idea applies there: a dedicated token with theDatastoreAuditpermission on/datastore, not a shared credential.
3. Turning on Patrol with an OpenRouter API key
This is the fun part. Pulse Patrol is a background loop that periodically looks across your whole infrastructure — current state and recent history — and flags the stuff a dashboard won't shout about: a backup job that's been quietly failing for a week, a pool creeping toward full, a container stuck in a restart loop nobody noticed. On the free Community tier this is "bring your own key" — Pulse doesn't ship its own model, you plug in a provider.
I went with OpenRouter instead of committing to a single vendor, since it lets me swap models without touching the Pulse config every time someone ships something new and shiny.
Openrouter allows you to usefreeandpaidmodels from multiple providers (Anthropic, OpenAI, Gemini, etc.) through a single API key. Im using free models and they rotate them every few hours, so I don't have to worry about running out of credits.
- Grab an API key from openrouter.ai (Keys section, top up some credits).
- In Pulse, go to Settings → Pulse Assistant (this is where all the AI/provider config lives, Patrol included).
- Add a provider, set the type to the OpenAI-compatible option, and set the custom base URL to
https://openrouter.ai/api/v1. - Paste in your OpenRouter API key.
- Hit Test — you want a green "connection successful" before moving on.
- Pick your model using OpenRouter's model naming (e.g. an Anthropic, OpenAI, or Gemini model routed through OpenRouter). Pulse lets you set a cheaper model for Patrol's routine sweeps and a beefier one for interactive chat, which is a nice touch for the wallet.
Once a provider's configured and tested, head to the Patrol page to actually switch it on: set the interval (anywhere from every 10 minutes to once a week — I run mine every 6 hours, no need to burn tokens checking a homelab that isn't exactly Black Friday traffic), and pick an autonomy level. Community/BYOK Patrol is watch-only: it investigates and reports, it doesn't touch anything. Higher autonomy levels with governed, approved fixes are a Pulse Pro thing — worth knowing so you're not confused when a setting is greyed out.
That's the whole setup: Docker container on Alpine via dockhand, Proxmox wired in through a least-privilege API token, Patrol running on a schedule with OpenRouter as the brain behind it. Not bad for something that now tells me when my backups quietly stop working instead of me finding out three weeks later.