$5 CPU Activity LED Indicator for your Server made with RP 2040 (Pi Pico)

Because who doesn’t love a little das-blinkenlights??

Pi Pico CPU Meter
Zip-tied to a cable management stick-on, on the front of my server

So this project is incredibly simple. You only need three things:
1. Raspberry Pi Pico (RP2040) — Of course, you could use pretty much any micro controller you want
2. Some LEDs. Mine were from a super cheap set which had a hundred or so? No specs on them, but they’re red.
3. One resistor, for each LED you’re going to install. On this I used 470 ohm resistors, I’m pretty sure.

Pi Pico bottom side
The best part is, you don’t need any kind of custom PCB. I did this just by soldering directly on the Pi Pico board itself. Now, you’ll need to be careful to get decent looking LED spacing… but it is more than possible if you are patient.

Silly-putty holding the LEDs
Silly-putty to the rescue!

You’ll definitely need some way to hold the LEDs in place or you’ll be fighting them the entire time. Blue tac would probably be ideal here. I didn’t have that, but I did have an old egg of silly-putty which worked out better than expected.

Back side of picoThis is what the whole thing looks like fully assembled. Basically, the resistor just gets soldered to the leg of each LED which is NOT on the GPIO. The way I’ve done it here was to tie the ground side of each LED through a resistor, and then they all fold into a backbone, each folded onto the next, down the line, and finally tie over to a ground pad on the pico.

Here is a video of it in action: https://ben.lostgeek.net/files/demo.mov

Basically, you’ll need two pieces of code. One which gets flashed to the RP2040 and handles the actual work of pulling the GPIO lines high/low when we get data from the computer.

How do we get the data to the pico? To keep things as simple as possible, we’re just using the Pico’s USB to uart. This makes the USB device show up in linux as a normal serial port, and makes it dead simple to interface with in software.

This is where the second piece of code we need comes into play. It is a daemon of sorts which runs on the machine of which we’d like to see CPU activity. Basically just a small amount of code to read from /proc, see our individual CPU core usage, do some math… and if it is above a certain threshold then we register that core as active and we tell the pico over serial.

My new server build has a 6 core, 12 thread Ryzen 5500 processor and so naturally I thought… Hey, wouldn’t it be cool if I had a little activity LED for each core? Well then, having one for each thread would be even cooler!

For a really nice, crisp, “activity LED” kind of genuine feel I’ve found that you want things updating pretty fast. My experience has been that a refresh period of about 30ms achieves that effect quite well.

If we try and poll the system too often then our daemon which sends data to the pico will start to use noticeable CPU time… Not very much by any means, but personally I’m happy to have the daemon only chewing up no more than ~ 1 % CPU utilization. With the 30ms update rate, it is only consuming 0.7 % of one thread. In other words, we’re only wasting a quite negligible 0.044 % of the total machine’s compute power to run our little light panel.

And who knows, I’m not a coder… someone could probably make this way more efficient. Let me know, if you have some much better code for this to run on 😉

You can get the code here: https://ben.lostgeek.net/files/blinken

Usual disclaimer Ai was used in the writing of the code for this.

Writing a Better DD Wrapper GUI

Back in September last year, I was working on some kind of a wrapper for dd… Just for my own personal needs, nothing too fancy.

I got a little more ambitious, and was happy enough with the results to share it with anyone interested. Use at your own risk, of course.

What is it? It is a GUI front-end to dd. It is dependant on the GNU version of dd. Written in Python, uses QT toolkit.

GitHub: https://github.com/HarderLemonade/ddwrap/

Screenshot of DDWrap

gputemp, a simple AMD Radeon manual fan control solution

# gpufan -- sets manual fan speed on AMD Radeon GPU. For 5.x / 6.x Linux Kernel users running AMDGPU driver...
# Author: Ben @ LostGeek . NET
# Created 09/20/2025

# 	READ ME! How to use:
# save as /usr/local/bin/gpufan then chmod +x
# running "gpufan" will give temperature & fan rpm. gpufan followed by a number (1-100)
# will manually set speed. "gpufan auto" will restore auto / driver control.

Your feedback is welcome!

https://ben.lostgeek.net/code/gpufan/

Writing a wrapper for DD

I’ve been working on a handy lil’ tool, basically a glorified wrapper script for dd. But I think I worked in some solid concepts:

You just run it, no args needed. (Though you can pass args if you want.)

Automatic target selection: Devices with the prefix /dev/sd* that are not mounted will be considered. I’ve put in a volume limit of 64 GB for safety. If the device is greater than 96 GB, then (imo) it’s probably something else – HDD/SSD – so in that case a manual override is required.

Automatic block size: Chosen based on drive capacity. Tiny drives use a smaller block size, while larger (likely more modern USB 3) drives can use big chunks, like bs=4M. This usually improves performance.

