Wolfspyre Labs 🐺🔥🔬/ Our Guides/ CoreDNS @ Wolfspyre Labs/ 🏗️ Setting Up CoreDNS/ Pi4 Soup to nuts/ ⑦ Extra Credit/ ⑦ Extra Credit ⇦ ⇦ ⇦ Make Haste! Robustification ⑥ Lets set up the eInk display! # ⑧ eInk Issues ⇨ ⇨ ⇨ PaperTTY # PaperTTY dependencies Apt Packages Install Poetry Setup PaperTTY Clone the PaperTTY repo Build paperTTY Test and Enable # 🔨 Test that PaperTTY actually works 🔤 Install fonts to increase legibility Start PaperTTY at boot 🛠️ PaperTTY Startup script 🔧 Systemd PaperTTY initscript 🔧 Necessary Handle Jiggling 🪠 Systemd enablement 🟢 DNSTop # 🏗️ Pre-reqs 📦 Packages 💿 ⌨️ Getty 🖥️ 🪩 Disco 🎉 🐾 PaperTTY: An eInk console #PaperTTY 1 is a nifty python tool to display a console TTY on an eInk display. Here we use it to give us an easily viewable status indicator. I wanted some mechanism of easily assessing the health of the DNS hosts… I didn’t want to spend too much time on it, but I wanted it to be robust enough that it would ‘just work’ consistently. I (admittedly briefly) explored a few different tools, and landed on a combination of PaperTTY and 🔗DNSTop There are definitely other ways to achieve this goal. While I’ll likely play with others later.. …This works well enough for the moment. Install Pre-Reqs for PaperTTY #Apt Packages # Installing the needful apt-get install libjpeg-dev libjpeg-dev libtiff6 python3-pip python3-pip-whl python3-setuptools-whl python3-venv python3-rgpio python3-rpi.gpio rgpio-tools librgpio python3-gpiozero python3-rpi.gpio rpi.gpio-common Poetry #Poetry2 is a packaging and dependency management toolchain for Python. Ubuntu Noble They made installing Poetry really easy in ubuntu 24: Install Poetry apt-get install python3-poetry Quickly test and validate that Poetry is functional # Poetry Version evaluation root@ubuntu:~# poetry --version ; cat /etc/lsb-release Poetry (version 1.8.2) DISTRIB_ID=Ubuntu DISTRIB_RELEASE=24.04 DISTRIB_CODENAME=noble DISTRIB_DESCRIPTION="Ubuntu 24.04.1 LTS" Raspbian Danger! The Internet is scary! I do not advocate running random shit on the internet piped into an interpreter sight unseen. I STRONGLY encourage you to look at the script (found here) before running the install one-liner below: Install Poetry # Install Poetry curl -sSL https://install.python-poetry.org | python3 - Symlink poetry to user-scoped bin directories # Symlink poetry to user-scoped bin directories _B='/root/.local/share/pypoetry/venv/bin/poetry' for DIR in '/root/bin' '/root/.local/bin'; do TARGET="${DIR}/poetry"; \ makeDirIfNeedful "${DIR}"; \ if [[ -e ${TARGET} ]]; then \ _L=`ls -la ${TARGET}|awk '{print $11}'` echo " TARGET: ${TARGET} exits. ${_L}"; else warn "TARGET: ${TARGET} does NOT exist. Linking"; ln -s ${_B} ${TARGET} ls -la ${TARGET} fi done Quickly test and validate that Poetry is functional #root@coredns-03:~# poetry --version Poetry (version 1.2.1) PaperTTY Installation #Clone the Repo #root@coredns-03:~# git clone https://github.com/joukos/PaperTTY.git Cloning into 'PaperTTY'... remote: Enumerating objects: 801, done. remote: Counting objects: 100% (29/29), done. remote: Compressing objects: 100% (21/21), done. remote: Total 801 (delta 13), reused 20 (delta 8), pack-reused 772 Receiving objects: 100% (801/801), 7.00 MiB | 13.36 MiB/s, done. Resolving deltas: 100% (497/497), done. root@coredns-03:~# Build PaperTTY # root@coredns-03:~# cd ~/PaperTTY && poetry install Actually running the command should look something like this: root@coredns-03:~# cd ~/PaperTTY && poetry install Creating virtualenv papertty-uSU0pReX-py3.10 in /root/.cache/pypoetry/virtualenvs Updating dependencies Resolving dependencies... (163.6s) Writing lock file Package operations: 1 install, 9 updates, 0 removals • Updating attrs (19.3.0 -> 22.1.0) • Updating idna (2.9 -> 3.4) • Updating setuptools (65.3.0 -> 50.3.2) • Updating six (1.15.0 -> 1.16.0) • Updating hyperlink (19.0.0 -> 21.0.0) • Updating incremental (17.5.0 -> 21.3.0) • Updating pyhamcrest (2.0.2 -> 2.0.3) • Updating zope-interface (5.1.0 -> 5.4.0) • Installing rpi-gpio (0.7.1) • Updating spidev (3.4 -> 3.5) Installing the current project: papertty (0.1.8b) Pretty neat and simple right? Hopefully this got you a working setup, lets make sure real quick: Quick test of PaperTTY #So… a quick test of PaperTTY will take you down one of a few paths…. poetry run papertty --driver EPD2in13v2 scrub && \ echo "Evey loves steak" | poetry run papertty --driver EPD2in13v2 stdin “Worky ish” #So… Cool! It works… BUT… it’s not terribly useful just yet without a magnifying glass… SO lets continue, and install fonts, shall we? Not so worky? #Several things are likely to go wrong here… Unless you lucked out, and things worked, head on over to the eInk Weirdness page and lets get you sorted out… … or try to at least…. Then come back here and continue! Installing Font-related packages #PaperTTY includes the TomThumb3 Font. This is awesome, but pretty small. So, there’s a handful of fonts that can be installed and will work with PaperTTY… In addition to the fonts available through apt, You can simply deploy TrueType fonts into /usr/share/fonts/truetype/ and reference them when launching PaperTTY. Quick shout-out to OpenDyslexic4… Which is a neat font with increased readability. It wasn’t suitable to my needs here, but is useful in other contexts. Install the fonts #apt-get install -y xfonts-utils xfonts-encodings x11-common \ ttf-mscorefonts-installer libfontenc1 fonts-liberation cabextract The process of installing these packages will require you to accept a user agreement ( remember, it IS microsoft we’re talking about here… ) cd /tmp _FONTDIR="/usr/share/fonts/truetype" _R=ubuntu-font-family _V=0.83 _ZipDir="${_R}-${_V}" _F="0cef8205-${_ZipDir}.zip" wget "https://assets.ubuntu.com/v1/${_F}"||exit 1 unzip ${_F} "${_ZipDir}/*" -d "${_FONTDIR}/" Once you’ve installed the fonts; you can make things a hair more legible: poetry run papertty --driver EPD2in13v2 scrub && echo "Evey loves steak" | \ poetry run papertty --driver EPD2in13v2 stdin --size=10 \ --font="/usr/share/fonts/truetype/msttcorefonts/Andale_Mono.ttf" Much more legible, IMHO… #To be fair, from a legibility perspective, both are kinda small; but this thing IS only 2" wide and 1" tall. PaperTTY Start script #The purpose of this script is to make the (re)configuration of the service independent from the invocation of PaperTTY. (In other words, you won’t have to jiggle the systemd daemon-reload handle anytime you make changes to the PaperTTY start script.) Install the following script someplace in your $PATH. I personally chose /root/bin/start-PaperTTY.sh. Note If you put this script in a different location, be sure to change your systemd init script for papertty accordingly. /root/bin/start-PaperTTY.sh: #!/usr/bin/env bash set -e DATESTRING=$(date +%m%d%y) _STARTTIME=$(/bin/date +%s) runningTime () { _NOW=$(/bin/date +%s) echo -e "$(( ${_NOW}-${_STARTTIME} ))" } convertsecs() { #take an int which is a number of seconds (IE: # now=$(date %s) ; sleep 30; newer_now=$(date %s); age=(${newer_now)-${now}) ; info "This took: $(convertsecs $age)" # ^^^^^---- untested example ((h=${1}/3600)) ((m=(${1}%3600)/60)) ((s=${1}%60)) printf "%02d:%02d:%02d\n" ${h} ${m} ${s} } error () { MSG=$1 _time=$(convertsecs $(runningTime)) echo -e "\033[31m[${_time}] ERROR\033[0m: $MSG" >>/dev/stderr } warn () { MSG=$1 _time=$(convertsecs $(runningTime)) echo -e "\033[1;33m[${_time}] WARN\033[0m: $MSG" >>/dev/stderr } info () { MSG=$1 _time=$(convertsecs $(runningTime)) echo -e "\033[32m[${_time}] INFO\033[0m: $MSG" } VENVROOT='/root/.cache/pypoetry/virtualenvs' PTTYROOT='/root/PaperTTY' POETRYBIN='/root/bin/poetry' if [[ `ls ${VENVROOT}|grep -c papertty` -ne 1 ]]; then error "I don't seem to be able to identify the papertty virtualenv. " sleep 1 error "I'm looking for exactly one match on 'papertty' here: ${VENVROOT}:" error "Contents listed below.... `ls -lA ${VENVROOT}`" sleep 1 error "I'm Not sure what to do. So... Executing maneuver FORCIBLY INSERT THUMBS UP ASS" sleep 3 error "Ow. I'm In pain." false; else _V=`ls ${VENVROOT}/papertty*/bin/activate` if [[ -e "${_V}" ]]; then info "WolfspyreLabs PaperTTY Wrapper -=/root/bin/StartPaperTTY=-" info "Virtualenv initializer: ${_V} " . ${_V} info "switching to PaperTTY Dir: ${PTTYROOT}" cd ${PTTYROOT} info "What a mess!! Scrubbing the Eink Display" ${POETRYBIN} run papertty --driver EPD2in13v2 scrub info "Fuck... what a day" info "Starting PaperTTY Terminal on /dev/vcsa3" info " partial refresh disabled. Cursor disabled." info " sleep 0.9. with an extra scrub first.... ..Because we care." info " Thank you for choosing WolfspyreLabs " sleep 1 info "Fuck your day. --hugs n Kisses" ${POETRYBIN} run papertty --nopartial --driver EPD2in13v2 terminal --vcsa=/dev/vcsa3 --font="/usr/share/fonts/truetype/msttcorefonts/Andale_Mono.ttf" --size=9 --cols 51 --rows 13 --sleep 0.9 --scrub --cursor=none else error "${_V} is not real! BOO" false fi fi PaperTTY systemd service file # /lib/systemd/system/papertty.service: [Unit] Description=PaperTTY DefaultDependencies=no After=getty.target [Service] Type=simple KillSignal=SIGINT TimeoutStopSec=8 Restart=on-failure ### Change the paths below to match yours WorkingDirectory=/root/PaperTTY ExecStart=/root/bin/StartPaperTTY ### [Install] WantedBy=sysinit.target Install the systemd script #cat <<EOF>/lib/systemd/system/papertty.service [Unit] Description=PaperTTY DefaultDependencies=no After=getty.target [Service] Type=simple KillSignal=SIGINT TimeoutStopSec=8 Restart=on-failure ### Change the paths below to match yours WorkingDirectory=/root/PaperTTY ExecStart=/root/bin/StartPaperTTY ### [Install] WantedBy=sysinit.target EOF rc.local script #As pointed out on the PaperTTY Readme5 Occasionally agetty goes a little apeshit and needs to be kicked after papertty is started on a tty… I added this as a belt-and-suspenders prophylactic to keep the hosts stable. it may not be necessary. YMMV. ‘/etc/rc.local`: /#!/bin/bash #/etc/rc.local /etc/init.d/procps restart exit 0 Last but not least… enable and start the PaperTTY Service #Its the simplest of things… …it’s so easily overlooked… Warning I may or may not have forgotten to do this and sat scratching my head for a bit wondering why stuff wasn’t working…. systemctl enable papertty.service systemctl start papertty.service And with that, You’ve done it! PaperTTY is now running It’s bound to the virtual terminal you specified in the PaperTTY Start script. AND it aught be started next time you reboot too! Strong work! Now lets set up getty to run DNSTop on the virtual terminal PaperTTY is displaying. 🐾 DNSTOP #So, there’s not really a whole lot to this, once the kinks are identified and worked out, it’s pretty clean, really. Packages #apt-get install dnstop tio ttylog rungetty tio ttylog ttysnoop The two most important packages here are rungetty6 and dnstop7. Rungetty #If you’ve not poked much into the way a console is managed in linux, this might be a little weird. TLDR: getty ((or something similar)) listens on known locations for user activity and does the needful for that context.. Usually this involves starting a ’login’ process and letting things go from there. Rungetty start script #We need to tell the system we want another virtual terminal instantiated. and we want that terminal instantiated in a fashion which permits us to launch an arbitrary command instead of init / login The simplest way of doing that is by creating a new singleton service which is responsible for making sure that a console manager process is started just for our chosen virtual terminal, and giving it unique startup parameters which tell it that we want it to run ((in our case)) ‘dnstop’ instead of login Much like we did with papertty, the way to do this is by creating an init script / systemd startup file. Lets deploy one and continue on, shall we? Rungetty init script #/etc/systemd/system/getty-tty3.service [Unit] Description=Getty on vcsa3 Documentation=man:agetty(8) man:systemd-getty-generator(8) Documentation=http://0pointer.de/blog/projects/serial-console.html After=systemd-user-sessions.service plymouth-quit-wait.service getty-pre.target After=rc-local.service # If additional gettys are spawned during boot then we should make # sure that this is synchronized before getty.target, even though # getty.target didn't actually pull it in. Before=getty.target IgnoreOnIsolate=yes Conflicts=rescue.service Before=rescue.service # On systems without virtual consoles, don't start any getty. Note # that serial gettys are covered by serial-getty@.service, not this # unit. ConditionPathExists=/dev/tty3 [Service] ExecStart=/sbin/rungetty --autologin root tty3 -u root -g root -- /usr/bin/dnstop -l3 -4QRr5 eth0 Type=idle Restart=always RestartSec=0 UtmpIdentifier=tty3 TTYPath=/dev/tty3 TTYReset=yes TTYVHangup=yes TTYVTDisallocate=yes KillMode=process IgnoreSIGPIPE=no SendSIGHUP=yes UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREM ENT LC_IDENTIFICATION [Install] WantedBy=getty.target Once you’ve put this in place, much like you did with the PaperTTY script, you’ll need to enable it, and start it. Enable the rungetty process #systemctl enable getty-tty3.service Start the rungetty process #systemctl start getty-tty3.service This will start a dnstop process as root, listening for dns traffic on eth0 and emitting some metrics. I’ll leave adjusting dnstop’s parameters as an exercise for the reader. And that’s about it for dnstop. WTFUtil # ⬅⃖⃖ Back to Robustify …Continue ➡⃗⃗ # https://github.com/joukos/PaperTTY ↩︎ https://python-poetry.org ↩︎ https://robey.lag.net/2010/01/23/tiny-monospace-font.html ↩︎ https://opendyslexic.org ↩︎ https://github.com/joukos/PaperTTY#how-to-use-the-terminal ↩︎ https://manpages.ubuntu.com/manpages/trusty/man8/rungetty.8.html ↩︎ http://dns.measurement-factory.com/tools/dnstop/ ↩︎