SPI on Orange Pi Zero

I had no need for SPI on my many Orange Pi Zero. Now I do, and thus enabling it is needed. Not hard, but not trivial either, which is why I document it here:

  1. Have a recent Armbian, e.g. https://www.armbian.com/orange-pi-zero/
  2. Run “sudo armbian-config”, System, Hardware, enable spi-spidev
  3. Reboot

In theory that should be it and you should now have a /dev/spidev0.0, however I had to edit /boot/armbianEnv.txt first:

verbosity=1
bootlogo=false
console=both
disp_mode=1920x1080p60
overlay_prefix=sun8i-h3
overlays=spi-spidev tve usbhost2 usbhost3
param_spidev_spi_bus=1
param_spidev_max_freq=100000000
rootdev=UUID=01234567-ffff-eeee-dddd-000000000001
rootfstype=ext4
usbstoragequirks=0x2537:0x1066:u,0x2537:0x1068:u

and add the two param_spidev_* lines. Once rebooted, I finally got /dev/spidev1.0

Note that the pins for spidev0 are not available on an Orange Pi Zero, while the pins for spidev1 are:

Replace a Mouse with a Tablet

2 years ago I bought a tablet (Huion HS611) for playing Osu! but I quickly found out that I suck at it. Drawing is not my thing either, so it was mostly unused.

But then recently my Microsoft Sculpt Mouse broke (single click made double clicks). I have a spare mouse which is very “un-ergonomic”. So I needed another replacement, and I tested again the tablet, but this time as a mouse-replacement.

And it’s better than I expected!

  • Scrolling is very easy (like on a phone).
  • Single-click is super-easy although click-and-drag does not work at all as it’s used for scrolling.
  • Double-click and right-mouse-button-clicks are hard: the pen pointer moves a lot more than when using a mouse.
  • Having the pen in your hand means that when you type, you either drop the pen or you type with a pen between your fingers.

The one problem I had was that the Huion driver puts Windows into “Tablet mode”, which is generally correct. However it also means Windows likes to pop up a soft keyboard. It should not as I have a USB keyboard connected. It’s annoying as heck then it happens. Luckily the fix is simple.

No more soft keyboard pop-up

Run services.msc, find the Touch Keyboard and Handwriting Panel Service and simply disable it.

Mounting QCOW2 Images

I use Vagrant for provisioning VMs via libvirt: it’s low-overhead and needs no special non-native software (unlike VirtualBox which I used before, and VMWare WorkStation before that).

My previous PC which ran my Vagrant-built VMs broke though: it does not power on anymore. So I wanted to get the latest files off those. My last backup was 2 months old. Not a big deal, but annoying, and since I could put the mSATA SSD into an external USB case, I could read the data, but mounting QCOW2 images is not as easy as loop-mounting a disk image.

So long story short: this is how to mount a QCOW2 image:

root@giga:/vm/images# file *
debian-VAGRANTSLASH-buster64_vagrant_box_image_10.4.0.img:        QEMU QCOW2 Image (v3), 20000000000 bytes
k3s_knode6.img:                                                   QEMU QCOW2 Image (v2), has backing file (path /var/lib/libvirt/images/debian-VAGRANTSLASH-buster64_vagrant_box_image_10.4.0.img), 21474836480 bytes
root@giga:/vm/images# guestmount -a k3s_knode6.img -m /dev/sda1 /mnt/

Make sure you got the backing file in place.

jq and jc: JSON in the shell

Everyone knows jq: it’s the JSON parser which can do nifty things like picking out data from a JSON document.

The problem is that many commands to not output JSON. E.g. the df command. Or pretty much any normal shell command. kubectl being one of the exceptions.

So what can we do about this? Re-implement all tools! But that’s a lot of work…

Or we use jc! Then you can do things like:

(venv) harald@r2s1:~$ ping 192.168.21.1 -c 4 | jc --ping | jq
{
  "destination_ip": "192.168.21.1",
  "data_bytes": 56,
  "pattern": null,
  "destination": "192.168.21.1",
  "packets_transmitted": 4,
  "packets_received": 4,
  "packet_loss_percent": 0,
  "duplicates": 0,
  "time_ms": 3005,
  "round_trip_ms_min": 1,
  "round_trip_ms_avg": 1.337,
  "round_trip_ms_max": 1.663,
  "round_trip_ms_stddev": 0.241,
  "responses": [
    {
      "type": "reply",
      "timestamp": null,
      "bytes": 64,
      "response_ip": "192.168.21.1",
      "icmp_seq": 1,
      "ttl": 64,
      "time_ms": 1.26,
      "duplicate": false
    },
    {
      "type": "reply",
      "timestamp": null,
      "bytes": 64,
      "response_ip": "192.168.21.1",
      "icmp_seq": 2,
      "ttl": 64,
      "time_ms": 1.43,
      "duplicate": false
    },
    {
      "type": "reply",
      "timestamp": null,
      "bytes": 64,
      "response_ip": "192.168.21.1",
      "icmp_seq": 3,
      "ttl": 64,
      "time_ms": 1,
      "duplicate": false
    },
    {
      "type": "reply",
      "timestamp": null,
      "bytes": 64,
      "response_ip": "192.168.21.1",
      "icmp_seq": 4,
      "ttl": 64,
      "time_ms": 1.66,
      "duplicate": false
    }
  ]
}

PowerShell has something similar: INPUT/OUTPUT is more objects and less a byte stream as it is in Unix. Now I have both: byte stream by default, and JSON structured data if I want to! It’s like eating a cake and keeping it too!

Wireguard VPN

