Estimated reading time: 9 minutes
Table of contents
- The Hypothesis: Power States and Consumer Drives Causing Random Reboots
- Fixing the Random Reboots: Summary of Changes
- OS-Level Mitigations: Kernel Flags
- Sensors: Preparation & Monitoring
- Critical BIOS Settings
- Optional: CPU Governor Optimization
- The Result: Keeping it Cool & Stable
- Final Thoughts: From Random Reboot Loop to Rock Solid
If you run Proxmox (or any Linux distribution) on a Mini PC – like the HP EliteDesk or ProDesk mini, Lenovo Tiny, or Dell Micro – especially with consumer grade – NVMe drives in ZFS or BTRFS RAID, you have likely experienced random reboots or system hangs. It’s a frustrating experience common to these small form-factor nodes.
For me, using an HP EliteDesk 800 G5 Mini (that replaced my Lenovo ThinkCentre M93p Tiny, which I put to use as a retro console), the symptoms were clear but baffling. My server rebooted randomly at idle or low load. NVMe drives would drop off the bus, showing IO errors in dmesg. Even worse, BTRFS scrub errors appeared after these unclean shutdowns. The kernel logs were often unhelpful, showing a generic “NVMe controller reset” or simply nothing at all because the crash happened too fast to write to disk.
This post documents my journey to diagnose and fix these specific hardware quirks. While I focus on the HP EliteDesk, the root causes – aggressive power saving and thermal throttling – applied to Mini PCs in a homelab environment.

The Hypothesis: Power States and Consumer Drives Causing Random Reboots
After some research, I started to see a pattern. This looked like a classic issue with NVMe power states (ASPM) or C-states causing kernel instability. This is apparently very common on these Mini PCs when running Linux or Proxmox, specifically when paired with consumer-grade NVMe drives rather than the Enterprise drives they were designed for.
My system was running mixed OEM drives – an SK Hynix PC601 and a Kingston OM8 series (I like to mix them, so that they do not fail simultaneously, when using the same brand from the same batch). These are standard client-grade drives designed for PCs and laptops, not 24/7 servers. My theory was that these drives were not playing nicely with Linux’s aggressive power-saving features (APST/ASPM) enabled by the HP BIOS. If the drive attempts to enter a low-power state, fails to wake up fast enough, and the controller resets, it would cause issues. Since I am running BTRFS RAID 1, if one drive drops offline momentarily due to this transition error, it can panic the kernel or hang the system, forcing a random reboot.

