Intro
Part 12 ended with pve-01 back from a POST hang after a CMOS clear. That was not the end of it. Over the next ten hours the host reset more than 30 more times. First the resets came during busy moments, later every few minutes. Finally the host stayed dark. Each time, the journal stopped mid-line.
This post is the whole hunt in one place. It covers what the resets looked like, what I ruled out and how, and what fixed it.
TL;DR: A host whose journal stops mid-line with no shutdown sequence lost power. I ruled out disks, CMOS, kernel, thermals and VM load. I swapped the power adapters between pve-01 and pve-02 (same model), and the resets stopped immediately. Host up/down and reboot alerts now run in Grafana Cloud, outside the cluster. The reason: part of the in-cluster monitoring lives on the host that fails.
The Situation
- Three Proxmox VE 9 hosts: pve-01 and pve-02 are Lenovo ThinkCentre M715q Tiny (Ryzen, external power adapter), pve-03 is an old laptop
- pve-01 runs two k0s workers (VM 101, 102) and a controller (VM 200)
- One worker on pve-01 holds node-local data (
/mnt/data) for CloudNativePG and the monitoring stack - Part 12 covered the first day: a reset loop in the morning of 2026-10-13, then a POST hang until about 21:00. Clearing the CMOS fixed the hang
Issue 1: Resets with no trace
Symptom
From pve-02, the pattern was always the same. Corosync reports that pve-01 left, then that it joined again a minute later.
Oct 14 01:26:33 pve-02 corosync[1223]: [TOTEM ] A new membership (2.4f0) was formed. Members left: 1
Oct 14 01:27:10 pve-02 corosync[1223]: [TOTEM ] A new membership (1.4f5) was formed. Members joined: 1
On pve-01, journalctl --list-boots showed the scale of it. Every boot that
day ended without a shutdown. The last lines were ordinary noise, in this case
the Tailscale netcheck:
Oct 14 01:25:44 pve-01 tailscaled[912]: portmapper: PMP probe failed due result code: {OpCode:128 ResultCode:NetworkFailure ...}
Oct 14 01:25:44 pve-01 tailscaled[912]: netcheck: DetectCaptivePortal(found=false)
-- nothing more; the next entry is the kernel of the next boot --
The evening of 2026-10-13 was the worst of it:
- I sent
poweroffonce. After that, the host came back on and went off again about every 5 seconds. - With the SSD attached, it booted into Proxmox and ran a filesystem check. Then it turned off again.
- On about the fifth try it stayed up, with two beeps and POST error 0162 (“Setup data integrity check failure”).
- On boots where the SSD was out, VMs stored on the SSD failed to start with
no such logical volume ssd/ssd. I removed the SSD to reach the CMOS battery.
The 0162 and the missing volume were side effects. The M715q reports 0162 on the first boot after a CMOS clear. The volume was missing because the disk was physically out.
What it was not
| Suspect | Check | Result |
|---|---|---|
| Disks | SMART on the NVMe and SSD, and a disk swap between pve-01 and pve-02 (Part 12) | Healthy, and the fault stayed with pve-01’s chassis |
| Kernel panic or hang | Last journal lines of each boot | No panic, no hung-task warnings. A panic leaves a trace. This did not |
| Hardware errors | journalctl -k for mce, Machine check, Hardware Error | None |
| Overheating | sensors and thermal messages | Normal temperatures, no throttling |
| Firmware reset cause | The AMD previous reset reason line at boot | Nothing useful recorded |
| Proxmox HA fencing | ha-manager status | No HA resources, watchdog idle |
| Heavy VM load | Stopped every VM outside the cluster at 00:16, removed Coroot and ClickHouse | Resets continued (next section) |
A log that ends in the middle of normal output, with no panic and no shutdown, means that the power went away. The question was why.
Dead end: it is the load
The resets clustered around busy moments: early boot, all VMs starting at once, and Helm rollouts. So I reduced the load. At 00:16 I stopped every VM that is not part of the cluster and disabled their autostart. In the cluster, I replaced Coroot with a lighter OpenTelemetry stack (Part 14). Coroot ran ClickHouse and an eBPF agent on every node.
The longest stretch after that was 73 minutes. Then the resets came faster, even when the host was close to idle:
| Boot | Last log | Up |
|---|---|---|
| 00:13:21 | 01:25:44 | 72 min |
| 01:26:53 | 02:39:50 | 73 min |
| 02:40:48 | 02:48:42 | 8 min |
| 02:50:15 | 02:55:46 | 5 min |
| 02:56:29 | 03:01:25 | 5 min |
| 03:02:27 | 03:04:27 | 2 min |
| 03:06:26 to 03:08:19 | three boots | seconds each |
| 03:41:02 | 03:42:07 | 1 min |
| 03:43:49 | 03:44:50 | 1 min |
| 03:45:54 to 04:25:16 | five boots | seconds each |
| after 04:25 | dark until 06:49 |
Load possibly made it fail sooner, but it was not the cause. Only the k0s VMs were running for every reset on 2026-10-14. Uptimes got shorter while the load got lower. That points at something physical that gets worse.
Cause
Nothing in software can explain a host that loses power while idle. Two suspects were left on pve-01: the power circuitry on the board, or the power input (the external adapter and its barrel plug).
Fix
The two M715q hosts use the same adapter, so the test was cheap. I swapped the adapters between pve-01 and pve-02 to see whether the fault moves.
At 06:49, pve-01 booted on the adapter from pve-02, and pve-02 booted on the one from pve-01. Both stayed up after that, with all k0s VMs running on both hosts. pve-01 did not reset once.
So far the fault did not move to pve-02. So I cannot yet say which of two things was the problem. The old adapter is weak, or the plug contact was bad and re-seating it fixed it. Either way it was the power input, not the board. If pve-02 starts to reset on its new adapter, the adapter is bad, and I replace it. The alerts below will tell me.
Issue 2: Finding out from the cluster is too late
Symptom
I noticed every reset above because I watched corosync from pve-02 by hand. The
in-cluster monitoring (Part 14) cannot help much. Grafana, VictoriaMetrics and
VictoriaLogs keep their data on a disk on k0s-pve-01-worker-1. When pve-01
loses power, the monitoring goes down with it.
Fix
The Proxmox hosts already ship metrics to Grafana Cloud through Grafana Alloy. Grafana Cloud is outside the cluster and outside the house, so the alerts go there. I made two rules in one rule group. A JSON file manages the group through the provisioning API:
| Rule | Query | Catches |
|---|---|---|
| PVE host down | max by (instance) (max_over_time(up{job="integrations/node_exporter"}[1d])) unless max by (instance) (up{job="integrations/node_exporter"}) | A host that reported in the last day and stopped (about 6 minutes) |
| PVE host rebooted | changes(node_boot_time_seconds{job="integrations/node_exporter"}[15m]) > 0 | A power loss that comes back on its own within a minute, which “down” misses |
The “down” rule does not use up == 0. When a host loses power, Alloy stops
sending, so up does not become 0. The series disappears instead. A comparison
against the last day finds hosts that were there and are not there anymore.
umask 077; printf 'Authorization: Bearer %s\n' "$(pbpaste)" > /tmp/gc.hdr
curl -s -H @/tmp/gc.hdr -H 'Content-Type: application/json' -H 'X-Disable-Provenance: true' \
-X PUT https://<stack>.grafana.net/api/v1/provisioning/folder/<folder-uid>/rule-groups/pve-hosts \
--data-binary @alerts/pve-hosts.json
rm /tmp/gc.hdr
Each rule sends email through a contact point that the rule names itself
(notification_settings.receiver). So the default notification policy of the
stack stays untouched.
One catch: a service account with No basic role gets 403 on everything. With Editor, it could create a folder but then could not read it. So I put the rules into an existing folder instead.
Lessons
- A journal that stops mid-line means power. A panic, a hang or a shutdown leaves something behind. Nothing at all means that the power went away.
- Uptimes that keep shrinking point at hardware that gets worse. Software faults usually repeat at the same point. These came faster each time, even with less load.
- Lower load can hide a power fault. It also kept me on the “too much load” theory for longer than it deserved.
- Identical hardware gives you free swap tests. First disks (Part 12), then power adapters. Each swap ruled something in or out in minutes.
- Some POST errors are side effects. Error 0162 is normal after a CMOS clear. The missing LVM volume was a disk that I pulled myself.
- Alert from outside the thing you watch. A monitoring stack with data on the failing host cannot report that the host fails. The host alerts run in Grafana Cloud.
Series
This post is part of Homelab Rebuild:
- Part 1: Upgrading Proxmox VE 8 to 9
- Part 2: Starting Over When the IaC Is Broken
- Part 3: When Tailscale Breaks Your Cilium Gateway
- Part 4: Living on the Tailnet
- Part 5: Secrets Without Secrets in Git
- Part 6: Certificates, DNS and a Private CA
- Part 7: Self-Hosted CI and Getting Back to IaC
- Part 8: Stateful Workloads on Unequal Hardware
- Part 9: Going Public Safely with Cloudflare Tunnel
- Part 10: When the Hypervisor Went Quiet
- Part 11: Hardening the Cluster in Five Layers
- Part 12: Observability with Coroot, and Losing pve-01
- Part 13: The Host That Kept Losing Power (this post)
- Part 14: Observability, Take Two with OpenTelemetry
- Part 15: Requests and Limits for Everything
- Part 16: Handing the Cluster to FluxCD
- Part 17: Making the Guardrails Earn Their Keep
- Part 18: When the API Server Outgrew Its VM
- Part 19: Logging In to OpenBao with Cloudflare Access and Google
- Part 20: Headlamp SSO, or Teaching kube-apiserver to Trust Cloudflare Access
- Part 21: pve-02 Loses Power, and Pi-hole Has Nowhere to Go
- Part 22: Turning Four Days of Fixes into AI Runbooks
- Part 23: microVM Sandboxes on Proxmox
- Part 24: Pi-hole Without a Home Host
- Part 25: It Was the Router
- Part 26: TLS on the Front, Plaintext Behind It
- Part 27: One Bad Power Adapter, Two Different Deaths
- Part 28: Observability, Take Three: Making It Worth Looking At
- Part 29: One Meter for Every Model, LiteLLM on Workers AI
- Part 30: Proxmox Joins the SSO, and a Plan Token Loses Admin
- Part 31: First Backups, Postgres, OpenBao and etcd to R2
- Part 32: Alerts That Reach Me, Even When the Lab Is Dead
- Part 33: The Firewall Held, the Tailnet Did Not
- Part 34: From Watching to Blocking, and a Record of Who Did What
- Part 35: Wazuh Without the 8 GB, Endpoint Security for One Mac and Three Hosts
- Part 36: The Fans Were Loud, the CPUs Were Idle
- Part 37: A Power Trip, a Search Domain and a Wildcard
- Part 38: An Autonomous AI Pentester in a Sealed Box
- Part 39: Wasm Pods on k0s, and the Label That Kept Them Packed