Being the geek that I am, I like to challenge myself with new ideas. A few weeks ago, I decided that my latest challenge should be to create a Christmas slideshow. I could put up a few strings of flashy lights, maybe even hang a wreath, but why should I be like my neighbors? I have the power of Linux and Free Software at my fingertips; I should show it to them, right?
My requirements for the project were simple:
- It must start automatically after boot.
- It must have some privilege separation, for protection against my programming mistakes.
- Later, I decided it should not run during the day, when sunlight makes the slideshow pointless.
The first challenge was to decide on the hardware setup. I have two primary systems: my powerful desktop, my much weaker system for experiments. My desktop system is nowhere near a window, and I didn’t feel like moving my entire computer desk. I’m not sure the weaker system is capable of running a slideshow (yes, it really is that weak). I don’t have a VGA extension cable, but I do have lots of Cat5 for Ethernet. Ah, the distributed X protocol to the rescue! My desktop runs the slideshow, and the experimental system runs the X server. Already having a serial console on the experimental system is an additional benefit, because I can keep a text login for emergency rescues.
The second challenge was to find properly-licensed images suitable for viewing from the street. I leave this as an “exercise for the readers,” who might want pictures for Hanukkah, Sol Invictus, Kwanzaa, or even simply “Happy Birthday.” My only word of advice: try not to be too abstract or conceptual. Remember, this really is a show for the “man on the street”; as my geeky retired mother said, Nativity scenes should not look like pickles.
Finally, it was time to make it all work together. To meet requirement #1, I had to make sure the script was suitable for running from /etc/inittab. Bash scripting is my language of choice, but security isn’t really part of the language (hence requirement #2). I had initially decided to use OpenOffice.org Impress, but it proved to have difficulty with long-term stability, so I settled on using the GLslideshow module from the XScreensaver collection. The GLslideshow setup also uses less memory.
I wanted to make the setup reasonably portable, so I decided to keep the configuration in environment variables (as many as I could think of). These are the local user for the X server; the remote user and hostname for the GLslideshow client; and a local, writable directory for state management.
The X forwarding capability of OpenSSH makes it the preferred channel for connecting the X server and the GLslideshow client. My desktop system connects directly to the Internet via dial-out, so a mis-routed packet needs to be shielded from snooping. The OpenSSH project provides the ssh-keygen program for automating SSH connections, without requiring a password. On the experimental system running the X server, I logged in as myself and ran ssh-keygen, giving no password. The generated key allows unattended scripts to use
On the desktop system, I created a new user called “slideshow”, with only a home directory, but none of the skeleton files. On my Slackware system, this meant deleting the standard skeleton files after the fact, leaving only .ssh:
useradd -g users slideshow cd /home/slideshow rm -rf * .[a-z]* # Be very careful NOT to use ".*"! mkdir .ssh
Then I copied the .ssh/id_rsa.pub file from the experimental system to the desktop, for password-less SSH connections:
cd .ssh scp me@remote:.ssh/id_rsa.pub authorized_keys chmod 600 authorized_keys chown slideshow:users authorized_keys
I confirmed this was correct, by opening an SSH session from the remote system to the local system, without requiring a password.
The GLslideshow program needed to know where to find the images on my desktop system. In a terminal window, I typed:
xhost +localhost # A different user needs this for X access su - slideshow [password] xscreensaver-demo
Then I clicked on the Advanced tab, selected “Choose Random Image” in the Image Manipulation block, and entered “/home/slideshow/wallpapers” as the directory containing the images. Closing the window saved the parameters.
Next, I created a script on the experimental system, to check the network connection and start the slideshow, if the time is between 5:00PM and 7:00AM. Okay, the script is actually the result of approximately 17 iterations. A few notes:
- I have tried to centralize configuration into the environment variables at the top of the script.
- Using -Y instead of -X bypasses certain security checks in OpenSSH’s X forwarding. This means it should be used only on a trusted network, with trusted systems.
- The parameters to glslideshow (no fading or panning) are chosen to minimize the network and CPU load on my experimental system.
- Checking that X is still running could surely be improved. Another process with the same PID as $XPID could appear, confusing the state management with a race condition.
With this script in /etc/rc.d, I made the following adjustments to /etc/inittab:
- I commented out all the c1-c6 lines, so that no login would interfere with the VGA screen. (I already had the serial console ttyS0 set up, from previous tinkering.)
- I changed the x1 line to read: x1:4:respawn:/etc/rc.d/slideshow.sh
With that, I logged in as root and typed “telinit 4” to see if it would work. Voila! Every 20 seconds, a different image appeared.
Bearing in mind the networked nature of the script, I tested its recovery capability by rebooting my desktop. Sure enough, it restarted just fine. In fact, the slideshow was running on the experimental
system before my X login screen appeared on my desktop.
To make it fully automatic, I changed the default runlevel in the experimental system’s /etc/inittab to 4:
This is Slackware’s default X login runlevel; some (most?) Linux distros use runlevel 5 instead. A reboot of the experimental system made sure the slideshow script would survive a reboot.
Once everything was working together correctly, I put the monitor in the window, so that my neighbors and people walking and driving by could see it.
My experiment has been a personal success, bringing together my skills in Bash scripting, documentation chasing, and the old “scratch an itch” feeling.