Once I get it all ironed out, I’ll share the code. So far, I find it pretty handy.

btflash in action…

XScreenSaver MATE Script for Fedora

Fedora

Added a script which does all the same things as the Debian MATE XSS script did…

Installs the Full XScreenSaver collection (GL + Extras)
Removes MATE Screensaver
Symlinks XSS commands to replace MATE SS commands
Optional SETUID for Sonar
Ensures MATE SS doesn’t try to reinstall
Locking works via “System” –> “Lock Screen”
Fix for locking via keyboard shortcut

https://ben.lostgeek.net/code/xsmate/

XScreenSaver on MATE Desktop: Fixing Screen-Lock Key Bind

XScreenSaverThis is a follow-up to XScreenSaver Install Script for Debian MATE Desktop

Mate Lock Screen
Mate’s Lock Screen Shortcut — This already worked /w my script as-is.

To get working XScreenSaver lock via mate’s default keybind (MOD+L) simply do the following…

We’ll create a small wrapper script at /usr/local/bin/mate-screensaver-command:

sudo nano /usr/local/bin/mate-screensaver-command

Add the following:

#!/bin/bash
if [[ “$1” == “–lock” ]]; then
xscreensaver-command -lock
else
xscreensaver-command “$@”
fi

Then:

sudo chmod +x /usr/local/bin/mate-screensaver-command

Running XScreenSaver on a laptop? Let’s run cool…

For most people these days, screensavers have died off.

XScreenSaver Settings on Debian 12
XScreenSaver Settings on Debian 12

I still like having them. And while most people have moved on from X.Org on Linux, well… here we are.

The 5300U in my ThinkPad has more than enough GPU power to display some beautiful screensavers. But by default, the system will ramp up into a higher performance state — because normally, that’s exactly what you’d want. Like if you were playing a game, or trying to load some bloated modern website.

But my idle laptop? I don’t want it getting all hot while it’s sitting on my lap or on the bed, just because it’s running a screensaver. So this is my little attempt to fix that — and it’s looking pretty promising.

The idea:

When XScreenSaver runs one of its screen hacks (screensavers), we’ll put the CPU into its lowest available frequency. That way, even when running hardware-accelerated 3D, the system will stay nice and cool.

Fortunately, the author of XScreenSaver — Jamie Zawinski — is a pretty smart dude, and the software already includes a clean little mechanism we can hook into to make this work.

Here’s how I’ve got it set up:

Create a script in your home folder, or wherever you want. xscreensaver_freq_watch.sh

#!/bin/bash

# Save current CPU and GPU max frequencies
CPU_MAX_BEFORE=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq)
GPU_MAX_BEFORE=$(cat /sys/class/drm/card0/gt_max_freq_mhz)

# Watch xscreensaver events
xscreensaver-command -watch | while read -r line
do
case “$line” in
LOCK*)
# Optional: do something on screen lock
;;
UNBLANK*)
echo “Screensaver stopped — restoring frequencies…”
echo $CPU_MAX_BEFORE | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq > /dev/null
echo $GPU_MAX_BEFORE | sudo tee /sys/class/drm/card0/gt_max_freq_mhz > /dev/null
;;
BLANK*)
echo “Screensaver started — limiting frequencies…”
echo 500000 | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq > /dev/null
echo 300 | sudo tee /sys/class/drm/card0/gt_max_freq_mhz > /dev/null
;;
esac
done

Of course, make it exactable with chmod +x. Also, use nopasswd in your /etc/sudoers line for your user.

Now because I’m using MATE / LightDM, I’m going to use a .desktop file. You could do something else, .xinitrc or a systemd service, but this is how I did it.

mkdir -p ~/.config/autostart
nano ~/.config/autostart/screensaver-watch.desktop

And inside that, we have the following

[Desktop Entry]
Type=Application
Exec=/home/ben/screensaver_freq_watch.sh
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
Name=Screensaver Frequency Watcher
Comment=Limits CPU and GPU frequencies while the screensaver is running

So far, it’s looking good! You may need to change this a bit depending on your configuration.

ben.lostgeek.net/code

MatrixTo keep things clean and organized

I’ve put most of the code I’ve shared here all up in one place. Everything has a .txt extension, so it can just be viewed in the browser, copied and pasted. There are some readme files, but they are minimal… and this is just a start; but a start is better than nothing.

A minimalist video player, controlled over ssh

MPV Player

I quite often find that when I’m setting up something that I’m going to use myself, the extra layers are just annoying. Kodi/XBMC is great, but if you don’t care to set it up right it can feel clunky… to me anyway. That said, I do want some comforts in my solution.

No manually typing out long file names!
No cryptic, long commands

