With my home lab, which I affectionately named SINGULARITY, I mostly interact with it via ssh over my home network. However, I’ve been tweaking BIOS settings a lot so I hooked the PC up to my wifes’ keyboard/video/mouse and was doing a lot of reboots.
But then I stopped tweaking and went back to using the machine as a node on my network. But as I sat there doing my work I started feeling anxious and I didn’t know why. I felt as though someone were watching me. Try as I may, I couldn’t shake this anxious feeling. It turns out that the login prompt was showing and the monitor wasn’t turning off! Mercy me!
I run the machine headless, which means its running at a lower runlevel, so I had no GUI tools or screensaver to set.
Incidentally, I enabled the low runlevel by issuing this simple command:
sudo systemctl set-default multi-user.target
If I wanted the GUI back, I’d just do:
sudo systemctl enable graphical.target --force
sudo systemctl set-default graphical.target
But I digress.
I poked around and didn’t find a direct solution. It did seem like the command I wanted to run was
setterm -blank 1, which would blank the screen and put the monitor into power-save mode. This is exactly what i wanted but the command vomits if you set it in a remote terminal, like Windows Terminal:
$ setterm -blank 1
setterm: terminal xterm-256color does not support --blank
After a little experimenting, I found that when I’m logged directly into the terminal, $TERM is set to
linux. So with this little bit in my .bashrc, I was able to run
setterm -blank 1 only when I’m logged in locally:
if [ "$TERM" == "linux" ]; then
setterm -blank 1
elif [ -e /usr/share/terminfo/x/xterm-256color ]; then
Great! Now when I login, a minute of inactivity blanks the monitor!
But the problem here was on reboot, I wouldn’t be logged in. So I dived into login details more and found there’s a file called
/lib/systemd/system/getty@.service that specifies the command used for the login prompt:
ExecStart=-/sbin/agetty -o '-p -- \u' --noclear %I $TERM
Still, I didn’t see a way to inject
setterm -blank 1 in there. But agetty does take a -l parameter allowing you to specify a login program. So I created /bin/login2:
setterm -blank 1
That’s so ugly I love it! I then invoked this piece of art from agetty:
ExecStart=-/sbin/agetty -l /bin/login2 -o '-p -- \u' --noclear %I $TERM
After a reboot, I found this did not work at all.
Why? because agetty blocks on awaiting login name. It queries for a login name and then passes it to /bin/login. So
setterm -blank 1 within
login2 does not get invoked until you enter the login name. Damn.
But wait, there’s more! agetty also takes a -a argument, autologin name! So I descend further into the rabbit hole and create this beauty:
ExecStart=-/sbin/agetty -a nic -l /bin/login2 -o '-p -- \u' --noclear %I $TERM
This bypassed the username prompt, executed
setterm -blank 1, but this left me with an awkward prompt for the password, and this filled me with even more anxiety than the original non-blanking screen!
I saw that /bin/login can take a -f argument to force a login. Documentation says “Do not perform authentication, user is preauthenticated.” Hahahah, so of course I went ahead and added it. Fuck it, it’s a home lab and this is only a security vulnerability for local access.
Now when I reboot, I basically get logged in automatically. But then, at this point, my .bashrc does the job of calling setterm -blank 1 so why the hell do I need /bin/login2 for?
Sooooo… I started thinking about if I can pass -f from the original agetty invocation and found that yes, this is possible. That’s what the -o option is for. Now I can get rid of /bin/login2 and just have this:
ExecStart=-/sbin/agetty -a nic -o '-f -p -- \u' --noclear %I $TERM