Skip to content

Linux Troubleshooting

Le Khanh Binh edited this page Jul 4, 2026 · 1 revision

Linux Troubleshooting

Check the daemon logs before anything else - they usually tell you what's wrong. This page is Linux-specific; for macOS, see macOS Troubleshooting instead.


Reading the daemon logs

journalctl -u zentune.service -n 100 --no-pager

For a live stream:

journalctl -u zentune.service -f

Every preset apply is logged with its trigger:

Applied preset 'Eco' (power source changed from AC to battery).
Applied preset 'Gaming' (selected in the app).
Applied preset 'Balance' (restoring saved settings at startup).

For more detail, enable debug logging (toggle Debug in Settings, or edit config directly):

# Assets/config.ini
[Settings]
debug = 1

Then restart the daemon:

sudo systemctl restart zentune.service

Daemon issues

Daemon is not running / TUI says "Not running"

With systemd - try starting it:

sudo systemctl enable --now zentune.service

Check the status:

systemctl status zentune.service

Full logs:

journalctl -u zentune.service -n 50 --no-pager

Without systemd - start the daemon by hand (needs root):

sudo /opt/zentune/venv/bin/python3 /opt/zentune/src/Assets/daemon/daemon.py
Log message Fix
ryzen_smu kernel module is not installed Secure Boot is on and ryzen_smu is missing - install it, see Linux Installation §2
ryzen_smu version X.X.X is too old Update ryzen_smu, same guide
ryzen_smu is installed but not signed for Secure Boot Enroll the signing key, see the Secure Boot section below
ryzen_smu is installed but not loaded Run sudo modprobe ryzen_smu then restart the service
Secure Boot disabled, using PCI direct access backend. Normal startup message, no action needed
Secure Boot is off, so ZenMaster uses PCI direct access, but the PCI config space is not writable. Run as root, and check that kernel lockdown is off
Another daemon instance is already running (lock: /run/zentune_daemon.lock). A previous daemon instance is still running. Kill it: sudo pkill -f daemon.py
Cannot bind IPC socket ipc:///run/zentune.sock: The socket may be stale or held by another process. Run sudo rm /run/zentune.sock then restart the service
Cannot remove stale socket /run/zentune.sock: Permission problem on the socket file. Run sudo rm /run/zentune.sock then restart the service

"Version mismatch" warning on startup

Usually happens after an update where the daemon wasn't restarted. Fix:

sudo systemctl restart zentune.service

Without systemd, kill the daemon process and start it again:

sudo pkill -f daemon.py
sudo /opt/zentune/venv/bin/python3 /opt/zentune/src/Assets/daemon/daemon.py

Daemon starts but exits immediately

Check logs. If you see Cannot bind IPC socket or Cannot remove stale socket:

sudo rm /run/zentune.sock
sudo systemctl restart zentune.service

Python tracebacks mean something is broken in the install. Quickest fix:

curl -fsSL https://raw.githubusercontent.com/HorizonUnix/ZenTune/main/install.sh | bash

Service keeps restarting / flapping

The unit has Restart=on-failure, RestartSec=5. Check logs to see why it's crashing, the fix depends on the error.

To stop the restart loop and see daemon output directly:

sudo systemctl stop zentune.service  # or kill it however your init handles it
sudo /opt/zentune/venv/bin/python3 /opt/zentune/src/Assets/daemon/daemon.py

TUI can't connect after the daemon is running

Check the socket exists:

ls -la /run/zentune.sock

If it's missing, the daemon isn't fully started yet. Wait a few seconds.

If it exists but the TUI still can't connect, check permissions. Should be world-writable (daemon sets 666 on it at startup):

stat /run/zentune.sock

For macOS, see macOS Troubleshooting.


ryzen_smu issues (Linux, Secure Boot only)

Note

ryzen_smu is only needed when Secure Boot is on. With Secure Boot off, the daemon uses PCI direct access and none of this applies. On macOS, the equivalent backend is DirectHW or the kext-free IOPCIBridge path, see macOS Troubleshooting.

ryzen_smu is not installed

Daemon starts but logs ryzen_smu kernel module is not installed and presets don't apply. See Linux Installation §2 for full per-distro steps.

Quick version:

# Install build dependencies first (this example is Debian/Ubuntu)
sudo apt install cmake gcc g++ dkms openssl

# Build and install
git clone https://github.com/amkillam/ryzen_smu
cd ryzen_smu
sudo make dkms-install
sudo modprobe ryzen_smu

ryzen_smu version is too old

Minimum is 0.1.7. Check:

cat /sys/kernel/ryzen_smu_drv/drv_version

To update:

cd ryzen_smu    # your existing clone, or clone it fresh
git pull
sudo make dkms-uninstall   # remove the old version from DKMS
sudo make dkms-install     # install the new version
sudo modprobe -r ryzen_smu
sudo modprobe ryzen_smu