I give you btv, a wrapper I wrote for MPV. It is meant to be used over SSH.

 

Log in via SSH, change directory to the file(s) you want to play and type btv, it will list out the available video formats in that dir. Hit the corresponding number, press enter and it will start playing. It does so with nohup, so you can exit the ssh session or whatever — it’ll keep playing. If you run it again, while something is playing, it will pause for you. If you run it while something is open and paused, it resumes.

You can also manually set args with:
–stop
–pause
–resume
–play (filename)
–status

You’ll have to configure the correct audio/video outputs for your own setup. This is mine, on a pi5. If you have no audio, pulse/pipewire is probably the reason. Just stop the service(s).

Source available along with some of my other projects:

https://ben.lostgeek.net/code

DnsMasq Network-Wide Blocking Part II. Dealing with Hostnames

NetworkAs stated last time; When you’re no longer serving DNS from the same machine as your DHCP server, local hostnames may become an issue.

If you’re like me, all the things you actually would be needing to access by name in that matter already have static addresses and /etc/hosts file entries. I had an idea that I thought should be shared though.

This is a little script I wrote. What it does, is takes the dhcp.leases file on an OpenWRT router and produces a correctly formatted hosts file. In the previous article, I offered my custom config, and you’ll see the option to have dnsmasq parse your /etc/hosts file — this is for that.

Weather you have 4 devices on your network, 40 or however many you’ve got, this is an easy way to get the local hostnames working on your new custom DNS setup.

Here is the code for Leases2Hosts, you can run it right on OpenWRT.

#!/bin/sh
# OpenWrt Leases2Hosts 0.01 -- BTA 03.13.2025 -- LostGeek.NET
# Transforms OpenWrt dhcp leases file into format suitable for external DNS server

LEASES_FILE="/tmp/dhcp.leases"
OUTPUT_FILE="/tmp/dhcp.hosts"

# Set domain suffix (leave blank to disable)
DOMAIN_SUFFIX=".lan"

# Ensure the leases file exists
[ -f "$LEASES_FILE" ] || { echo "Leases file not found!"; exit 1; }

# New hosts file header
echo "# Generated by Lease2Hosts" > "$OUTPUT_FILE"

# Process the leases file using BusyBox-compatible awk
awk -v suffix="$DOMAIN_SUFFIX" '
{
    ip = $3;
    hostname = $4;

    # Ignore entries where hostname is "*"
    if (hostname == "*") next;

    # Ensure hostname is not a MAC address (contains colons)
    if (index(hostname, ":") > 0) next;

    # Ensure hostname is only letters, numbers, dots, and dashes
    if (match(hostname, /^[a-zA-Z0-9.-]+$/)) {
        if (suffix != "") {
            print ip, hostname, hostname suffix;
        } else {
            print ip, hostname;
        }
    }
}' "$LEASES_FILE" >> "$OUTPUT_FILE"

echo "Hosts file:"
echo "-----"
cat $OUTPUT_FILE
echo "-----"
echo "Hosts file written: $OUTPUT_FILE"

You can run this once and be done, if you don’t always add and change devices. It can also be auto started via a cron job.

I think there is even a way to have an event-based trigger so perhaps it could run as soon as a new lease is given to a unique device. I’ll leave that up to the reader though!

For those who don’t know, what this does is reads the DHCP leases file; this has the IPs and hostnames of all DHCP clients on your network. It also has mac addresses though, and may contain nameless entries, both of which you obviously don’t want in your hosts file. I’d imagine this could be very useful if you’ve got a network full of machines, VMs, or IoT devices… heck, even a family with laptops, smartphones and tablets.

It produces output as follows: 10.0.0.1 workstation1 workstation1.local 10.0.0.2 laptop1 laptop1.local etc…

From the dhcp.leases file, which looks something like this: *1621306452 c8:3d:6b:55:f1:e5 10.0.0.22 Roku * 1772607384 2c:ab:67:3d:90:5d 10.0.0.29 piframe 01:2c:cf:67:3d:90:5d etc…*

Quite ugly — notice the double MAC?? Well, that happens, especially on modern cell phones which hide their mac as a privacy feature, and on cheap-o devices which don’t have the mac set in stone.

Originally MACs weren’t supposed to just be changed on a whim but rather burned into the device’s eprom. My script aims to sort out all of this non-sense. I have had excellent results using the script, however please review it before using the generated list. If you understand shell script basics and awk, you can gauge your own confidence in it being fairly safe, but I shall make no such guarantee.

Using cron and scp, you can automate putting this new hosts file on your DNS server. However, I’d recommend that you use it simply to save you time in formatting a hosts file from a large lease pool — and it seems to do so quite well.

© 2025 LostGeek.NET - All Rights Reserved. Powered by ClassicPress, NGINX, Debian GNU/Linux.