diff --git a/README.md b/README.md
index 410ff1a..a3b7d2b 100644
--- a/README.md
+++ b/README.md
@@ -21,6 +21,9 @@ When seen as part of the IP network, they are called
* [Node Architecture](#na "Main Chapter")
+ [Hardware Node](#hn "Chapter Reference")
+ [Virtual QEMU Guest Node](#vq "Chapter Reference")
+* [RaspiOS Hints & Helpers](#oe "Main Chapter")
+ + [Upgrade Caveat](#uc "Chapter Reference")
+ + [Installer Scripts](#is "Chapter Reference")
* [Licence](#li "Main Chapter")
# Quick Start
@@ -301,6 +304,51 @@ Here, node ID configuration is superimposed by the *QEMU virtual machine* when
configuring the WAN interface via DHCP. Nevertheless, LAN and WLAN interfaces
follow the same logic as in the hardware case.
+# RaspiOS Hints & Helpers
+
+## Upgrade Caveat
+
+Upgrading the current *RaspiOS* with *apt update;apt upgrade* will result in
+a boot image replacement that cannot be properly handled by *QEMU* (as of Feb
+2021). In that case, *QEMU* just stalls and leaves the system incommunicado.
+The replacement happens when running
+
+ sh pijack.sh --software-update
+or
+
+ sh pijack.sh --apt-upgrade
+
+As a kludge, no *apt upgrade* command must be run on the *RaspiOS* when
+installing which can be accomplished with
+
+ sh pijack.sh --base-system --apt-install --local-software
+
+See *sh pijack.sh --help* for details.
+
+
+## Installer scripts
+
+With the *--local-software* command line option for the *pijack.sh* tool,
+the following installer scripts will be provided in the */usr/local/src*
+directory of the *RaspiOS* image. See the script headers for the Debian
+packages needed for compiling and running. The scripts will fetch the source
+code from *github* and install into */usr/local/bin* or */usr/local/sbin*.
+Invoking a script again again, it will re-compile/install only if there was
+source code update.
+
+* *ndjbdns-update.sh*
+ This script installs a ported version of the *DJBDNS* name server tools
+ originally written by Dr. D J Bernstein. These servers are supposed to run
+ under control of *runit* or *daemontools*.
+
+* *nim-update.sh*
+ Installs the latest development version of the *NIM* compiler.
+
+* *rsync-update.sh*
+ Compiles the latest *rsync* version. This is currently needed (as of Feb
+ 2021) for running an *rsync* server proxied through *NGINX* (allowing
+ certificate authentication.)
+
# Licence
This is free and unencumbered software released into the public domain.
diff --git a/pibox.sh b/pibox.sh
index db6fadc..cfd6316 100644
--- a/pibox.sh
+++ b/pibox.sh
@@ -601,7 +601,7 @@ then
fi
# -----------------------------------------------------------------------------
-# Delete all clons in cache
+# Delete all clones in cache
# -----------------------------------------------------------------------------
if [ -n "$CCACHECLN" ]
diff --git a/pijack.sh b/pijack.sh
index 5439177..b319694 100644
--- a/pijack.sh
+++ b/pijack.sh
@@ -614,7 +614,7 @@ pijack_ssh_apt_install () { # syntax: [packages] ...
pijack_verify_ssh_available
# sanitise package list
- local pkgs=`echo -n "$raw_pkgs"|tr -c '[:alnum:]:*+-' ' '|sed 's/ */ /g'`
+ local pkgs=`echo -n "$raw_pkgs"|tr -c '[:alnum:]:.*+-' ' '|sed 's/ */ /g'`
# needs to run as SSH command (piping through /bin/sh causes APT to
# complain; it seems that a pseudo tty must be available)
diff --git a/raspios/local/usr/local/src/ndjbdns-update.sh b/raspios/local/usr/local/src/ndjbdns-update.sh
new file mode 100644
index 0000000..ae719a6
--- /dev/null
+++ b/raspios/local/usr/local/src/ndjbdns-update.sh
@@ -0,0 +1,73 @@
+#! /bin/sh
+#
+# Install/update ndjbdns
+#
+#
+# RaspiOS/Debian/Ubuntu extra packages for compiling:
+#
+# autoconf automake g++ gcc
+#
+
+self=`basename "$0"`
+prfx=`dirname "$0"`
+
+ndjbdns_src="https://github.com/pjps/ndjbdns.git"
+ndjbdns_trg="$prfx/ndjbdns"
+ndjbdns_etc="/usr/local/src/ndjbdns-hideaway"
+
+suffix=package-updated
+ndjbdns_tag=`date +%Y%m%d%H%M%S-$suffix`
+
+
+# Install or update DNJBDNS sources
+if [ -d "$ndjbdns_trg/.git" ]
+then
+ (set -x; cd "$ndjbdns_trg" && git pull origin master)
+else
+ (set -x; git clone --depth 1 "$ndjbdns_src" "$ndjbdns_trg")
+fi || {
+ echo
+ echo "*** $self: something went wrong, please install manually"
+ echo
+ exit 2
+}
+
+
+# Check the locally provided time stamp of last update
+if (cd "$ndjbdns_trg" && git describe 2>/dev/null) | grep -q "$suffix\$"
+then
+ echo
+ echo "*** $self: recently updated, already"
+ echo
+else
+ (
+ trap "set +x;echo;echo '*** Oops, unexpected exit!';echo;trap" 0
+ set -ex
+ cd "$ndjbdns_trg"
+
+ # create/update configure script
+ touch README
+ aclocal
+ autoheader
+ libtoolize --automake --copy
+ autoconf
+ automake --add-missing --copy
+
+ # configure and compile
+ ./configure --sysconfdir="$ndjbdns_etc"
+ make
+
+ # install binaries
+ make install-strip
+
+ # clean up
+ make distclean
+ [ -s README ] || rm -f README
+
+ # set update time stamp
+ git tag -a -m '' "$ndjbdns_tag"
+ trap 0
+ )
+fi
+
+# End
diff --git a/raspios/local/usr/local/src/nim-update.sh b/raspios/local/usr/local/src/nim-update.sh
new file mode 100644
index 0000000..6ddb2cb
--- /dev/null
+++ b/raspios/local/usr/local/src/nim-update.sh
@@ -0,0 +1,139 @@
+#! /bin/sh
+#
+# Install/update nim compiler
+#
+# RaspiOS/Debian/Ubuntu runtime packages:
+#
+# gcc (optional libssl1.1)
+#
+# RaspiOS/Debian/Ubuntu extra packages for compiling:
+#
+# (optional libssl-dev)
+#
+
+self=`basename "$0"`
+prfx=`dirname "$0"`
+branch=devel
+
+# see CPU case below: docs not needed on raspi
+build_docs=yes
+
+nim_src="https://github.com/nim-lang/Nim.git"
+cso_src="https://github.com/nim-lang/csources"
+nim_trg="$prfx/nim"
+
+suffix=package-updated
+nim_tag=`date +%Y%m%d%H%M%S-$suffix`
+arch=`dpkg --print-architecture`
+
+case $arch in
+armhf)
+ # No docs on RaspiOS/RaspberriPi
+ CPU="--cpu $arch"
+ build_docs=no
+esac
+
+# Install or update NIM sources
+if [ -d "$nim_trg/.git" ]
+then
+ (set -x; cd "$nim_trg" && git pull origin $branch)
+else
+ (set -x; git clone --depth=1 --branch=$branch "$nim_src" "$nim_trg")
+fi || {
+ echo
+ echo "*** $self: something went wrong, please install manually"
+ echo
+ exit 2
+}
+
+# Check the locally provided time stamp of last update
+if (cd "$nim_trg" && git describe 2>/dev/null) | grep -q "$suffix\$"
+then
+ echo
+ echo "*** $self: recently updated, already"
+ echo
+else
+ (
+ trap "set +x;echo;echo '*** Oops, unexpected exit!';echo;trap" 0
+ set -ex
+ cd "$nim_trg"
+
+ # import C library (make it resilient against temporary hangups)
+ for _ in 1 2 3
+ do
+ [ ! -d csources ] ||
+ mv csources csources~
+ rm -rf csources~
+
+ if git clone --depth=1 "$cso_src"
+ then
+ break
+ fi
+
+ sleep 10
+ done
+ (cd csources && sh build.sh $CPU)
+
+ ./bin/nim c koch
+ ./koch boot -d:release
+ ./koch nimble || true
+ ./bin/nim c -d:release -o:bin/nimgrep tools/nimgrep.nim || true
+
+ # clean up, save space
+ find . -type d -name nimcache -print | xargs -n1 rm -rf
+ rm -rf csources csources~
+
+ # make binaries accessible
+ chmod +x ./bin/nim*
+
+ # build docs unless disabled
+ if [ yes = "$build_docs" ]
+ then
+ set +e
+ rm -rf web/upload/[1-9]*
+ ./koch docs
+ p=`ls -d web/upload/[1-9]*`
+ ./bin/nim --skipProjCfg buildIndex -o:$p/theindex.html $p || true
+ fi
+
+ # Install shell script stubs
+ (
+ set +x
+ NIM_BIN="`pwd`/bin"
+ mkdir -p /usr/local/bin
+ for name in nim nimble nim-gdb nimgrep
+ do
+ cmd="/usr/local/bin/$name"
+
+ if [ -x "$cmd" ]
+ then
+ continue
+ elif [ -f "$cmd" ]
+ then
+ rm -f "$cmd~"
+ mv "$cmd" "$cmd~"
+ fi
+
+ echo "*** $self: installing $cmd"
+ (
+ echo '#! /bin/sh'
+ echo
+ echo 'self=`basename $0`'
+ echo "bind=$NIM_BIN"
+ echo
+ echo 'PATH=$bind:$PATH'
+ echo
+ echo 'exec "$bind/$self" "$@"'
+ ) >> "$cmd"
+
+ chmod +x "$cmd"
+ done
+ )
+
+ # set update time stamp
+ git tag -a -m '' "$nim_tag"
+ trap 0
+ )
+fi
+
+# End
diff --git a/raspios/local/usr/local/src/rsync-update.sh b/raspios/local/usr/local/src/rsync-update.sh
new file mode 100644
index 0000000..d539ace
--- /dev/null
+++ b/raspios/local/usr/local/src/rsync-update.sh
@@ -0,0 +1,75 @@
+#! /bin/sh
+#
+# Install/update rsync, RaspiOS version is pretty old
+#
+#
+# RaspiOS/Debian/Ubuntu runtime packages:
+#
+# acl attr liblz4-1 libnginx-mod-stream libssl1.1 libzstd1 libxxhash0
+#
+# RaspiOS/Debian/Ubuntu extra packages for compiling:
+#
+# autoconf automake g++ gcc libacl1-dev libattr1-dev liblz4-dev libssl-dev
+# libtool libxxhash-dev libzstd-dev python3-cmarkgfm
+#
+
+self=`basename "$0"`
+prfx=`dirname "$0"`
+
+rsync_src="https://github.com/WayneD/rsync.git"
+rsync_trg="$prfx/rsync"
+
+suffix=package-updated
+rsync_tag=`date +%Y%m%d%H%M%S-$suffix`
+
+
+# Install or update DNJBDNS sources
+if [ -d "$rsync_trg/.git" ]
+then
+ (set -x; cd "$rsync_trg" && git pull origin master)
+else
+ (set -x; git clone --depth 1 "$rsync_src" "$rsync_trg")
+fi || {
+ echo
+ echo "*** $self: something went wrong, please install manually"
+ echo
+ exit 2
+}
+
+
+# Check the locally provided time stamp of last update
+if (cd "$rsync_trg" && git describe 2>/dev/null) | grep -q "$suffix\$"
+then
+ echo
+ echo "*** $self: recently updated, already"
+ echo
+else
+ (
+ trap "set +x;echo;echo '*** Oops, unexpected exit!';echo;trap" 0
+ set -ex
+ cd "$rsync_trg"
+
+ # configure and compile
+ ./configure --sysconfdir=/usr/local/rsync-hideaway
+
+ # kludge
+ grep -q ZSTD_STATIC_LINKING_ONLY config.h ||
+ echo "#define ZSTD_STATIC_LINKING_ONLY" >> config.h
+
+ make
+ make check
+
+ # install binaries
+ make install-strip
+
+ # clean up
+ make distclean
+ rm -rfv /usr/local/rsync-hideaway
+
+ # set update time stamp
+ git tag -a -m '' "$rsync_tag"
+ trap 0
+ )
+fi
+
+# End