modprobe fails with "Operation not permitted"

Secure Boot is on and the module isn't signed. See the Secure Boot section below.


modprobe fails with "Module ryzen_smu not found"

Module isn't installed for the running kernel. Common causes: kernel updated and DKMS didn't rebuild, headers missing, or installed for a different kernel.

Check DKMS status:

sudo dkms status

ryzen_smu/X.X.X: added but not installed means you need to force a rebuild:

sudo dkms install ryzen_smu/$(sudo dkms status | grep ryzen_smu | cut -d, -f1 | cut -d/ -f2)

Or just reinstall from source:

cd ryzen_smu
sudo make dkms-uninstall
sudo make dkms-install
sudo modprobe ryzen_smu

ryzen_smu loads but /sys/kernel/ryzen_smu_drv/ is missing or empty

sudo modprobe -r ryzen_smu
sudo modprobe ryzen_smu
dmesg | tail -20

Check dmesg for module errors. If the directory is empty after loading, your CPU may not be supported by the installed version of ryzen_smu.


Secure Boot issues (Linux)

Module won't load with Secure Boot enabled

Secure Boot on means the kernel only loads signed modules. Enroll the DKMS signing key:

mokutil --sb-state

Enroll the key:

sudo mokutil --import /var/lib/dkms/mok.pub

Set a one-time password when prompted, then reboot. Watch for the blue MOK Manager, it only stays a few seconds:

  1. Enroll MOK -> Continue -> Yes
  2. Type the one-time password
  3. Reboot

After booting:

sudo modprobe ryzen_smu
lsmod | grep ryzen_smu

MOK Manager screen didn't appear

Either the timeout was too short and you missed it, or your firmware doesn't support MOK enrollment. Try mokutil --import /var/lib/dkms/mok.pub again and reboot. If it still doesn't appear, check BIOS for "Secure Boot Key Management", "MOK Management" or "UEFI Key Enrollment".


Secure Boot is enabled and you can't enroll the key

Some OEM laptops have Secure Boot locked down. Options:

  1. Disable Secure Boot in BIOS/UEFI and reload the module
  2. Use a distro-packaged signed kernel module if one exists
  3. Build and sign with your own key and add it to the UEFI Authorized Signature Database (advanced)

For macOS backend problems (DirectHW, IOPCIBridge, debug=0x144), see macOS Troubleshooting.


Hardware detection issues

ZenTune detects your CPU without dmidecode or any external tool: on Linux it reads /proc/cpuinfo through the zenmaster library. For the macOS equivalent, see macOS Troubleshooting.

Hardware type shows "Unknown"

CPU was detected but has no SMU command table. Could be: CPU is pre-Zen 1, or too new to be added yet.

Try Settings -> Re-detect hardware first.

If still Unknown, check what was actually read:

grep -E "^cpu family|^model" /proc/cpuinfo

If the family/model look right for your CPU, file a bug with that output and your CPU model name.


CPU detected as wrong family or codename

Run Settings -> Re-detect hardware. If the wrong codename persists, it's a bug in detection logic, file a bug with your CPU model and the cpuinfo output from above.

If you just want to pick a different premade preset table without fixing detection, use Settings -> Edit CPU info instead, see Configuration.


Preset issues

Presets apply but the CPU reverts after a few seconds

Something else is resetting the power limits, common culprits are power-profiles-daemon, thermald, tlp, auto-cpufreq. Enable Reapply in Settings with a short interval:

Settings (7) -> Reapply preset periodically on -> Reapply interval = 3


Presets reset after sleep/resume/hibernation

The SMU loses state on suspend. Set a resume preset:

Automations (4) -> Preset on System Resume -> pick a preset

The daemon detects resume by comparing a clock that keeps running through sleep against one that doesn't, so it catches both suspend-to-RAM and hibernation with no dependency on logind. This works the same way on macOS. You'll see Applied preset 'Balance' (woke from suspend after ~28m). in the logs.

If the resume preset never applies on Linux: CLOCK_BOOTTIME isn't available (daemon logs this and disables detection), or resume is restarting the service, in that case enable Apply preset on daemon start in Settings instead.


Automations aren't switching on AC/battery

At least one of Preset on Battery Charge or Preset on Battery Discharge needs to be set. There's no separate on/off switch.

Check the daemon is running:

systemctl is-active zentune.service

Check power source (Linux):

cat /sys/class/power_supply/AC*/online 2>/dev/null || cat /sys/class/power_supply/ACAD*/online 2>/dev/null

1 = AC, 0 = battery. If the file doesn't exist, the kernel isn't reporting AC state and the monitor can't see transitions.

On macOS, check pmset -g batt instead, see Automations.


Applied preset has no effect on performance