Tested between my home machine and my server-on-the-Internet, and…it just worked once I stopped using my usual Debian 10 server and “upgraded” to Ubuntu 20.04. Really good description is here.

Significantly easier to configure compared to SoftEther which is what I used before. SoftEther can do much more though, but if all you want is a VPN tunnel, Wireguard it is.

HTTPS on Synology’s DSM

My NAS is a Synology DS212 and it can do https. But to make it use my own CA’s certificate, a bit extra work is needed:

Add my own root CA’s Certificate

# Copy to the default folder for CA Root Certs of DSM 
cp root_ca.crt /usr/share/ca-certificates/mozilla/myCA.crt

# Linking to the system folder
ln -s /usr/share/ca-certificates/mozilla/myCA.crt /etc/ssl/certs/myCA.pem 

# Create hashed link
cd /etc/ssl/certs
ln -s myCA.pem `openssl x509 -hash -noout -in myCA.pem`.0

cat myCA.pem >> /etc/ssl/certs/ca-certificates.crt

# Testing
openssl verify -CApath /etc/ssl/certs myCA.pem

Use our own TLS Certificate

Create certificate

step ca certificate ds.lan ds.crt ds.key --kty RSA --size 2048 --not-after=8760h

DSM → Control Panel → Security → Certificate → Add. Then Configure and use the new one as system default.

Now https://ds.lan:5001 will use the new certificate. Repeat in 1 year. Since the default maximum lifetime of certificates was 720h, I had to change this to 1 year (8760h) on the step CA server:

    "minTLSCertDuration": "5m", 
    "maxTLSCertDuration": "8760h",
    "defaultTLSCertDuration": "24h",

CGroups V2 on Debian

CGroups V2 is not enabled by default on Debian, but it can be enabled easily:

# echo 'GRUB_CMDLINE_LINUX_DEFAULT="${GRUB_CMDLINE_LINUX_DEFAULT} systemd.unified_cgroup_hierarchy=1"' >> /etc/default/grub
# grub-mkconfig -o /boot/grub/grub.cfg
# reboot

To find out which cgroups version you use, this is v1:

❯ ls /sys/fs/cgroup
 blkio  cpuacct      cpuset   freezer  memory   net_cls,net_prio  perf_event  rdma     unified
 cpu    cpu,cpuacct  devices  hugetlb  net_cls  net_prio          pids        systemd

and this is v2:

ls /sys/fs/cgroup 
cgroup.controllers  cgroup.max.descendants  cgroup.stat             cgroup.threads  system.slice 
cgroup.max.depth    cgroup.procs            cgroup.subtree_control  init.scope      user.slice

Hiding the Mouse Cursor in X

Konsole hides the mouse cursor when typing. This is generally good. But this is Konsole’s behavior and not a general one. I don’t generally want the mouse cursor when typing. So how to remove it?

Help comes from an old utility: xbanish. Clone the repo, and assuming you got the needed items to compile, 0.2s later you got a 27k binary. Refreshing.

❯ time make
cc -O2 -Wall -Wunused -Wmissing-prototypes -Wstrict-prototypes -Wunused -I/usr/X11R6/include -c xbanish.c -o xbanish.o
cc xbanish.o -L/usr/X11R6/lib -lX11 -lXfixes -lXi -o xbanish
make  0.18s user 0.04s system 84% cpu 0.265 total

❯ ls -la xbanish
-rwxr-xr-x 1 harald users 27288 Sep 22 09:05 xbanish

Put it in /usr/local/bin and make it autostart when KDE starts. And now the mouse cursor disappears in any X11 program.

k3s – local persistent storage

When using k3s and the built-in local persistent storage provider, once in a while you have to edit those files. While that usually works, sometimes you have to replace a 150kB binary file and when containers usually don’t have scp installed, there’s a problem…

The fix is to modify the storage from outside the container. That depends on the persistent storage provider. If it’s NFS, mount by NFS from another machine. If it’s an S3 bucket, edit it directly etc.

k3s has a local persistent storage driver called “local-path”. But where are those files so I can replace one of them? Turns out they are on /var/lib/rancher/k3s/storage/ on a node. Which node and what directory inside storage/ ?

Finding Your PVC

To find the PVC named “grafana-lib”, do

❯ kubectl describe persistentVolumeClaim grafana-lib
Name:          grafana-lib
Namespace:     default
StorageClass:  local-path
Status:        Bound
Volume:        pvc-a89cee51-0000-47d7-a095-2d48400768e3
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
               volume.beta.kubernetes.io/storage-provisioner: rancher.io/local-path
               volume.kubernetes.io/selected-node: knode5
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      3Gi
Access Modes:  RWO
VolumeMode:    Filesystem
Mounted By:    grafana-deployment-669fc6d658-l78z7
Events:        <none>

and the volume shows where it is: knode5:/var/lib/rancher/k3s/storage/pvc-a89cee51…
A bit of jq magic and you get a complete list of all PVCs:

❯ kubectl get persistentVolumeClaims -o json | jq '[.items[] | { "Name": .metadata.name, "Volume": .spec.volumeName, "Node": .metadata.annotations."volume.kubernetes.io/selected-node" }]'
[
  {
    "Name": "influxdb-data",
    "Volume": "pvc-bbac2312-0000-450e-aee1-41a0d5517adb",
    "Node": "knode6"
  },
  {
    "Name": "grafana-log",
    "Volume": "pvc-22814c7b-0000-4b8b-99b6-ab4a4ca6c65c",
    "Node": "knode5"
  },
  {
    "Name": "grafana-lib",
    "Volume": "pvc-a89cee51-0000-47d7-a095-2d48400768e3",
    "Node": "knode5"
  }
]