I also suspected the Intel i915 graphics driver. On headless systems, it can sometimes cause system hangs when trying to enter deep sleep states, also causing random reboots.
Based on this, I developed a comprehensive fix involving kernel flags, thermal monitoring, and deep BIOS configuration.
A Note on Permissions: For the purpose of documenting this process, I wrote down all commands that should be done as root. However, I used
sudofor everything in my actual workflow as I’m not a fan of using the root user directly. Please adapt the commands to your preferred method.
Fixing the Random Reboots: Summary of Changes
If you don’t want to read and think “Just tell me what you did so I can move on with my life!”:
Here is a TL;DR of every(set)ting I changed to stabilize the system.
| Setting | Old Value | New Value | Reason |
|---|---|---|---|
| GRUB: nvme_core.default_ps_max_latency_us | (Default) | latency=0 | Disables APST so drives don’t sleep. |
| GRUB: pcie_aspm | (Default) | off | Disables PCIe power management at OS level. |
| BIOS: Runtime PM | Enable | Disable | Prevents hardware-level device sleep. |
| BIOS: PCIe PM | Enable | Disable | Keeps NVMe link active (L0). |
| BIOS: Extended Idle | Enable | Disable | Prevents CPU C-State hangs. |
| BIOS: Fan Speed | 0% | 30% | Prevents NVMe thermal throttling. |
| CPU Governor | performance | powersave | Reduces idle power and ambient heat. |
For those interested to go in to the details… continue reading…
OS-Level Mitigations: Kernel Flags
Before touching the BIOS, I told the Linux kernel to ignore these aggressive power-saving states. This acts as a safety net.
First, I edited the default GRUB configuration file.
nano /etc/default/grub
I found the line starting with GRUB_CMDLINE_LINUX_DEFAULT and appended specific parameters inside the quotes.
GRUB_CMDLINE_LINUX_DEFAULT="quiet nvme_core.default_ps_max_latency_us=0 pcie_aspm=off i915.enable_dc=0"
Here is what these flags do:
nvme_core.default_ps_max_latency_us=0: Disables APST (Autonomous Power State Transition) for NVMe drives.pcie_aspm=off: Disables Active State Power Management for the PCIe bus.i915.enable_dc=0: (Optional) Prevents the Intel GPU from entering deep sleep, which can hang headless systems.
Finally, I updated GRUB and rebooted.
update-grub
reboot
Sensors: Preparation & Monitoring
To verify that my changes worked, especially regarding fan speeds, I needed to read the hardware sensors. I installed the monitoring tools and ran the detection script.
apt update
apt install lm-sensors
sensors-detect
Important: I answered YES to all questions (scanning for I2C, SMBus, ISA adapters, etc.) to ensure the Super I/O chip was detected.
Then, I checked the baseline temperatures.
- NVMe Drives: At roughly 35°C–40°C, we are about 30 degrees below the 70°C+ danger zone where throttling occurs. The controller temp (Sensor 2) is also very healthy at 38.9°C.
- CPU: Running at ~28°C–31°C is barely above room temperature, indicating unimpeded airflow through the chassis.
- Chipset: The PCH is at 51.0°C, which is normal for these Mini PCs. Anything under 60°C is great.
Thermally, the system is now rock solid and there are no more random reboots.
Critical BIOS Settings
Before diving into the complex tools needed to change these settings from Linux, I established exactly what I needed to achieve. These HP EliteDesk BIOS settings are tuned for Windows Enterprise efficiency, not for a Linux Hypervisor running 24/7.
Here are the critical changes required for stability:
- Runtime Power Management: Disable (Critical for stability).
- Extended Idle Power States (C-States): Disable (Stops random reboots).
- PCI Express Power Management: Disable (Helps with NVMe dropouts).
- Fast Boot: Disable (Ensures hardware initializes fully).
- Fan Speed: Increase minimum speed (e.g., to 30%) to prevent NVMe overheating.
Why Not Just Enter the BIOS?
Now, you might be wondering: “Why go through all this trouble with kernel modules and proprietary HP tools? Why not just plug in a monitor and keyboard, hit F10, and change the settings in the BIOS?”
Technically, I could have. But my servers are in the basement, where there is very little room and definitely no comfortable chair or space to setup a monitor. I always prefer to do everything over SSH from the comfort of my desk unless I absolutely have no other choice.
I actually played around with a TinyPilot KVM over IP solution for exactly these scenarios. It worked great, but I found myself only needing that kind of direct access maybe once a year. Eventually, I repurposed the Raspberry Pi 4 for another project, leaving me committed to solving this the remote-admin way.
The Initial Attempt: hp_bioscfg
Proxmox (Kernel 6.x) comes with a built-in module called hp_bioscfg that exposes BIOS settings via the sysfs interface. Ideally, this is the “Modern Way” to change settings without external tools.
I tried this first:
modprobe hp_bioscfg
cd /sys/class/firmware-attributes/hp-bioscfg/attributes
echo "Disable" > 'Runtime Power Management/current_value'
The Failure: It failed immediately with bash: echo: write error: Invalid argument.
Even when using echo -n, the driver rejected the write operation. This is a known issue on the EliteDesk 800 G5. The motherboard’s WMI interface does not play nicely with the generic Linux kernel driver. It allowed me to read values perfectly, but writing was impossible.
This failure forced me to pivot to the “Nuclear Option”: HP’s legacy, proprietary Linux tools (hp-repsetup), which bypass the kernel abstraction and talk directly to the hardware.
The “Hard” Way: HP Linux Utilities
Since the native kernel driver failed, I had to compile the proprietary driver. I started by installing the necessary build tools and kernel headers.
apt update
apt install build-essential pve-headers-$(uname -r)
Then, I used the “HP Flash and Replicated Setup Utilities for Linux” (SoftPaq sp157762).
cd ~
mkdir hp-tools
cd hp-tools
# Download the specific SoftPaq (Version 3.25)
wget https://ftp.hp.com/pub/softpaq/sp157501-158000/sp157762.tgz
# Extract the main package
tar -xvf sp157762.tgz
Next, I compiled the hpuefi driver, which acts as a bridge to the BIOS.
# Extract the driver source
tar -xvf non-rpms/hpuefi-mod-3.06.tgz
# Enter the source directory
cd hpuefi-mod-3.06
# Compile and Install
make
make install
modprobe hpuefi
If make runs without errors, the driver is loaded. Then, I prepared the BIOS tool itself.
cd ../non-rpms
tar -xvf hp-flash-3.25_x86_64.tgz
# Run the installation script to place binaries in /opt/hp/hp-flash
./install.sh
# Navigate to the installed directory to run the tool
cd /opt/hp/hp-flash/bin
The Configuration & The “UTF-16 Trap”
Here, I hit a snag. I initially tried to use sed and grep to edit the BIOS config file directly, but it failed silently or returned “binary file matches.”
The Reason: HP encodes these files in UTF-16LE (2 bytes per character). Standard Linux tools expect UTF-8, so they saw the file as “binary garbage.”
The Solution: I created a workflow that converts the config to UTF-8, patches it, converts it back, and flashes it.
Spoiler: There was no UTF-16LE Unicode UCS-2 trap…
After doing this and writing this, I saw I missed something when running ./hp-repsetup -h:
-a (ASCII Mode) - Create file in ASCII format (default: Unicode UCS-2)*
*Note: ASCII file cannot be imported with other tools
So it could have been as simple as the below (this is not verified/tested by me), I’m leaving it here so someone else could try this somewhat simpler approach:
cd /opt/hp/hp-flash/bin
# Export current BIOS settings to a file
./hp-repsetup -g config.txt -a
# Disable Runtime Power Management (Stops random sleep crashes)
sed -i '/Runtime Power Management/{n;s/Disable/*Disable/;n;s/\*Enable/Enable/;}' config.txt
# Disable PCI Express Power Management (Stops NVMe dropouts)
sed -i '/PCI Express Power Management/{n;s/Disable/*Disable/;n;s/\*Enable/Enable/;}' config.txt
# Disable Extended Idle Power States (Stops CPU C-State crashes)
sed -i '/Extended Idle Power States/{n;s/Disable/*Disable/;n;s/\*Enable/Enable/;}' config.txt
# Disable Fast Boot (Ensures hardware initializes fully)
sed -i '/Fast Boot/{n;s/Disable/*Disable/;n;s/\*Enable/Enable/;}' config.txt
# Set Fan Speed to 30% (Fixes NVMe overheating)
sed -i '/Increase Idle Fan Speed(%)/{n;s/[0-9]\+/30/;}' config.txt
# Flash the new BIOS settings
./hp-repsetup -s config_final.txt -a
UCS-2 vs. UTF-16LE
Technically, UTF-16LE (Little Endian) and UCS-2 are almost identical for the majority of characters, but there’s a key structural difference in how they handle “rare” characters. Why did UTF-16LE work if the tool wants UCS-2? Because the text in the BIOS config file consists entirely of standard alphanumeric characters (English letters, numbers, punctuation). Most things are 2 bytes, but UTF-16LE can use 4 bytes if it really needs to.
You can copy and paste these blocks into your terminal inside the /opt/hp/hp-flash/bin folder:
1. Export and Convert the Config
First, I dumped the current BIOS settings and converted them into a Linux-readable format.
# Export current BIOS settings to a file
./hp-repsetup -g config.txt
# Convert from UTF-16LE (BIOS format) to UTF-8 (Linux format)
iconv -f UTF-16LE -t UTF-8 config.txt -o config_utf8.txt
2. Patch the Settings
With a clean text file, I used sed to apply the critical fixes. I disabled the power management features that were causing instability and bumped the minimum fan speed to prevent thermal throttling.
# Disable Runtime Power Management (Stops random sleep crashes)
sed -i '/Runtime Power Management/{n;s/Disable/*Disable/;n;s/\*Enable/Enable/;}' config_utf8.txt
# Disable PCI Express Power Management (Stops NVMe dropouts)
sed -i '/PCI Express Power Management/{n;s/Disable/*Disable/;n;s/\*Enable/Enable/;}' config_utf8.txt
# Disable Extended Idle Power States (Stops CPU C-State crashes)
sed -i '/Extended Idle Power States/{n;s/Disable/*Disable/;n;s/\*Enable/Enable/;}' config_utf8.txt
# Disable Fast Boot (Ensures hardware initializes fully)
sed -i '/Fast Boot/{n;s/Disable/*Disable/;n;s/\*Enable/Enable/;}' config_utf8.txt
# Set Fan Speed to 30% (Fixes NVMe overheating)
sed -i '/Increase Idle Fan Speed(%)/{n;s/[0-9]\+/30/;}' config_utf8.txt
3. Verify and Flash
Before applying anything, I verified that my changes were actually written to the file. Then, I converted it back to HP’s format…
# Verify the changes visually
grep -a -A 2 -E "Runtime Power|PCI Express|Extended Idle|Fast Boot|Fan Speed" config_utf8.txt
# Convert back to UTF-16LE
iconv -f UTF-8 -t UTF-16LE config_utf8.txt -o config_final.txt
…and flashed it.
# Flash the new settings
./hp-repsetup -s config_final.txt
Validation & Reboot
After running the script, I saw a “Success” message. I rebooted the system to apply the changes.
reboot
Upon restart, I verified the stability:
- Sound: The fan was slightly audible (a constant hum), which is a good sign.
- Temperature: I ran
sensorsagain (as shown in Step 2). My NVMe temperatures now stayed safely under 55°C-60°C. - Logs: I checked
journalctl -fand confirmed that the “PCIe Bus Error” and “NVMe controller reset” messages were gone.
Post-Fix Validation Results: I ran a full BTRFS scrub on the root filesystem (RAID 1 NVMe) to stress-test the drives and thermal solution.
Scrub started: Thu Dec 30 12:08:12 2025
Status: finished
Duration: 0:01:58
Total to scrub: 180.92GiB
Rate: 1.53GiB/s
Error summary: no errors found
Even under this intense I/O load, the thermals remained exceptionally safe. The NVMe drives peaked at ~60°C, well below the danger zone.
Optional: CPU Governor Optimization
To further reduce power consumption and temperatures without compromising stability, I set the CPU scaling governor to “powersave”. This tells the CPU to run at the lowest frequency when idle.
I opened my crontab:
crontab -e
And added this reboot job, which waits 60 seconds after boot before applying the governor:
@reboot (sleep 60 && echo "powersave" | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor)
The Result: Keeping it Cool & Stable
Here is what my system looks like after applying all the fixes – notice the NVMe drives sitting comfortably around 35-40°C.
hp-isa-0000
Adapter: ISA adapter
pwm1: N/A
coretemp-isa-0000
Adapter: ISA adapter
Package id 0: +28.0°C (high = +82.0°C, crit = +100.0°C)
Core 0: +28.0°C (high = +82.0°C, crit = +100.0°C)
...
Core 5: +25.0°C (high = +82.0°C, crit = +100.0°C)
nvme-pci-0100
Adapter: PCI adapter
Composite: +40.9°C (low = -0.1°C, high = +82.8°C)
(crit = +83.8°C)
Sensor 1: +33.9°C (low = -273.1°C, high = +65261.8°C)
Sensor 2: +38.9°C (low = -273.1°C, high = +65261.8°C)
acpitz-acpi-0
Adapter: ACPI interface
temp1: +30.0°C
pch_cannonlake-virtual-0
Adapter: Virtual device
temp1: +50.0°C
ucsi_source_psy_USBC000:001-isa-0000
Adapter: ISA adapter
in0: 0.00 V (min = +0.00 V, max = +0.00 V)
curr1: 0.00 A (max = +0.10 A)
nvme-pci-0200
Adapter: PCI adapter
Composite: +35.9°C (low = -20.1°C, high = +84.8°C)
(crit = +89.8°C)
This output is excellent and also confirms that increasing the fan speed to 30% is doing its job perfectly.
Final Thoughts: From Random Reboot Loop to Rock Solid
Before this fix, my HP EliteDesk 800 G5 was a nightmare to run. It would reboot seemingly at random – sometimes every hour, sometimes every 15 minutes, multiple times a day. It made the system unusable for any serious work – like hosting this website.
Since applying these changes, the transformation has been night and day. The server has been running rock-solid for days now without a single reboot or NVMe dropout. If you are struggling with similar instability on your Mini PC homelab, don’t give up on the hardware – it just needs a little bit of convincing to play nice with Linux.
Buy me a coffee 🙂
If you found this post helpful, informative, or if it saved or made you some money, consider buying me a coffee. Your support means a lot and motivates me to keep writing.
You can do so via bunq.me (bunq, iDeal, Bankcontact and Credit- or Debit cards) or PayPal (PayPal and Credit- or Debit cards). Thank you!
Disclaimer
The blog posts, guides, and scripts provided on this website are for informational and educational purposes only. They are provided “as is” and without any warranty of any kind, either express or implied, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement.
By using the information or scripts from this blog, you agree that I am not liable for any direct, indirect, incidental, consequential, or any other damages or losses arising from the use of or inability to use the information, scripts, or instructions contained herein. You assume full responsibility for any and all risks associated with the use of this content.
The blog posts, guides, and pages may contain referral/affiliate links. If you make a purchase through these links, I may receive a commission at no additional cost to you.