Open the Status tab (6) and check for rejected commands (marked [!]). Other possibilities: the CPU is throttling for thermal or VRM reasons, or your CPU family doesn't support a parameter, lines like some-arg -> not supported on HawkPoint in the apply output mean exactly that.


Custom preset shows no sections / editor is mostly empty

The editor only shows sections for parameters the CPU's SMU firmware supports. If almost everything is hidden, the CPU may be mapped to a socket type with limited command support.

Check detected family:

grep -i family /opt/zentune/src/Assets/config.ini

If Unknown or wrong, fix detection first. If correct but sections are still missing, it's a genuine limitation of that CPU's SMU firmware.

The System section (power profile, ASUS modes, CCD affinity) never appears on macOS, that's expected, see Custom Presets.


Config and setup issues

Setup wizard runs every time I start the app

The Info section in config.ini is missing or incomplete, usually after a bad update, manual config editing that removed required keys, or a first run that got interrupted. Let the wizard run to completion and don't skip hardware detection; Info only gets written when detection finishes.


All my settings and custom presets were wiped

If you hit Reset all in Settings, that's intentional. If it happened on its own, the Info section was broken and the wizard reset the config.

Custom presets live in Assets/custom.json. Updates back it up to /opt/zentune/custom.json.bak, restore with:

cp /opt/zentune/custom.json.bak /opt/zentune/src/Assets/custom.json

config.ini is not being saved

Check Assets/ is writable by the user running the TUI:

ls -la /opt/zentune/src/Assets/

The install script chowns /opt/zentune to your user. If you installed manually with sudo, fix it:

sudo chown -R "$USER" /opt/zentune/src

Display and terminal issues

"Terminal too small" message

Needs at least 50x25. Make the window bigger or reduce font size, the UI comes back automatically.


Garbled characters or weird symbols

Needs UTF-8 and a terminal with ANSI/truecolor support. Most modern terminals handle this fine.

Check locale:

echo $LANG

Should be en_US.UTF-8 or similar. If it's C or POSIX:

export LANG=en_US.UTF-8

Colors look wrong or input doesn't work over SSH

Check TERM:

echo $TERM

If it's dumb or empty:

export TERM=xterm-256color

Inside tmux or screen, use tmux-256color so colors render correctly.


App won't start outside a real terminal

Needs an interactive terminal, no piped input, scripts or non-interactive shells. Run it directly in a terminal emulator. In tmux or screen, make sure you're attached to a live session.


Service path issues

Daemon starts but uses the wrong Python or the wrong script path

The service file bakes in absolute paths at install time. If you moved the app, the paths go stale. Launch the TUI once, it detects the mismatch, asks for your password, and rewrites the service file automatically:

zentune

If that doesn't work, regenerate manually:

sudo systemctl stop zentune.service
sudo tee /etc/systemd/system/zentune.service > /dev/null << 'EOF'
[Unit]
Description=ZenTune Power Management Daemon
After=multi-user.target

[Service]
Type=simple
ExecStart=/opt/zentune/venv/bin/python3 /opt/zentune/src/Assets/daemon/daemon.py
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl start zentune.service

On macOS, the equivalent is the com.horizonunix.zentune launchd job at /Library/LaunchDaemons/com.horizonunix.zentune.plist; the same "launch the TUI once" fix applies there too.


Update issues

Update fails with a permission error

The updater uses sudo mv internally to back up and swap the install directory. If sudo isn't available or the prompt fails, it aborts without touching your working install. Re-run the install script to recover:

curl -fsSL https://raw.githubusercontent.com/HorizonUnix/ZenTune/main/install.sh | bash

Update completed but the app is broken / won't start

Config and presets are backed up to /opt/zentune/config.ini.bak and custom.json.bak (the updater restores them on success). If the new version is broken, re-run the installer:

curl -fsSL https://raw.githubusercontent.com/HorizonUnix/ZenTune/main/install.sh | bash

If an update died halfway, the old app dir may be at /opt/zentune/src.bak:

sudo rm -rf /opt/zentune/src
sudo mv /opt/zentune/src.bak /opt/zentune/src
sudo systemctl restart zentune.service

Getting more help

Collect this before opening an issue (on macOS, see macOS Troubleshooting's equivalent section instead):

# OS and kernel
uname -a
cat /etc/os-release

# Python version
python3 --version

# ryzen_smu version (Secure Boot only)
cat /sys/kernel/ryzen_smu_drv/drv_version 2>/dev/null || echo "not loaded"

# CPU info
grep -E "^cpu family|^model|^model name" /proc/cpuinfo

# Daemon logs
journalctl -u zentune.service -n 50 --no-pager

# App config
cat /opt/zentune/src/Assets/config.ini

Open an issue on GitHub with this output and a description of what you were doing.

Clone this wiki locally