Planet Grep

Planet'ing Belgian FLOSS people

Planet Grep is maintained by Wouter Verhelst. All times are in UTC.

July 06, 2022

Conferences are back! After Botconf in April, that’s Pass-The-Salt that is organized this week in Lille, France. After the two years break, the formula did not change: same location, free, presentations around security, and free software! And, most important, the same atmosphere.

The first day started in the afternoon and talks are grouped by topic. The first one was cryptography, hard way to start the conference if, like me, you don’t like this. But, the talks were interesting anyway! The first one was “Mattermost End-to-End Encryption plugin” by Adrien Guinet & Angèle Bossuat. Mattermost is a very popular free chat service (like Slack) but a free version is available and the community around it creates a lot of plugins. Encryption is in place between the client and the server but there was a lack of E2EE or “End-2-End Encryption” (so that even administrators of the server can’t see messages and files exchanged). The plugin was not easy to implement due to the Mattermost limitations: notifications, attachments, modification of sent messages, etc. Adrien & Angèle explained how they implemented this, how they solved some challenges, and ended with a quick demo. The plugin is available here if interested.

Then, Ludovic Dubost came on stage to present “CryptPad : a zero knowledge collaboration platform”. This project is already six years old and, even if I’ve heard about it, I never used it. Cryptpad tries to solve all privacy issues with data (example: the cloud by definition). Today, in most cases, it’s all about trust. The situation between the two parties has been widely accepted and let’s sign contracts instead. Cryptpad helps you to work on many documents and share them with your peers. Its key points are encrypted docs that can be edited in real time, E2EE, and key management with secure and private key sharing. Server owners have access to nothing (even recover data). Some features:

  • Create application files (docs, presentations, pads, kanban, surveys, code, forms, …
  • Crypt drive
  • Sharing functions
  • Work in teams

A good resume could be “Get people out of Google Docs”. Another good fact: it requires a low amount of resources. More information on

Then, another tool was presented by Yves Rutschle: “Dataflow tabular charts — a presentation tool for security architects”. The tool is called, yes, written in Perl! Its purpose is to create SVG files that will represent drawings of complex infrastructure or systems but the file is generated based on descriptions in a text file. Example:

-> Human (6)
void / void / void / void / void / Human Content
Reader laptop:

The tool is available here.

The second round of sessions focused on operating systems security. Mickaël Salaün presented “Sandboxing your application with Landlock, illustration with the p7zip case”. Landlock is not new but not known by many people. It’s enable by default on many systems like Ubuntu 22.04-LTS. It’s a software sandboxing systems that allows to restrict access to applications. It must be implemented by developers and is based on only three syscalls! Mickaël explained the system (how to enable it, create rules and populate them) and them applied it to a popular utility, 7zip to add sandboxing capabilities.

The last presentation of the day was “Building operating systems optimized for containers, from IoT to desktops and servers” by Timothée Ravier. The idea behind the talk was to explain how operating systems can be improved by using other techniques like containers to reduce the attack surface. Indeed, many OS are deployed today with plenty of tools that, because software have bugs, increase the attack surface for attackers. The idea is to reduce this amount of software to the bare minimum and deploy them with other technique to make them easier to patch.

The second day started with a series of presentations around networks. Yves Rutschle came back for a a second time with “sslh — an applicative-level protocol multiplexer“. Yves started this project years ago because he’s a big fan of console mail clients like Mutt and would like to have access to a SSH server from anywhere. In 2000, when firewalls started to filter the outgoing traffic, he developed the first version of sslh. The idea is to let sslh to listen to a port (TCP/443) and, depending on the first bytes of the session, redirect the incoming connection: Apache, the SSH server, etc. With time, it expanded, was rewritten C, as a daemon etc… Today, his tool is integrated into many Linux distributions. It also supports more protocols like OpenVPN, XMPP. The tools is available on Yves’s github repo but also available as a package in your favorite Linux distribution.

The next slot was assigned to Eric Leblond who, as usual, came to speak about the Suricata eco-system: “Write faster Suricata signatures easier with Suricata Language Server“. This time, nothing related to the tool in itself but he focused on a recurrent and annoying task: to write Suricata rules. The classic process looks like: write a rule, test it, fine-tune it, test it, … Very complex signatures can be complex to write. Because, he received multiple time the question: “How to write Suricata signature?”, he developed a solution based on the Language Server Protocol: “SLS” or “Suricata Language Server”. From your preferred text editor (lot of them are supported), you can get help, auto-completion, verification directly when you write Suricata rules. Really interesting if you write a lot of them!

The next one was “Building on top of Scapy: what could possibly go wrong?” by Claire Vacherot who’s a pen tester active in the ICS field. She explained their needs for specific tools. They create a framework (BOF – “Boiboite Opener Framework”) but they faced a lot of problems and tried to find an alternative with Scapy. Scapy was not immediately effective so they decided to keep both and use BOF as a frontend for Scapy. Best conclusion: Don’t just use tools, learn the power of them! make the most of them!

After the welcomed coffee break, we switched to other talks. The next one was “Use of Machine and Deep Learning on RF Signals” by Sébastien Dudek. RF signals are used everywhere and a lot of researchers try to look at them to check many risks are related to them (jamming, eavesdropping, replay, inject, …) but the very first challenge is to get a good idea about the signals. What are we capturing? Sébastien explained briefly how to get some signals from very expensive devices to “gadgets” connected to free software. His research was to use machine learning and deep learning to help identifying the discovered signals. As I don’t have experiences in these domains (nor RF nor ML), it was a bit complex to follow but the idea seems interesting. I just bookmarked this site which helps to identify RF signals patterns:

The keynote was given by Ivan Kwiatkowski: “Ethics in cyberwar times”. It was a great talk and an eye-opener for many of us (well, I hope). The common thread was related to thread intelligence. How it is generated, by who, what companies do with it (and by they buy it!). For Ivan, “TI resellers are intelligence brokers”. Also, can there be neutal, apolitical intelligence? This is a huge debate! Everybody uses TI today: APT groups conduct attacks, TI companies write reports and APT groups buy these reports to improve their attacks. What could go wrong?

After the lunch break, we started a série about reverse and binary files. 

Abusing archive-based file formats” by Ange Albertini. Once again, Ange covered his techniques and tools to abuse file formats and create “malicious” documents. I recommend you to have a look at his Github repo.

Then, Damien Cauquil presented “Binbloom reloaded”. The first version of this tool was published in 2020 by Guillaume Heilles. Damien stumbled upon an unknown firmware… First reflex, load it into Ghidra but it was not easy to guess the base address to start the analysis. He started other tools like without luck. He reviewed these tools and explained how they search for the base addresses. Finally, he decided to dive into binbloom and improve it. The tool is available here.

Then another tool was presented by Jose E. Marchesi: “GNU poke, the extensible editor for structured binary data“. Honestly, I never of this hex editor. They are plenty of them in the open source ecosystem but Jose explained they weaknesses. Poke looks extremely powerful to extract specific information and convert them to update the file but I was a bit lost in the details. The tool looks complex at a first sight!

To wrap-up the schedule, Romain Thomas presented something pretty cool: “The Poor Man’s Obfuscator“. The idea of his research was to transform a ELF file (Linux executable) or Mach-O (Macos executable) to make them obfuscated and not easy to debug using classic debuggers/disassemblers. Of course, the modified binaries have to remain executable from an OS point of view. Several techniques were covered like creating a lot of exports with random names or confusing names. Another technique was to alter the sections of the file. Really interesting techniques to seem very powerful. With one sample, he was able to crash Ghidra!

The day finished with a series of rump sessions and the social event in the center of Lille. The day three started with talks related to blueteams. The first one was “Sudo logs for Blue Teamers” by Peter Czanik. Peter is an advocate for Sudo & Syslog-NG, two useful tools for your Linux distributions. Both are integrated smoothly because Sudo logs are parsed automatically by Syslog-NG. IO Logs API is a nice feature that many people don’t know: you can interact with the user session. Ex: Use a few lines of Python code to terminate the session if some text if detected. Peter covered the new features like the possibility to execute a chroot with Sudo. Recap of the new versions: more logging capabilities, track and intercept sub-commands.

The next presentation focused on another tool: “DFIR-IRIS – collaborative incident response platform” presented by Théo Letailleur (&) and Paul Amicelli. As incident handlers, they came with problems to solve: Track elements during investigations, share pieces of information between analysts and handle repetitive tasks. Many solutions existed: TheHive, FIR, Catalyst, DRIFTrack, Aurora. They decided to start their own tool: DFIR-IRIS. It provides the following components:

  • python web application (API, modules)
  • automation (enrichment, reports)
  • collaboration (notes, share, tasks)
  • tracking (IOCs, assets, timeline, evidences)

I was surprised by the number of features and the power of the tool. I’m not using at this time (I use TheHive) but it deserves to be tested! More information here.

The next speaker was Solal Jabob, another regular PTS speaker! This time, he presented: “TAPIR : Trustable Artifact Parser for Incident Response“. Based on what he demonstrated, the amount of work is simply crazy. It’s a complete framework that you can use to collect artefacts and perform triage, export, … It is based on a library (TAP) used to parse data from files, disk images, … then plugins are use to extract metadata. The first tool is presented is Bin2JSON, then TAP-Query, TAPIR is a client/server solution with a REST-API, multi-user capabilities. It is command line or web based. A Python library is also available (TAPyR).

Just before the lunch break, I presented “Improve your Malware Recipes with Cyberchef“. I explained how this tool can be powerful to perform malware analysis.

After the break, the second half of the day was dedicated to pentesting / readteaming presentations. Quickly, we had Antoine Cervoise who presented “MobSF for penetration testers“. MobSF is a free open-source security scanner for mobile applications. He demonstrated how he can find interesting information to be used in his pentest projects. Hugo Vincent presented “Finding Java deserialization gadgets with CodeQL”. Java deserialization remains a common issue in many applications in 2022. It’s still present in the OWASP Top-10. Hugo explained the principle behind this attack, then demonstrated, with the help of CodeQL (a static code analyzer) how he can find vulnerabilities. Pierre Milioni presented “Dissecting NTLM EPA & building a MitM proxy“. NTML is an old protocol but still used to authenticate users on web applications. Microsoft expanded it to “EPA” for “Extended Protection for Authentication”. This make some tools useless because they don’t support this protocol extension. Pierre developed a MitM proxy called Proxy-Ez that helps to use these tools. Finally, Mahé Tardy presented “kdigger: A Context Discovery Tool for Kubernetes Penetration Testing“. kdigger is a tool that helps to perform penetration tests in the context of a Kubernetes environment. The demo was pretty nice!

After two years “online”, it was nice to be back at Lille to meet people in real life. We were approximatively 100 attendees, great number to have time to exchange with many people! The talks have been recorded and are already online, slides as well.

The post Pass-The-Salt 2022 Wrap-Up appeared first on /dev/random.

July 03, 2022


I use a few Raspberry PI’s 4 to run virtual machines and k3s.

I was using the Manjaro Linux with full disk encryption but I’ll switch to Debian GNU/Linux, the main reason is that libvirt is currently broken on archlinuxarm.

You’ll find my journey to get Debian GNU/Linux bullseye up and running on the Raspberry PI with full disk encryption below.


All actions below are executed on a Debian 11 (bullseye) GNU/Linux virtual machine.

Download image

Debian provides more information on how to use Debian GNU/Linux on: You can download the images from:

Download the latest bullseye release image/sha2sum/signature from [

Verify signatures

Go to the directory with the download files.

staf@debian11:~/Downloads/iso/debian/raspi$ ls

Verify that the signature of the checksum file is correct.

staf@debian11:~/Downloads/iso/debian/raspi$ gpg --auto-key-retrieve  --verify 20220121_raspi_4_bullseye.img.xz.sha256.asc
gpg: Signature made Fri 21 Jan 2022 06:19:50 PM CET
gpg:                using EDDSA key 60B3093D96108E5CB97142EFE2F63B4353F45989
gpg: key 2404C9546E145360: public key "Gunnar Wolf <>" imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg: Good signature from "Gunnar Wolf <>" [unknown]
gpg:                 aka "Gunnar Eyal Wolf Iszaevich <>" [unknown]
gpg:                 aka "Gunnar Wolf <>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 4D14 0506 53A4 02D7 3687  049D 2404 C954 6E14 5360
     Subkey fingerprint: 60B3 093D 9610 8E5C B971  42EF E2F6 3B43 53F4 5989
gpg: WARNING: not a detached signature; file '20220121_raspi_4_bullseye.img.xz.sha256' was NOT verified!

You can verify if the checksum file is signed by a trusted key of the Debian project at:

You can search for the name of the maintainer’s key.

If you want to import the key into your trusted key ring execute.

staf@debian11:~/Downloads/iso/debian/raspi$ wget '' -O gwolf_gpg_public_key.asc
gpg --import gwolf_gpg_public_key.asc
--2022-06-19 11:00:26--
Resolving (, 2001:41b8:202:deb:1a1a:0:52c3:4b6a
Connecting to (||:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/plain]
Saving to: ‘gwolf_gpg_public_key.asc’

gwolf_gpg_public_key.asc                 [ <=>                                                                 ]  19.25K  --.-KB/s    in 0.01s   

2022-06-19 11:00:27 (1.27 MB/s) - ‘gwolf_gpg_public_key.asc’ saved [19709]

gpg: key 2404C9546E145360: 24 signatures not checked due to missing keys
gpg: key 2404C9546E145360: "Gunnar Wolf <>" 27 new signatures
gpg: Total number processed: 1
gpg:         new signatures: 27
gpg: no ultimately trusted keys found

To verify the public key is imported execute.

staf@debian11:~/Downloads/iso/debian/raspi$ gpg --list-keys
pub   ed25519 2019-11-22 [SC] [expires: 2024-09-05]
uid           [ unknown] Gunnar Wolf <>
uid           [ unknown] Gunnar Eyal Wolf Iszaevich <>
uid           [ unknown] Gunnar Wolf <>
sub   ed25519 2019-11-22 [A] [expires: 2022-09-06]
sub   ed25519 2019-11-22 [S] [expires: 2022-09-06]
sub   cv25519 2019-11-22 [E] [expires: 2022-09-06]


Verify the signature again.

staf@debian11:~/Downloads/iso/debian/raspi$ gpg --verify 20220121_raspi_4_bullseye.img.xz.sha256.asc 
gpg: Signature made Fri 21 Jan 2022 06:19:50 PM CET
gpg:                using EDDSA key 60B3093D96108E5CB97142EFE2F63B4353F45989
gpg: Good signature from "Gunnar Wolf <>" [unknown]
gpg:                 aka "Gunnar Eyal Wolf Iszaevich <>" [unknown]
gpg:                 aka "Gunnar Wolf <>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 4D14 0506 53A4 02D7 3687  049D 2404 C954 6E14 5360
     Subkey fingerprint: 60B3 093D 9610 8E5C B971  42EF E2F6 3B43 53F4 5989
gpg: WARNING: not a detached signature; file '20220121_raspi_4_bullseye.img.xz.sha256' was NOT verified!
staf@debian11:~/Downloads/iso/debian/raspi$ echo $?

You can ignore the gpg: WARNING: not a detached signature; this is just that gpg also tries to verify the checksum. If you want to get rid of this warning you can move the checksum to another directory and run the gpg verify command again.


Extract the download image.

staf@debian11:~/Downloads/iso/debian/raspi$ xz -d 20220121_raspi_4_bullseye.img.xz


Copy the image to keep the original intact.

staf@debian11:~/Downloads/iso/debian/raspi$ cp 20220121_raspi_4_bullseye.img image

Create tarball

Verify the image

Verify the image layout with fdisk -l.

root@debian11:/home/staf/Downloads/iso/debian/raspi# fdisk -l image
Disk image: 1.95 GiB, 2097152000 bytes, 4096000 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xec6a3321

Device     Boot  Start     End Sectors  Size Id Type
image1            8192  819199  811008  396M  c W95 FAT32 (LBA)
image2          819200 4095999 3276800  1.6G 83 Linux

We’ll use kpartx to map the partitions in the image so we can mount them.

Install kpartx.

root@debian11:/home/staf/Downloads/iso/debian/raspi# apt install kpartx

Map the partitions in the image with kpartx -ax, the “-a” option add the image, “-v” makes it verbose so we can see where the partitions are mapped to.

root@debian11:/home/staf/Downloads/iso/debian/raspi# kpartx -av image
add map loop0p1 (253:3): 0 811008 linear 7:0 8192
add map loop0p2 (253:4): 0 3276800 linear 7:0 819200

Create the destination directory.

root@debian11:/home/staf/Downloads/iso/debian/raspi# mkdir /mnt/chroot

Mount the partitions. Debian (and also Ubuntu) uses /boot/firmware as the raspberry-pi boot filesystem.

root@debian11:/home/staf/Downloads/iso/debian/raspi# mount /dev/mapper/loop0p2 /mnt/chroot
root@debian11:/home/staf/Downloads/iso/debian/raspi# mount /dev/mapper/loop0p1 /mnt/chroot/boot/firmware/

Verify that the filesystems are mounted.

root@debian11:/home/staf/Downloads/iso/debian/raspi# df -h
Filesystem                     Size  Used Avail Use% Mounted on
udev                           1.9G     0  1.9G   0% /dev
tmpfs                          394M  1.2M  392M   1% /run
/dev/mapper/debian11--vg-root   19G   11G  6.6G  62% /
tmpfs                          2.0G     0  2.0G   0% /dev/shm
tmpfs                          5.0M  4.0K  5.0M   1% /run/lock
/dev/vda1                      470M  264M  182M  60% /boot
tmpfs                          394M  840K  393M   1% /run/user/1000
tmpfs                          394M   48K  394M   1% /run/user/114
/dev/mapper/loop0p2            1.6G  557M  886M  39% /mnt/chroot
/dev/mapper/loop0p1            396M   75M  322M  19% /mnt/chroot/boot/firmware

Create the tarball.

root@debian11:/home/staf/Downloads/iso/debian/raspi# cd /mnt/chroot/
root@debian11:/mnt/chroot# tar czvpf /home/staf/Downloads/iso/debian/raspi/debian_bullseye.tgz .


root@debian11:/mnt/chroot# cd
root@debian11:~# umount /mnt/chroot/boot/firmware
root@debian11:~# umount /mnt/chroot

Partition and create filesystems

Create partitions

Partition your harddisk delete all partitions if there are partition on the harddisk.

Make sure that you execute the commands below on the correct harddisk. I executed my commands on Virtual Machine.

I’ll create 3 partitions on my harddisk

  • boot partitions of 500MB (Type c ‘W95 FAT32 (LBA)’
  • root partitions of 50G
  • rest

Empty the partition table.

root@debian11:~# fdisk /dev/sda

Welcome to fdisk (util-linux 2.36.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): o
Created a new DOS disklabel with disk identifier 0xe93a7e99.

Command (m for help): 

Create the boot partition.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 
First sector (65535-117210239, default 65535): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (65535-117210239, default 117210239): +500M

Created a new partition 1 of type 'Linux' and of size 512 MiB.

Command (m for help): 

Set type partition type to vfat.

Command (m for help): t
Selected partition 1
Hex code or alias (type L to list all): c
Changed type of partition 'Linux' to 'W95 FAT32 (LBA)'.

Command (m for help): 

Create the root partition.

Command (m for help): t
Selected partition 1
Hex code or alias (type L to list all): c
Changed type of partition 'Linux' to 'W95 FAT32 (LBA)'.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 
First sector (1114095-117210239, default 1114095): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1114095-117210239, default 117210239): +50G

Created a new partition 2 of type 'Linux' and of size 50 GiB.

Command (m for help): 

Write the partition table to the disk.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.


Create filesystems

boot file system

The Raspberry PI uses a FAT filesystem for the boot partition.

root@debian11:~# mkfs.vfat /dev/sda1
mkfs.fat 4.2 (2021-01-31)

Create the root filesystem

Overwrite the root partition with random data

Because we are creating an encrypted filesystem it’s a good idea to overwrite it with random data. We’ll use badblocks for this. Another method is to use dd if=/dev/random of=/dev/xxx, the dd method is probably the best method but is a lot slower.

root@debian11:~# badblocks -c 10240 -s -w -t random -v /dev/sda2
Checking for bad blocks in read-write mode
From block 0 to 52427999
Testing with random pattern: ^[^[[A^[[A^C3.81% done, 0:49 elapsed. (0/0/0 errors)

Interrupted at block 2027520
root@debian11:~# badblocks -c 10240 -s -w -t random -v /dev/sda2
Checking for bad blocks in read-write mode
From block 0 to 52427999
Testing with random pattern: done                                                 
Reading and comparing: done                                                 
Pass completed, 0 bad blocks found. (0/0/0 errors)

Encrypt the root filesystem


I ran a cryptsetup benchmark on one of my Raspberry PI running Manjaro.

[root@minerva ~]# cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1       529049 iterations per second for 256-bit key
PBKDF2-sha256     853889 iterations per second for 256-bit key
PBKDF2-sha512     674759 iterations per second for 256-bit key
PBKDF2-ripemd160  440578 iterations per second for 256-bit key
PBKDF2-whirlpool  165286 iterations per second for 256-bit key
argon2i       4 iterations, 271370 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
argon2id      4 iterations, 295124 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
#     Algorithm |       Key |      Encryption |      Decryption
        aes-cbc        128b       108.6 MiB/s       111.8 MiB/s
    serpent-cbc        128b        48.3 MiB/s        49.6 MiB/s
    twofish-cbc        128b        75.5 MiB/s        80.4 MiB/s
        aes-cbc        256b        85.8 MiB/s        87.5 MiB/s
    serpent-cbc        256b        48.8 MiB/s        49.6 MiB/s
    twofish-cbc        256b        75.5 MiB/s        80.6 MiB/s
        aes-xts        256b       112.8 MiB/s       114.0 MiB/s
    serpent-xts        256b        50.0 MiB/s        49.7 MiB/s
    twofish-xts        256b        77.8 MiB/s        81.0 MiB/s
        aes-xts        512b        88.3 MiB/s        89.2 MiB/s
    serpent-xts        512b        50.0 MiB/s        49.6 MiB/s
    twofish-xts        512b        77.9 MiB/s        80.7 MiB/s
[root@minerva ~]# 

The aes-xts cipher seems to have the best performance on the RPI4.

Create the Luks volume
root@debian11:~# cryptsetup luksFormat --cipher aes-xts-plain64 --key-size 256 --hash sha256 --use-random /dev/sda2

This will overwrite data on /dev/sda2 irrevocably.

Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/sda2: 
Verify passphrase: 
Ignoring bogus optimal-io size for data device (33553920 bytes).
Open the Luks volume
root@debian11:~# cryptsetup luksOpen /dev/sda2 cryptroot
Enter passphrase for /dev/sda2: 
Create the root filesystem
root@debian11:~# mkfs.ext4 /dev/mapper/cryptroot
mke2fs 1.46.2 (28-Feb-2021)
Creating filesystem with 13102903 4k blocks and 3276800 inodes
Filesystem UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
	4096000, 7962624, 11239424

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (65536 blocks): done
Writing superblocks and filesystem accounting information: done   


Mount and extract

Create a directory to mount the root filesystem.

root@debian11:~# mkdir -p /mnt/chroot

Mount the root filesystem.

root@debian11:~# mount /dev/mapper/cryptroot /mnt/chroot/

Debian and also Ubuntu uses /boot/firmware as the boot partition on a Raspberry PI.

Create the /boot/firmware directory on the root filesystem.

root@debian11:~# mkdir -p /mnt/chroot/boot/firmware

Mount the boot filesystem.

~# mount /dev/sda1 /mnt/chroot/boot/firmware

Verify that the filesystem are mounted.

~# df -h
Filesystem                     Size  Used Avail Use% Mounted on
udev                           1.9G     0  1.9G   0% /dev
tmpfs                          394M  1.2M  393M   1% /run
/dev/mapper/debian11--vg-root   19G   11G  6.9G  60% /
tmpfs                          2.0G     0  2.0G   0% /dev/shm
tmpfs                          5.0M  4.0K  5.0M   1% /run/lock
/dev/vda1                      470M  113M  333M  26% /boot
tmpfs                          394M   48K  394M   1% /run/user/114
tmpfs                          394M   44K  394M   1% /run/user/1000
/dev/mapper/cryptroot           49G   32K   47G   1% /mnt/chroot
/dev/sda1                      500M     0  500M   0% /mnt/chroot/boot/firmware

Extract the tarball.

root@debian11:~# cd /home/staf/Downloads/iso/debian/raspi
root@debian11:/home/staf/Downloads/iso/debian/raspi# tar xzvpf debian_bullseye.tgz -C /mnt/chroot/
root@debian11:/home/staf/Downloads/iso/debian/raspi# sync


To continue the setup we need to boot or chroot into the operating system. It possible to run ARM64 code on a x86_64 system with qemu - qemu will emulate an ARM64 CPU -.

Install the qemu-arm-static package

root@debian11:/home/staf/Downloads/iso/debian/raspi# apt install -y qemu-user-static
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
The following NEW packages will be installed:
  binfmt-support qemu-user-static
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 41.1 MB/41.2 MB of archives.
After this operation, 288 MB of additional disk space will be used.
Get:1 bullseye-security/main amd64 qemu-user-static amd64 1:5.2+dfsg-11+deb11u2 [41.1 MB]
Fetched 22.5 MB in 5s (4,111 kB/s)          
Selecting previously unselected package binfmt-support.
(Reading database ... 147695 files and directories currently installed.)
Preparing to unpack .../binfmt-support_2.2.1-1_amd64.deb ...
Unpacking binfmt-support (2.2.1-1) ...
Selecting previously unselected package qemu-user-static.
Preparing to unpack .../qemu-user-static_1%3a5.2+dfsg-11+deb11u2_amd64.deb ...
Unpacking qemu-user-static (1:5.2+dfsg-11+deb11u2) ...
Setting up qemu-user-static (1:5.2+dfsg-11+deb11u2) ...
Setting up binfmt-support (2.2.1-1) ...
Created symlink /etc/systemd/system/ → /lib/systemd/system/binfmt-support.servic
Processing triggers for man-db (2.9.4-2) ...
Scanning processes...                                                                                                         
Scanning linux images...                                                                                                      

Running kernel seems to be up-to-date.

No services need to be restarted.

No containers need to be restarted.

No user sessions are running outdated binaries.

mount proc & co

To be able to run programs in the chroot we need the proc, sys and dev filesystems mapped into the chroot.

root@debian11:~# mount -t proc none /mnt/chroot/proc
root@debian11:~# mount -t sysfs none /mnt/chroot/sys
root@debian11:~# mount -o bind /dev /mnt/chroot/dev
root@debian11:~# mount -o bind /dev/pts /mnt/chroot/dev/pts


Chroot into ARM64 installation.

root@debian11:~# LANG=C chroot /mnt/chroot/

Set the PATH.

root@debian11:/# export PATH=/sbin:/bin:/usr/sbin:/usr/bin

And verify that we are running aarch64.

root@debian11:/# uname -a
Linux debian11 5.10.0-15-amd64 #1 SMP Debian 5.10.120-1 (2022-06-09) aarch64 GNU/Linux


root@debian11:/# apt update
Get:1 bullseye InRelease [116 kB]                      
Get:2 bullseye-security InRelease [44.1 kB]
Get:3 bullseye-security/main arm64 Packages [159 kB]
Get:4 bullseye-security/main Translation-en [99.8 kB]
Get:5 bullseye/main arm64 Packages [8070 kB]
Get:6 bullseye/main Translation-en [6241 kB]                                                    
Get:7 bullseye/contrib arm64 Packages [40.8 kB]                                                 
Get:8 bullseye/contrib Translation-en [46.9 kB]                                                 
Get:9 bullseye/non-free arm64 Packages [69.6 kB]                                                
Get:10 bullseye/non-free Translation-en [91.3 kB]                                               
Fetched 15.0 MB in 14s (1106 kB/s)                                                                                           
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
34 packages can be upgraded. Run 'apt list --upgradable' to see them.
root@debian11:/# apt upgrade -y
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
The following NEW packages will be installed:
The following packages will be upgraded:
  base-files bsdutils dpkg fdisk gpgv gzip libblkid1 libc-bin libc6 libcryptsetup12 libexpat1 libfdisk1 liblzma5 libmount1
  libpam-systemd libsmartcols1 libssl1.1 libsystemd0 libudev1 libuuid1 linux-image-5.10.0-11-arm64 linux-image-arm64 mount
  openssl rsyslog systemd systemd-sysv systemd-timesyncd sysvinit-utils tasksel tasksel-data udev util-linux zlib1g
34 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 110 MB of archives.
After this operation, 257 MB of additional disk space will be used.
Get:1 bullseye-security/main arm64 dpkg arm64 1.20.10 [2513 kB]
Get:2 bullseye/main arm64 base-files arm64 11.1+deb11u3 [70.1 kB]
Fetched 110 MB in 22s (4981 kB/s)                                                                                            
Extracting templates from packages: 100%
Preconfiguring packages ...
(Reading database ... 18210 files and directories currently installed.)
Preparing to unpack .../base-files_11.1+deb11u3_arm64.deb ...
Unpacking openssl (1.1.1n-0+deb11u2) over (1.1.1k-1+deb11u1) ...
Setting up libexpat1:arm64 (2.2.10-2+deb11u3) ...
Setting up linux-image-5.10.0-15-arm64 (5.10.120-1) ...
I: /vmlinuz is now a symlink to boot/vmlinuz-5.10.0-15-arm64
I: /initrd.img is now a symlink to boot/initrd.img-5.10.0-15-arm64
update-initramfs: Generating /boot/initrd.img-5.10.0-15-arm64
W: Couldn't identify type of root file system for fsck hook
grep: /sys/firmware/devicetree/base/model: No such file or directory
grep: /proc/device-tree/model: No such file or directory
grep: /sys/firmware/devicetree/base/model: No such file or directory
grep: /proc/device-tree/model: No such file or directory
Setting up linux-image-arm64 (5.10.120-1) ...
Setting up linux-image-5.10.0-11-arm64 (5.10.92-2) ...
update-initramfs: Generating /boot/initrd.img-5.10.0-11-arm64
W: Couldn't identify type of root file system for fsck hook
grep: /sys/firmware/devicetree/base/model: No such file or directory
grep: /proc/device-tree/model: No such file or directory
grep: /sys/firmware/devicetree/base/model: No such file or directory
grep: /proc/device-tree/model: No such file or directory
Setting up rsyslog (8.2102.0-2+deb11u1) ...
Running in chroot, ignoring request.
Setting up udev (247.3-7) ...
A chroot environment has been detected, udev not started.
Setting up libfdisk1:arm64 (2.36.1-8+deb11u1) ...
Setting up mount (2.36.1-8+deb11u1) ...
Setting up libcryptsetup12:arm64 (2:2.3.7-1+deb11u1) ...
Setting up openssl (1.1.1n-0+deb11u2) ...
Setting up systemd (247.3-7) ...
Initializing machine ID from random generator.
Setting up fdisk (2.36.1-8+deb11u1) ...
Setting up systemd-timesyncd (247.3-7) ...
Setting up systemd-sysv (247.3-7) ...
Setting up libpam-systemd:arm64 (247.3-7) ...
Setting up tasksel (3.68+deb11u1) ...
Setting up tasksel-data (3.68+deb11u1) ...
Processing triggers for initramfs-tools (0.140) ...
update-initramfs: Generating /boot/initrd.img-5.10.0-15-arm64
W: Couldn't identify type of root file system for fsck hook
grep: /sys/firmware/devicetree/base/model: No such file or directory
grep: /proc/device-tree/model: No such file or directory
Processing triggers for libc-bin (2.31-13+deb11u3) ...
Processing triggers for dbus (1.12.20-2) ...

Install required packages

It’s always useful to have apt-file installed.

root@debian11:/# apt install apt-file
root@debian11:/# apt-file update

Install the required packages for the disk encryption.

root@debian11:~# apt install busybox cryptsetup dropbear-initramfs

Update boot settings

On Debian 10 “buster”, it was required to add CRYPTSETUP=y to the /etc/cryptsetup-initramfs/ configuration. This isn’t required anymore on Debian 11 “bullseye” the update-initramfs will automatically detect the encrypted root filesystem and include the required config into the boot initramfs boot image.

Another pitfall might be that the default console on Debian 11 is the serial port on the Raspberry PI. It’ll ask for the unlock password on the serial unless you update the console configuration (see below).

Label boot partition

Verify labels that are used by Debian GNU/Linux on the Rapberry Pi. Review the labels that are used in /etc/fstab.

root@debian11:~# cat /etc/fstab 
# The root file system has fs_passno=1 as per fstab(5) for automatic fsck.
LABEL=RASPIROOT / ext4 rw 0 1
# All other file systems have fs_passno=2 as per fstab(5) for automatic fsck.
LABEL=RASPIFIRM /boot/firmware vfat rw 0 2

Label the /boot/firmware partition with the RASPIFIRM

root@debian11:/# fatlabel /dev/sda1 "RASPIFIRM"

Update fstab

Update /etc/fstab to use cryptroot as the root filesystem.

root@debian11:~# cd /etc
root@debian11:/etc# vi fstab
# The root file system has fs_passno=1 as per fstab(5) for automatic fsck.
/dev/mapper/cryptroot / ext4 rw 0 1
# All other file systems have fs_passno=2 as per fstab(5) for automatic fsck.
LABEL=RASPIFIRM /boot/firmware vfat rw 0 2
Create /etc/cryptab

Update /etc/cryptab to include the crypted root.

Find the UUID for the cryptroot` filesystem. I open a second session to the x86 host that is used during the installation.

root@debian11:/etc# ls -l /dev/disk/by-uuid/ | grep -i sda2
lrwxrwxrwx 1 root root 10 Jul  2 06:19 xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxx -> ../../sda2

Edit /etc/crypttab.

root@debian11:~# vi /etc/crypttab 
# <target name> <source device>         <key file>      <options>
cryptroot UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx none luks,discard
Generated initramfs

Create the boot image and verify that you don’t have errors related to the cryptsetup.

root@debian11:/etc/default# update-initramfs -u -k all
update-initramfs: Generating /boot/initrd.img-5.10.0-15-arm64
cryptsetup: ERROR: cryptroot: Source mismatch
cryptsetup: WARNING: target 'vda5_crypt' not found in /etc/crypttab
dropbear: WARNING: Invalid authorized_keys file, SSH login to initramfs won't work!
grep: /sys/firmware/devicetree/base/model: No such file or directory
grep: /proc/device-tree/model: No such file or directory
update-initramfs: Generating /boot/initrd.img-5.10.0-11-arm64
cryptsetup: ERROR: cryptroot: Source mismatch
cryptsetup: WARNING: target 'vda5_crypt' not found in /etc/crypttab
dropbear: WARNING: Invalid authorized_keys file, SSH login to initramfs won't work!
grep: /sys/firmware/devicetree/base/model: No such file or directory
grep: /proc/device-tree/model: No such file or directory

cmdline.txt is created by update-initramfs on Debian.

Review the current settings.

root@debian11:/boot/firmware# cat cmdline.txt 
console=tty0 console=ttyS1,115200 root=LABEL=RASPIROOT rw net.ifnames=0 cma=64M rootwait 

You can update the settings in /etc/default/raspi-firmware

root@debian11:/etc# vi /etc/default/raspi-firmware

Set the console.


Set the root partition.

Create new ramfs images
root@debian11:/etc/default# update-initramfs -u -k all
update-initramfs: Generating /boot/initrd.img-5.10.0-15-arm64
cryptsetup: ERROR: cryptroot: Source mismatch
cryptsetup: WARNING: target 'vda5_crypt' not found in /etc/crypttab
dropbear: WARNING: Invalid authorized_keys file, SSH login to initramfs won't work!
grep: /sys/firmware/devicetree/base/model: No such file or directory
grep: /proc/device-tree/model: No such file or directory
update-initramfs: Generating /boot/initrd.img-5.10.0-11-arm64
cryptsetup: ERROR: cryptroot: Source mismatch
cryptsetup: WARNING: target 'vda5_crypt' not found in /etc/crypttab
dropbear: WARNING: Invalid authorized_keys file, SSH login to initramfs won't work!
grep: /sys/firmware/devicetree/base/model: No such file or directory
grep: /proc/device-tree/model: No such file or directory
root@debian11:/etc/default# cat /boot/firmware/cmdline.txt 
 console=tty0 root=LABEL=RASPIROOT rw net.ifnames=0 cma=64M rootwait 
root@debian11:/etc/default# nvi /etc/crypttab 

Remote unlock

Authorized keys

Copy ( or copy /paste ) your ssh public key to /etc/dropbear-initramfs/authorized_keys.

root@debian11:/etc/default# cat > /etc/dropbear-initramfs/authorized_keys
root@debian11:/etc/default# chmod 0600 /etc/dropbear-initramfs/authorized_keys

Fixed Ip address

If you want to use a fixed ip address edit /etc/initramfs-tools/initramfs.conf

root@debian11:/etc/default# vi /etc/initramfs-tools/initramfs.conf 

Recreate boot iniramfs

root@debian11:/etc/default# update-initramfs -u -k all
update-initramfs: Generating /boot/initrd.img-5.10.0-15-arm64
cryptsetup: ERROR: cryptroot: Source mismatch
cryptsetup: WARNING: target 'vda5_crypt' not found in /etc/crypttab
grep: /sys/firmware/devicetree/base/model: No such file or directory
grep: /proc/device-tree/model: No such file or directory
update-initramfs: Generating /boot/initrd.img-5.10.0-11-arm64
cryptsetup: ERROR: cryptroot: Source mismatch
cryptsetup: WARNING: target 'vda5_crypt' not found in /etc/crypttab
grep: /sys/firmware/devicetree/base/model: No such file or directory
grep: /proc/device-tree/model: No such file or directory

Finish installation

Set the root password

root@debian11:/etc/default# passwd root
New password: 
Retype new password: 
passwd: password updated successfully

Install some useful tools

I use ansible to configure my systems. So I installed the sudo and python3 package.

root@debian11:/etc/default# apt install sudo vim python3

Create user

root@debian11:/etc/default# adduser staf
Adding user `staf' ...
Adding new group `staf' (1000) ...
Adding new user `staf' (1000) with group `staf' ...
Creating home directory `/home/staf' ...
Copying files from `/etc/skel' ...
New password: 
Retype new password: 
passwd: password updated successfully
Changing the user information for staf
Enter the new value, or press ENTER for the default
	Full Name []: 
	Room Number []: 
	Work Phone []: 
	Home Phone []: 
	Other []: 
Is the information correct? [Y/n] 


Add the user to the sudo group.

root@debian11:/etc/default# usermod -a -G sudo staf

Verify that the use can execute commands as root.

root@debian11:/etc/default# export EDITOR=vi
root@debian11:/etc/default# visudo 
# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL

Enable the ssh server

root@debian11:/etc/default# systemctl enable ssh
Synchronizing state of ssh.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable ssh

Clean up

Exit chroot

Exit the chroot.

root@debian11:/etc/default# exit
root@debian11:~# uname -a
Linux debian11 5.10.0-15-amd64 #1 SMP Debian 5.10.120-1 (2022-06-09) x86_64 GNU/Linux

Umount the chroot filesystems

Verify the mounted chroot filesystems.

root@debian11:/home/staf/Downloads/iso/debian/raspi# mount | grep -i chroot | awk '{print $3}'

I used the oneliner belong to umount them.

root@debian11:/home/staf/Downloads/iso/debian/raspi# mount | grep -i chroot | awk '{print $3}' | sort -r | xargs -n1 umount 

Close the luks volume…

root@debian11:/home/staf/Downloads/iso/debian/raspi# cryptsetup luksClose cryptroot


Fingers crossed

Connect the usb disk to the raspberry pi and power it on. If you are lucky the PI will boot from the USB device and ask you to type the password to decrypt the root filesystem.


[staf@vicky ~]$ ssh root@minerva
The authenticity of host 'minerva (' can't be established.
ED25519 key fingerprint is SHA256:htnkR8sj1WlF6tDexGhvf5BEDeqEObKBYr/XZWJLdjE.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'minerva' (ED25519) to the list of known hosts.
To unlock root partition, and maybe others like swap, run `cryptroot-unlock`.

BusyBox v1.30.1 (Debian 1:1.30.1-6+b3) built-in shell (ash)
Enter 'help' for a list of built-in commands.

~ # 
~ # cryptroot-unlock
Please unlock disk cryptroot: 
Error: Timeout reached while waiting for PID 192.
~ # Connection to minerva closed by remote host.
Connection to minerva closed.
[staf@vicky ~]$ 


Have fun!

July 02, 2022

A wise person recently told me:

"Release early, release often!"

So here goes... I know a teeny-weeny bit of Python and have recently learned to enjoy FreeCAD. This morning I discovered that FreeCAD can be scripted using Python, so here's my first attempt. Any hints are welcome.



The script creates a (very flat) cube, attaches four smaller flat cubes that serve as tenons, and then cuts out four small cubes that act as mortises. It ends by creating four simple copies of this piece, forming a four-piece puzzle.

The next step is to automate the inclusion of an SVG file on the surface of these pieces.

June 29, 2022

La digue s’est rompue. Sous la pression des flots furieux, je me suis reconnecté, j’ai été inondé.

La cause initiale a été l’organisation de plusieurs voyages. De nos jours, organiser un voyage consiste à passer des heures en ligne à faire des recherches, trouver des opportunités, comparer les offres, les disponibilités puis à réserver, attendre les emails, confirmer les réservations. Au moment de la confirmation finale d’un vol, j’ai par exemple eu la désagréable surprise de découvrir que les bagages n’étaient pas autorisés. Mais bien sur le même vol le lendemain. Il m’a fallu décaler tout le planning, revenir aux réservations des hébergements, etc.

Lorsqu’on passe sa journée en ligne, papillonnant entre les sites web, répondant à un mail de temps en temps, ce genre d’exercice s’inscrit naturellement dans la journée. Mais quand, comme moi, on chronomètre le temps passé en ligne, l’énergie consacrée à organiser un voyage est effrayante. Outre le temps passé à explorer les possibilités, à chercher activement et remplir les formulaires, il y a également le temps d’attente pour les confirmations, les dizaines de mails à déchiffrer dont la plupart ne sont que des arguties administratives ou, déjà, des publicités desquelles il faut se désabonner.

Le tout évidemment devant être synchronisé avec les autres participants desdits voyages.

Entre deux créations de comptes et deux mails de confirmations, attendant la réponse urgente d’un des participants, mon cerveau n’a pas la capacité de se concentrer. Il attend. Et tant qu’à attendre, il y’a justement des dizaines, des centaines, des milliers de petites tranches informationnelles divertissantes. Les résultats d’une course cycliste. Les élections en France. Des sujets passionnants. Voire inquiétant pour le dernier. Mais un sujet inquiétant n’en est que plus passionnant. J’observe avec un intérêt morbide la montée de l’extrême droite comme on regarde un film d’horreur : impuissant et sans pouvoir me détacher de l’écran.

Dans mon cas, le fait de voyager a été la cause de ma reconnexion. Mais cela aurait pu être autre chose. Comme les problèmes que j’ai eus avec mon ex-banque, qui force désormais l’utilisation d’une application Android revendant mes données privées afin de fermer les agences et virer le personnel.

Le point commun entre les banques et les voyagistes ? La disparition du service client. La disparition d’un métier essentiel qui consistait à écouter le client pour ensuite tenter de transformer ses desiderata en actes administratifs. Désormais, le client est seul face à la machine administrative. Il doit remplir les formulaires, tout connaitre, tout comprendre tout seul. Se morigéner pour la moindre erreur, car personne ne vérifiera à sa place.

Mais, si le service n’existe plus, la fiction du service existe toujours. Les départements marketing bombardent d’emails, de courriers papier et d’appels téléphoniques intempestifs. Pour vour faire signer ou acheter un énième produit dont vous ne pourrez plus vous défaire. L’agression est permanente. Le pouvoir politique est incapable d’agir pour plusieurs raisons.

La première est qu’il ne veut pas agir, les politiciens étant les premiers à vouloir envahir les gens sous leurs publicités. Les administrations publiques, peuplées de spécialistes du privé dont on a vanté les mérites organisationnels, se retrouvent… à faire de la publicité. C’est absurde et inexorable. Pourquoi les chemins de fer mettent-ils tant d’effort à promouvoir, à travers des publicités risibles, des systèmes compliqués d’abonnements incompréhensibles ? Ce budget ne pourrait-il pas être utilisé à mieux payer les cheminots ?

Le second point est lui plus profond. Les pouvoirs publics se targuent de vouloir faire la différence entre le « bon » marketing et les arnaques malhonnêtes. Le problème est que la différence est purement arbitraire. Les deux cherchent à exploiter une faiblesse quelconque pour soutirer de l’argent.

Pourquoi, par exemple, faut-il explicitement mettre un autocollant sur sa boîte aux lettres pour éviter de la voir se remplir de publicités sous blister ? L’inverse serait plus logique : n’autoriser la publicité que lorsqu’elle est explicitement demandée.

Pourquoi le RGPD est-il tellement décrié alors qu’il tente de mettre de l’ordre dans la manière dont sont utilisées les données privées ? Parce qu’il a été, à dessein, rendu incroyablement complexe. Il suffirait de mettre dans la loi que toute donnée personnelle ne peut-être utilisée qu’avec un accord explicite valable un an. Que cet accord n’est pas transférable. Cela impliquerait que toute revente de données forcerait l’acheteur à demander l’accord aux personnes concernées. Et à renouveler cet accord tous les ans. Simple, efficace.

À la base, le rôle du pouvoir public est de protéger les citoyens, de faire respecter cette frontière en perpétuel mouvement entre la liberté de l’individu et le respect de l’autre. Mais lorsque le pouvoir public prétend devenir rentable et agir comme un acteur économique plutôt que politique, son action devient ubuesque.

Comme lorsque l’état engage les grands moyens pour empêcher la contrefaçon de cigarettes. En tentant d’arguer que les cigarettes contrefaites sont… dangereuses pour la santé. Oubliant que les cigarettes « légales » sont responsables de plus de morts que le COVID (dont le tiers ne fume pas), d’une destruction grave de l’environnement et de l’émission de plus de 1% du CO2 annuellement produit.

Plusieurs fois par semaine, mon téléphone sonne pour tenter de m’extorquer de l’argent selon une technique quelconque. Je suis pourtant dans une liste rouge. À chaque appel imprévu, je porte plainte sur le site du gouvernement ainsi que, lorsque c’est possible, auprès de la société appelant. Cela m’a valu un échange avec un enquêteur travaillant chez le plus gros opérateur téléphonique belge. Grâce à lui, j’ai compris comment la loi rendait difficile de lutter contre ce type d’arnaque sous prétexte de défendre le télémarketing « légal ».

On en revient toujours au même problème : l’optimisation de l’économie implique de maximiser les échanges économiques, quels qu’ils soient. De maximiser le marketing, aussi intrusif, aussi absurde, aussi dommageable soit-il. D’exploiter les faiblesses humaines pour soutirer un maximum d’argent, pour générer un maximum de consommation et donc de pollution.

La pollution de l’environnement, la pollution de l’air, la pollution mentale permanente ne sont que les facettes d’une seule et même cause : la maximisation politique des échanges économiques. Jusqu’à en crever.

Nous achetons des bouteilles en plastique remplies de sucres morbides à consommer en attendant le énième message qui fera sonner notre smartphone. Un message qui, la plupart du temps, nous poussera à consommer ou justifiera l’argent que nous recevons mensuellement pour continuer à consommer. Sans message, nous serons réduits à rafraichir compulsivement l’écran, espérant une nouvelle info, quelque chose de croustillant. N’importe quoi. La mort d’un animateur télévision de notre enfance, par exemple, histoire de se taper plusieurs heures de vidéos postées sur YouTube.

Le fait que j’aie en partie replongé me démontre à quel point la connexion est une drogue. Une addiction savamment entretenue, un danger permanent pour les addicts comme je le suis.

Chaque connexion est jouissive. C’est une bouffée de plaisir bien méritée, un repos intellectuel. Je peux compulsivement consommer, cliquer sans penser. Le simple fait d’utiliser la souris, de multiples onglets ouverts sur des images ou des vidéos permet de ralentir l’esprit tout en donnant une fausse sensation de contrôle, de puissance.

La problématique touche d’ailleurs depuis longtemps le monde professionnel. Comme le raconte Cal Newport dans son livre « A world without email », la plupart des métiers se résument désormais à répondre à ses emails, ses coups de téléphone, le tout en participant à des réunions. L’échange est permanent et a été largement aggravé par l’apparition des messageries professionnelles comme Slack.

Le monde professionnel n’a plus le loisir de penser. Les décisions sont prises sans recul et acceptées sur base du simple charisme d’un manager. Ce n’est pas un hasard. Penser est dangereux. Penser remets en question. Penser fait de vous un paria.

Les élections en France m’ont donné envie de politique, de débat. Alors j’ai lu « Son Excellence Eugène Rougon », de Zola. En version papier. Je me suis remis à penser. J’ai retrouvé la motivation de reprendre le combat. Un combat contre mon addiction. Un combat contre toute la société qui m’entoure. Un combat contre moi-même.

Recevez les billets par mail ou par RSS. Max 2 billets par semaine, rien d’autre. Adresse email jamais partagée et définitivement effacée lors du désabonnement. Dernier livre paru : Printeurs, thriller cyberpunk. Pour soutenir l’auteur, lisez, offrez et partagez des livres.

Ce texte est publié sous la licence CC-By BE.

June 22, 2022

I published the following diary on “Malicious PowerShell Targeting Cryptocurrency Browser Extensions“:

While hunting, I found an interesting PowerShell script. After a quick check, my first conclusion was that it is again a simple info stealer. After reading the code more carefully, the conclusion was different: It targets crypto-currency browser apps or extensions. The script has a very low score on VT: 1/53… [Read more]

The post [SANS ISC] Malicious PowerShell Targeting Cryptocurrency Browser Extensions appeared first on /dev/random.

June 16, 2022

I published the following diary on “Houdini is Back Delivered Through a JavaScript Dropper“:

Houdini is a very old RAT that was discovered years ago. The first mention I found back is from 2013! Houdini is a simple remote access tool written in Visual Basic Script. The script is not very interesting because it is non-obfuscated and has just been adapted to use a new C2 server… [Read more]

The post [SANS ISC] Houdini is Back Delivered Through a JavaScript Dropper appeared first on /dev/random.

June 14, 2022

If you want to receive Bluetooth Low Energy sensor measurements, there's a new project you can use: Theengs Gateway. It uses Theengs Decoder, an efficient, portable and lightweight C++ library for BLE payload decoding, and it publishes the decoded data as MQTT messages. It already supports 40 BLE devices, including RuuviTags, iBeacons, and various Xiaomi devices.

Recently Mihai Ambrosie created a Theengs Gateway add-on for Home Assistant, so you can install it easily. The installation process goes like this:

  • Click on Settings / Add-ons in Home Assistant and then Add-on Store at the bottom right. Click on the three dots at the top right and then Repositories.

  • Enter the url and click on Add. Click on Close after the repository has been added.

  • Click on TheengsGateway in the list of add-ons and then Install.

After the installation is complete, open the Configuration tab of the add-on and enter the host and port of your MQTT broker and optionally a username and password. 1 You can also change some parameters such as the base of the MQTT topics, the scan duration and the time between scans, and a filter for devices that you don't want to be discovered by Home Assistant because they're too numerous. 2


Click on Save to save the configuration and then click on Start in the Info tab to start the add-on. After this, all BLE devices that Theengs Gateway detects are automatically discovered by Home Assistant, and you can find them in Settings / Devices & Services. Look at the Devices and Entities tabs:


If you don't have an MQTT broker yet, install the Mosquitto add-on in Home Assistant.


By default, iBeacons, Google/Apple Exposure Notifications (GAEN), and Microsoft Advertising Beacons (advertised by Windows devices) are filtered.

June 13, 2022

Reinventing rendering one shader at a time

Cover Image - Burrito

The other day I ran into a perfect example of exactly why GPU programming is so foreign and weird. In this post I will explain why, because it's a microcosm of the issues that lead me to build Use.GPU, a WebGPU rendering meta-framework.

What's particularly fun about this post is that I'm pretty sure some seasoned GPU programmers will consider it pure heresy. Not all though. That's how I know it's good.

GLTF Damaged Helmet

GLTF model, rendered with Use.GPU GLTF

A Big Blob of Code

The problem I ran into was pretty standard. I have an image at size WxH, and I need to make a stack of smaller copies, each half the size of the previous (aka MIP maps). This sort of thing is what GPUs were explicitly designed to do, so you'd think it would be straight-forward.

Downscaling an image by a factor of 2

If this was on a CPU, then likely you would just make a function downScaleImageBy2 of type Image => Image. Starting from the initial Image, you apply the function repeatedly, until you end up with just a 1x1 size image:

let makeMips = (image: Image, n: number) => {
  let images: Image[] = [image];
  for (let i = 1; i < n; ++i) {
    image = downScaleImageBy2(image);
  return images;

On a GPU, e.g. WebGPU in TypeScript, it's a lot more involved. Something big and ugly like this... feel free to scroll past:

// Uses:
// - device: GPUDevice
// - format: GPUTextureFormat (BGRA or RGBA)
// - texture: GPUTexture (the original image + initially blank MIPs)

// A vertex and pixel shader for rendering vanilla 2D geometry with a texture
let MIP_SHADER = `
  struct VertexOutput {
    @builtin(position) position: vec4<f32>,
    @location(0) uv: vec2<f32>,

  fn vertexMain(
    @location(0) uv: vec2<f32>,
  ) -> VertexOutput {
    return VertexOutput(
      vec4<f32>(uv * 2.0 - 1.0, 0.5, 1.0),

  @group(0) @binding(0) var mipTexture: texture_2d<f32>;
  @group(0) @binding(1) var mipSampler: sampler;

  fn fragmentMain(
    @location(0) uv: vec2<f32>,
  ) -> @location(0) vec4<f32> {
    return textureSample(mipTexture, mipSampler, uv);

// Compile the shader and set up the vertex/fragment entry points
let module = device.createShaderModule(MIP_SHADER);
let vertex = {module, entryPoint: 'vertexMain'};
let fragment = {module, entryPoint: 'fragmentMain'};

// Create a mesh with a rectangle
let mesh = makeMipMesh(size);

// Upload it to the GPU
let vertexBuffer = makeVertexBuffer(device, mesh.vertices);

// Make a texture view for each MIP level
let views = seq(mips).map((mip: number) => makeTextureView(texture, 1, mip));

// Make a texture sampler that will interpolate colors
let sampler = makeSampler(device, {
  minFilter: 'linear',
  magFilter: 'linear',

// Make a render pass descriptor for each MIP level, with the MIP as the drawing buffer
let renderPassDescriptors = seq(mips).map(i => ({
  colorAttachments: [makeColorAttachment(views[i], null, [0, 0, 0, 0], 'load')],
} as GPURenderPassDescriptor));

// Set the right color format for the color attachment(s)
let colorStates = [makeColorState(format)];

// Make a rendering pipeline for drawing a strip of triangles
let pipeline = makeRenderPipeline(device, vertex, fragment, colorStates, undefined, 1, {
  primitive: {
    topology: "triangle-strip",
  vertex:   {buffers: mesh.attributes},
  fragment: {},

// Make a bind group for each MIP as the texture input
let bindGroups = seq(mips).map((mip: number) => makeTextureBinding(device, pipeline, sampler, views[mip]));

// Create a command encoder
let commandEncoder = device.createCommandEncoder();

// For loop - Mip levels
for (let i = 1; i < mips; ++i) {

  // Begin a new render pass
  let passEncoder = commandEncoder.beginRenderPass(renderPassDescriptors[i]);
  // Bind render pipeline

  // Bind previous MIP level
  passEncoder.setBindGroup(0, bindGroups[i - 1]);

  // Bind geometry
  passEncoder.setVertexBuffer(0, vertexBuffer);

  // Actually draw 1 MIP level
  passEncoder.draw(mesh.count, 1, 0, 0);

  // Finish

// Send to GPU

The most important thing to notice is that it has a for loop just like the CPU version, near the end. But before, during, and after, there is an enormous amount of set up required.

For people learning GPU programming, this by itself represents a challenge. There's not just jargon, but tons of different concepts (pipelines, buffers, textures, samplers, ...). All are required and must be hooked up correctly to do something that the GPU should treat as a walk in the park.

That's just the initial hurdle, and by far not the worst one.

Use.GPU Plot

Use.GPU Plot aka MathBox 3

The Big Lie

You see, no real application would want to have the code above. Because every time this code runs, it would do all the set-up entirely from scratch. If you actually want to do this practically, you would need to rewrite it to add lots of caching. The shader stays the same every time for example, so you want to create it once and then re-use it. The shader also uses relative coordinates 0...1, so you can use the same geometry even if the image is a different size.

Other parts are less obvious. For example, the render pipeline and all the associated colorState depend entirely on the color format: RGBA or BGRA. If you need to handle both, you would need to cache two versions of everything. Do you need to?

The data dependencies are quite subtle. Some parts depend only on the data type (i.e. format), while other parts depend on an actual data value (i.e. the contents of texture)... but usually both are aspects of one and the same object, so it's very difficult to effectively separate them. Some dependencies are transitive: we have to create an array of views to access the different sizes of the texture (image), but then several other things depend on views, such as the colorAttachments (inside pipeline) and the bindGroups.

There is one additional catch. Everything you do with the GPU happens via a device context. It's entirely possible for that context to be dropped by the browser/OS. In that case, it's your responsibility to start anew, recreating every single resource you used. This is btw the API design equivalent of a pure dick move. So whatever caching solution you come up with, it cannot be fire-and-forget: you need to invalidate and refresh too. And we all know how hard that is.

This is what all GPU rendering code is like. You don't spend most of your time doing the work, you spend most of your time orchestrating for the work to happen. What's amazing is that it means every GPU API guide is basically a big book of lies, because it glosses over these problems entirely. It's just assumed that you will intuit automatically how it should actually be used, even though it actually takes weeks, months, years of trying. You need to be intimately familiar with the whys in order to understand the how.

One can only conclude that the people making the APIs rarely, if ever, talk to the people using the APIs. Like backend and frontend web developers, the backend side seems blissfully unaware of just how hairy things get when you actually have to let people interact with your software instead of just other software. Instead, you get lots of esoteric features and flags that are never used except in the rarest of circumstances.

Few people in the scene really think any of this is a problem. This is just how it is. The art of creating a GPU renderer is to carefully and lovingly choose every aspect of your particular solution, so that you can come up with a workable answer to all of the above. What formats do you handle, and which do you not? Do all meshes have the same attributes or not? Do you try to shoehorn everything through one uber-pipeline/shader, or do you have many? If so, do you create them by hand, or do you use code generation to automate it? Also, where do you keep the caches? And who owns them?

It shouldn't be a surprise that the resulting solutions are highly bespoke. Each has its own opinionated design decisions and quirks. Adopting one means buying into all of its assumptions wholesale. You can only really swap out two renderers if they are designed to render exactly the same kind of thing. Even then, upgrading e.g. from Unreal Engine 4 to 5 is the kind of migration only a consultant can love.

This goes a very long way towards explaining the problem, but it doesn't actually explain the why.

Use.GPU Picking

Use.GPU has first class GPU picking support.

Memory vs Compute

There is a very different angle you can approach this from.

GPUs are, essentially, massively parallel pure function applicators. You would expect that functional programming would be a huge influence. Except it's the complete opposite: pretty much all the established practices derive from C/C++ land, where the men are men, state is mutable and the pointers are unsafe. To understand why, you need to face the thing that FP is usually pretty bad at: dealing with the performance implications of its supposedly beautiful abstractions.

Let's go back to the CPU model, where we had a function Image => Image. The FP way is to compose it, threading together a chain of Image → Image → .... → Image. This acts as a new function Image => Image. The surrounding code does not have to care, and can't even notice the difference. Yay FP.

Making an image gray scale, and then increasing the contrast

But suppose you have a function that makes an image grayscale, and another function that increases the contrast. In that case, their composition Image => Image + Image => Image makes an extra intermediate image, not just the result, so it uses twice as much memory bandwidth. On a GPU, this is the main bottleneck, not computation. A fused function Image => Image that does both things at the same time is typically twice as efficient.

The usual way we make code composable is to split it up and make it pass bits of data around. As this is exactly what you're not supposed to do on a GPU, it's understandable that the entire field just feels like bizarro land.

It's also trickier in practice. A grayscale or contrast adjustment is a simple 1-to-1 mapping of input pixels to output pixels, so the more you fuse operations, the better. But the memory vs compute trade-off isn't always so obvious. A classic example is a 2D blur filter, which reads NxN input pixels for every output pixel. Here, instead of applying a single 2D blur, you should do a separate 1D Nx1 horizontal blur, save the result, and then do a 1D 1xN vertical blur. This uses less bandwidth in total.

But this has huge consequences. It means that if you wish to chain e.g. Grayscale → Blur → Contrast, then it should ideally be split right in the middle of the two blur passes:

Grayscale + Blur X → Blur Y + Contrast

Image → (Grayscale + Horizontal Blur) → Memory → (Vertical Blur + Contrast) → ...

In other words, you have to slice your code along invisible internal boundaries, not along obvious external ones. Plus, this will involve all the same bureaucratic descriptor nonsense you saw above. This means that a piece of code that normally would just call a function Image => Image may end up having to orchestrate several calls instead. It must allocate a place to store all the intermediate results, and must manually wire up the relevant save-to-storage and load-from-storage glue on both sides of every gap. Exactly like the big blob of code above.

When you let C-flavored programmers loose on these constraints, it shouldn't be a surprise that they end up building massively complex, fused machines. They only pass data around when they actually have to, in highly packed and compressed form. It also shouldn't be a surprise that few people beside the original developers really understand all the details of it, or how to best make use of it.

There was and is a massive incentive for all this too, in the form of AAA gaming. Gaming companies have competed fiercely under notoriously harsh working conditions, mostly over marginal improvements in rendering quality. The progress has been steady, creeping ever closer to photorealism, but it comes at the enormous human cost of having to maintain code that pretty much becomes unmaintainable by design as soon as it hits the real world.

This is an important realization that I had a long time ago. That's because composing Image => Image is basically how Winamp's AVS visualizer worked, which allowed for fully user-composed visuals. This was at a time when CPUs were highly compute-constrained. In those days, it made perfect sense to do it this way. But it was also clear to anyone who tried to port this model to GPU that it would be slow and inefficient there. Ever since then, I have been exploring how to do serious fused composition for GPU rendering, while retaining full end-user control over it.


Use.GPU Render-To-Texture, aka Milkdrop / AVS (except in Float16 Linear RGB)


Functional programmers aren't dumb, so they have their own solutions for this. It's much easier to fuse things together when you don't try to do it midstream.

For example, monadic IO. In that case, you don't compose functions Image => Image. Rather, you compose a list of all the operations to apply to an image, without actually doing them yet. You just gather them all up, so you can come up with an efficient execution strategy for the whole thing at the end, in one place.

This principle can be applied to shaders, which are pure functions. You know that the composition of function A => B and B => C is of type A => C, which is all you need to know to allow for further composition: you don't need to actually compose them yet. You can also use functions as arguments to other shaders. Instead of a value T, you pass a function (...) => T, which a shader calls in a pre-determined place. The result is a tree of shader code, starting from some main(), which can be linked into a single program.

To enable this, I defined some custom @attributes in WGSL which my shader linker understands:

@optional @link fn getTexture(uv: vec2<f32>) -> vec4<f32> { return vec4<f32>(1.0, 1.0, 1.0, 1.0); };

@export fn getTextureFragment(color: vec4<f32>, uv: vec2<f32>) -> vec4<f32> {
  return color * getTexture(uv);

The function getTextureFragment will apply a texture to an existing color, using uv as the texture coordinates. The function getTexture is virtual: it can be linked to another function, which actually fetches the texture color. But the texture could be entirely procedural, and it's also entirely optional: by default it will return a constant white color, i.e. a no-op.

It's important here that the functions act as real closures rather than just strings, with the associated data included. The goal is to not just to compose the shader code, but to compose all the orchestration code too. When I bind an actual texture to getTexture, the code will contain a texture binding, like so:

@group(...) @binding(...) var mipTexture: texture_2d<f32>;
@group(...) @binding(...) var mipSampler: sampler;

fn getTexture(uv: vec2<f32>) -> vec4<f32> {
  return textureSample(mipTexture, mipSampler, uv);

When I go to draw anything that contains this piece of shader code, the texture should travel along, so it can have its bindings auto-generated, along with any other bindings in the shader.

That way, when our blur filter from earlier is assigned an input, that just means linking it to a function getTexture. That input could be a simple image, or it could be another filter being fused with. Similarly, the output of the blur filter can be piped directly to the screen, or it could be passed on to be fused with other shader code.

What's really neat is that once you have something like this, you can start taking over some of the work the GPU driver itself is doing today. Drivers already massage your shaders, because much of what used to be fixed-function hardware is now implemented on general purpose GPU cores. If you keep doing it the old way, you remain dependent on whatever a GPU maker decides should be convenient. If you have a monad-ish shader pipeline instead, you can do this yourself. You can add support for a new packed data type by polyfilling in the appropriate encoder/decoder code yourself automatically.

This is basically the story of how web developers managed to force browsers to evolve, even though they were monolithic and highly resistant to change. So I think it's a very neat trick to deploy on GPU makers.

There is of course an elephant in this particular room. If you know GPUs, the implication here is that every call you make can have its own unique shader... and that these shaders can even change arbitrarily at run-time for the same object. Compiling and linking code is not exactly fast... so how can this be made performant?

There are a few ingredients necessary to make this work.

The easy one is, as much as possible, pre-parse your shaders. I use a webpack plug-in for this, so that I can include symbols directly from .wgsl in TypeScript:

import { getFaceVertex } from '@use-gpu/wgsl/instance/vertex/face.wgsl';

A less obvious one is that if you do shader composition using source code, it's actually far less work than trying to compose byte code, because it comes down to controlled string concatenation and replacement. If guided by a proper grammar and parse tree, this is entirely sound, but can be performed using a single linear scan through a highly condensed and flattened version of the syntax tree.

This also makes perfect sense to me: byte code is "back end", it's designed for optimal consumption by a run-time made by compiler engineers. Source code is "front end", it's designed to be produced and typed by humans, who argue over convenience and clarity first and foremost. It's no surprise which format is more bureaucratic and which allows for free-form composition.

The final trick I deployed is a system of structural hashing. As we saw before, sometimes code depends on a value, sometimes it only depends on a value's type. A structural hash is a hash that only considers the types, not the values. This means if you draw the same kind of object twice, but with different parameters, they will still have the same structural hash. So you know they can use the exact same shader and pipeline, just with different values bound to it.

In other words, structural hashing of shaders allows you to do automatically what most GPU programmers orchestrate entirely by hand, except it works for any combination of shaders produced at run-time.

The best part is that you don't need to produce the final shader in order to know its hash: you can hash along the way as you build the monadic data structure. Even before you actually start linking it, you can know if you already have the result. This also means you can gather all the produced shaders from a program by running it, and then bake them to a more optimized form for production. It's a shame WebGPU has no non-text option for loading shaders then...

Use the GPU

If you're still following along, there is really only one unanswered question: where do you cache?

Going back to our original big blob of code, we observed that each part had unique data and type dependencies, which were difficult to reason about. Given rare enough circumstances, pretty much all of them could change in unpredictable ways. Covering all bases seems both impractical and insurmountable.

It turns out this is 100% wrong. Covering all bases in every possible way is not only practical, it's eminently doable.

Consider some code that calls some kind of constructor:

let foo = makeFoo(bar);

If you set aside all concerns and simply wish for a caching pony, then likely it sounds something like this: "When this line of code runs, and bar has been used before, it should return the same foo as before."

The problem with this wish is that this line of code has zero context to make such a decision. For example, if you only remember the last bar, then simply calling makeFoo(bar1) makeFoo(bar2) will cause the cache to be trashed every time. You cannot simply pick an arbitrary N of values to keep: if you pick a large N, you hold on to lots of irrelevant data just in case, but if you pick a small N, your caches can become worse than useless.

In a traditional heap/stack based program, there simply isn't any obvious place to store such a cache, or to track how many pieces of code are using it. Values on the stack only exist as long as the function is running: as soon as it returns, the stack space is freed. Hence people come up with various ResourceManagers and HandlePools instead to track that data in.

The problem is really that you have no way of identifying or distinguishing one particular makeFoo call from another. The only thing that identifies it, is its place in the call stack. So really, what you are wishing for is a stack that isn't ephemeral but permanent. That if this line of code is run in the exact same run-time context as before, that it could somehow restore the previous state on the stack, and pick up where it left off. But this would also have to apply to the function that this line of code sits in, and the one above that, and so on.

Storing a copy of every single stack frame after a function is done seems like an insane, impractical idea, certainly for interactive programs, because the program can go on indefinitely. But there is in fact a way to make it work: you have to make sure your application has a completely finite execution trace. Even if it's interactive. That means you have to structure your application as a fully rewindable, one-way data flow. It's essentially an Immediate Mode UI, except with memoization everywhere, so it can selectively re-run only parts of itself to adapt to changes.

For this, I use two ingredients:
- React-like hooks, which gives you permanent stack frames with battle-hardened API and tooling
- a Map-Reduce system on top, which allows for data and control flow to be returned back to parents, after children are done

What hooks let you do is to turn constructors like makeFoo into:

let foo = useFoo(bar, [...dependencies]);

The use prefix signifies memoization in a permanent stack frame, and this is conditional on ...dependencies not changing (using pointer equality). So you explicitly declare the dependencies everywhere. This seems like it would be tedious, but I find actually helps you reason about your program. And given that you pretty much stop writing code that isn't a constructor, you actually have plenty of time for this.

The map-reduce system is a bit trickier to explain. One way to think of it is like an async/await:

async () => {
  // ...
  let foo = await fetch(...);
  // ...

Imagine for example if fetch() didn't just do an HTTP request, but actually subscribed and kept streaming in updated results. In that case, it would need to act like a promise that can resolve multiple times, without being re-fetched. The program would need to re-run the part after the await, without re-running the code before it.

Neither promises nor generators can do this, so I implement it similar to how promises were first implemented, with the equivalent of a .then(...):

() => {
   // ...
   return gather(..., (foo) => {

When you isolate the second half inside a plain old function, the run-time can call it as much as it likes, with any prior state captured as part of the normal JS closure mechanism. Obviously it would be neater if there was syntactic sugar for this, but it most certainly isn't terrible. Here, gather functions like the resumable equivalent of a Promise.all.

What it means is that you can actually write GPU code like the API guides pretend you can: simply by creating all the necessary resources as you need them, top to bottom, with no explicit work to juggle the caches, other than listing dependencies. Instead of bulky OO classes wrapping every single noun and verb, you write plain old functions, which mainly construct things.

In JS there is the added benefit of having a garbage collector to do the destructing, but crucially, this is not a hard requirement. React-like hooks make it easy to wrap imperative, non-reactive code, while still guaranteeing clean up is always run correctly: you can pass along the code to destroy an object or handle in the same place you construct it.

It really works. It has made me over 10x more productive in doing anything GPU-related, and I've done this in C++ and Rust before. It makes me excited to go try some new wild vertex/fragment shader combo, instead of dreading all the tedium in setting it up and not missing a spot. What's more, all the extra performance hacks and optimizations that I would have to add by hand, it can auto-insert, without me ever thinking about it. WGSL doesn't support 8-bit storage buffers and only has 32-bit? Well, my version does. I can pass a Uint8Array as a vec<u8> and not think about it.

The big blob of code in this post is all real, with only some details omitted for pedagogical clarity. I wrote it the other day as a test: I wanted to see if writing vanilla WebGPU was maybe still worth it for this case, instead of leveraging the compositional abstractions that I built. The answer was a resounding no: right away I ran into the problem that I had no place to cache things, and the solution would be to come up with yet another ad-hoc variant of the exact same thing the run-time already does.

Once again, I reach the same conclusion: the secret to cache invalidation is no mystery. A cache is impossible to clear correctly when a cache does not track its dependencies. When it does, it becomes trivial. And the best place to cache small things is in a permanent stack frame, associated with a particular run-time call site. You can still have bigger, more application-wide caches layered around that... but the keys you use to access global caches should generally come from local ones, which know best.

All you have to do is completely change the way you think about your code, and then you can make all the pretty pictures you want. I know it sounds facetious but it's true, and the code works. Now it's just waiting for WebGPU to become accessible without developer flags.

Veterans of GPU programming will likely scoff at a single-threaded run-time in a dynamic language, which I can somewhat understand. My excuse is very straightforward: I'm not crazy enough to try and build this multi-threaded from day 1, in a static language where every single I has to be dotted, and every T has to be crossed. Given that the run-time behaves like an async incremental data flow, there are few shady shortcuts I can take anyway... but the ability to leverage the any type means I can yolo in the few places I really want to. A native version could probably improve on this, but whether you can shoehorn it into e.g. Rust's type and ownership system is another matter entirely. I leave that to other people who have the appetite for it.

The idea of a "bespoke shader for every draw call" also doesn't prevent you from aggregating them into batches. That's how Use.GPU's 2D layout system works: it takes all the emitted shapes, and groups them into unique layers, so that shapes with the same kind of properties (i.e. archetype) are all batched together into one big buffer... but only if the z-layering allows for it. Similar to the shader system itself, the UI system assumes every component could be a special snowflake, even if it usually isn't. The result is something that works like dear-imgui, without its obvious limitations, while still performing spectacularly frame-to-frame.

Use.GPU Layout

Use.GPU Layout - aka HTML/CSS

For an encore, it's not just a box model, but the box model, meaning it replicates a sizable subset of HTML/CSS with pixel-perfect precision and perfectly smooth scaling. It just has a far more sensible and memorable naming scheme, and it excludes a bunch of things nobody needs. Seeing as I have over 20 years of experience making web things, I dare say you can trust I have made some sensible decisions here. Certainly more sensible than W3C on a good day, amirite?

* * *

Use.GPU is not "finished" yet, because there are still a few more things I wish to make composable; this is why only the shader compiler is currently on NPM. However, given that Use.GPU is a fully "user space" framework, where all the "native" functionality sits on an equal level with custom code, this is a matter of degree. The "kernel" has been ready for half a year.

One such missing feature is derived render passes, which are needed to make order-independent transparency pleasant to use, or to enable deferred lighting. I have consistently waited to build abstractions until I have a solid set of use cases for it, and a clear idea of how to do it right. Not doing so is how we got into this mess into the first place: with ill-conceived extensions, which often needlessly complicate the base case, and which nobody has really verified if it's actually what devs need.

In this, I can throw shade at both GPU land and Web land. Certain Web APIs like WebAudio are laughably inadequate, never tested on anything more than toys, and seemingly developed without studying what existing precedents do. This is a pitfall I have hopefully avoided. I am well aware of how a typical 3D renderer is structured, and I am well read on the state of the art. I just think it's horribly inaccessible, needlessly obtuse, and in high need of reinventing.

The code is on Gitlab. If you want to play around with it, or just shoot holes in it, please, be my guest. It comes with a dozen or so demo examples. It also has a sweet, fully reactive inspector tool, shown in the video above at ~1:30, so you don't even need to dig into the code to watch it work.

There will of course be bugs, but at least they will be novel ones... and so far, a lot fewer than usual.

↑ Leica M10-R

I have over 10,000 photos on my website. All these photos are managed by a custom Drupal module. I wrote the first version of that module over 15 years ago, and continue to work on it from time to time. Like this weekend, when I added a new feature.

Digital photos have EXIF data embedded in them. EXIF data includes information such as camera model, lens, aperture, shutter speed, focal length, ISO, and much more.

My module now extracts the EXIF data from my photos and stores it in a database. Having all my EXIF metadata in a database allows me to analyze my photography history.

For example, over the years, I've owned 11 different cameras and 10 different lenses:

SELECT COUNT(DISTINCT(camera)) AS count FROM images; 
| count |
|    11 |

SELECT COUNT(DISTINCT(lens)) AS count FROM images;  
| count |
|    10 |

Here is a SQL query that shows all cameras I have owned in the last 22 years, and the timeframe I used them for.

SELECT camera, MIN(DATE(date)) AS first, MAX(DATE(date)) AS last, TIMESTAMPDIFF(YEAR, MIN(date), MAX(date)) AS years FROM images GROUP BY camera ORDER BY first; 
| camera              | first      | last       | years |
| Sony Cybershot      | 2000-01-01 | 2003-08-01 |     3 |
| Nikon Coolpix 885   | 2001-11-13 | 2004-04-11 |     2 |
| Nikon D70           | 2004-04-03 | 2006-11-19 |     2 |
| Nikon D200          | 2006-12-31 | 2012-06-17 |     5 |
| Panasonic Lumix GF1 | 2011-10-11 | 2014-10-26 |     3 |
| Nikon D4            | 2012-07-01 | 2018-08-26 |     6 |
| Sony Alpha 7 II     | 2015-02-25 | 2019-01-09 |     3 |
| DJI Mavic Pro       | 2017-07-23 | 2019-01-18 |     1 |
| Nikon D850          | 2019-03-16 | 2021-04-24 |     2 |
| Nikon Z 7           | 2019-04-07 | 2021-08-31 |     2 |
| Leica M10-R         | 2021-11-18 | 2022-06-09 |     0 |

Finally, here is a chart that visualizes my camera history:

Chart that shows my cameras and when I used them
The timeframe I used each camera for. The white numbers on the blue bars represent the number of photos I published on my website.

A few takeaways:

  • I used my Nikon D4 for 6 years and my Nikon D200 for 5 years. On average, I use a camera for 3.3 years.
  • I should dust of my drone (DJI Mavic Pro) as I haven't used it since early 2019.
  • In 2019, I bought a Nikon D850 and a Nikon Z 7. I liked the Nikon Z 7 better, and didn't use my Nikon D850 much.
  • Since the end of 2021, I've been exclusively using my Leica.

I shared this with my family but they weren't impressed. Blank stares ensued, and the conversation took a quick turn. While I could go on and share more statistics, I'll take a hint from my family, and stop here.

June 12, 2022

This week my new book has been published, Develop your own Bluetooth Low Energy Applications for Raspberry Pi, ESP32 and nRF52 with Python, Arduino and Zephyr.

Bluetooth Low Energy (BLE) is one of the most accessible wireless communication standards. You don't need any expensive equipment to develop BLE devices such as wireless sensor boards, proximity beacons, or heart rate monitors. All you need is a computer or a Raspberry Pi, an ESP32 microcontroller board, or a development board with a Nordic Semiconductor nRF5 (or an equivalent BLE SoC from another manufacturer).

On the software side, BLE is similarly accessible. Many development platforms, most of them open source, offer an API (application programming interface) to assist you in developing your own BLE applications. This book shows you the ropes of Bluetooth Low Energy programming with Python and the Bleak library on a Raspberry Pi or PC, with C++ and NimBLE-Arduino on Espressif's ESP32 development boards, and with C on one of the development boards supported by the Zephyr real-time operating system, such as Nordic Semiconductor's nRF52 boards.

While Bluetooth Low Energy is a complex technology with a comprehensive specification, getting started with the basics is relatively easy. This book takes a practical approach to BLE programming to make the technology even more approachable. With a minimal amount of theory, you'll develop code right from the start. After you've completed this book, you'll know enough to create your own BLE applications.

What is Bluetooth Low Energy?

Bluetooth is a wireless communication standard in the 2.4 GHz Industrial, Scientific, and Medical (ISM) frequency band. These days, if you hear about Bluetooth support in a product, this almost always is Bluetooth Low Energy (BLE). It's a radical departure from the original Bluetooth standard, which is now called Classic Bluetooth.

Bluetooth Low Energy and Classic Bluetooth are actually different protocols. Classic Bluetooth is essentially a wireless version of the traditional serial connection. If you want to print a document, transfer a file or stream audio, you want this to happen as fast as possible. Therefore, the focus of development in Classic Bluetooth was on attaining faster and faster speeds with every new version.

However, Classic Bluetooth wasn't a good fit for devices with low power consumption, for instance those powered by batteries. That's why Nokia adapted the Bluetooth standard to enable it to work in low-power scenarios. In 2006, they released their resulting technology onto the market, dubbed Wibree.

The Bluetooth Special Interest Group (SIG), the organization that maintains the Bluetooth specifications, showed interest in this new development. After consulting with Nokia, they decided to adopt Wibree as part of Bluetooth 4.0, with a new name, Bluetooth Low Energy. Classic Bluetooth remained available for high-throughput applications.


In practice, many chipsets support both Classic Bluetooth and Low Energy, especially in laptops and smartphones.

Layered architecture

The Bluetooth Core Specification is more than 3200 pages long. And this is only the core specification; there are many supplemental documents for BLE. However, BLE has a layered architecture. Many end-user applications only use the upper layers, so you don't need to know the details of the architecture's lower layers.


The BLE architecture consists of three main blocks: controller, host, and application.


This has the lower-level layers: the Physical Layer (PHY), Link Layer (LL) and Direct Test Mode (DTM). These are the layers where the Bluetooth radio does its work. The controller communicates with the outside world using the antenna, in a frequency band around 2.4 GHz. It communicates with the host using a standardized interface between the two blocks: the Host Controller Interface (HCI). 1


This is the block with which the end user or application developer comes in contact. The Logical Link Control and Adaptation Protocol (L2CAP) defines channels and signaling commands. On top of it, the Security Manager Protocol (SMP) handles secure connections (with authentication and encryption), and the Attribute Protocol (ATT) defines how to expose and access data as attributes. The Generic Attribute Profile (GATT) 2 builds on the Attribute Protocol to define how to discover services and their characteristics and how to read and write their values. The upper layer of the Host block is the Generic Access Profile (GAP), which defines how devices can discover other devices and connect, pair, and bond to them. The host communicates with the controller using its part of the host controller interface, and applications communicate with the host depending on the APIs exposed by the operating system.


This layer builds on top of the Generic Attribute Profile to implement application-specific characteristics, services, and profiles. A characteristic defines a specific type of data, such as an Alert Level. A service defines a set of characteristics and their behaviors, such as the Link Loss Service. A profile is a specification that describes how two or more devices with one or more services communicate with each other. An example is the Proximity profile, which has two roles: Proximity Monitor and Proximity Reporter.

The three blocks don't have to run on the same processor. In fact, there are three common configurations --- one single-chip and two dual-chip:

Single-chip (SoC)

Controller, host and application code run on the same chip. The host and controller communicate through function calls and queues in the chip's RAM. Most simple devices such as BLE sensors use this configuration; it keeps the cost down. Some smartphones also use this configuration if they have a SoC with Bluetooth built in.

Dual-chip over HCI

A dual-chip solution with application and host on one chip, and the controller on another chip, communicates over HCI. Because HCI is a standardized interface, it lets you combine different platforms. For instance, on a Raspberry Pi, the Wi-Fi and BLE chip implements a BLE controller. If you connect a BLE dongle to an older Raspberry Pi, this dongle also implements a BLE controller. 3 BlueZ, the Raspberry Pi Linux kernel's Bluetooth stack, implements a BLE host. So BlueZ communicates with the BLE controller in the built-in BLE chip or the BLE dongle. In the former case, the HCI uses SDIO, and in the latter, UART over USB. 4 Many smartphones and tablets also use the dual-chip over HCI configuration, with a powerful processor running the host and a Bluetooth chip running the controller.

Dual-chip with connectivity device

Another dual-chip solution is one with the application running on one chip and the host and controller on another chip. The latter is then called the connectivity device because it adds BLE connectivity to the other device. This approach is useful if you have an existing hardware device that you want to extend with BLE connectivity. Because there's no standardized interface in this case, the communication between the application processor and the connectivity device needs to make use of a proprietary protocol implemented by the connectivity device.

A three-chip solution with controller, host, and application each running on its own chip is also possible. However, because of the associated cost, this is typically only done for development systems.

How to communicate with BLE devices?

Bluetooth Low Energy has two ways to communicate between devices: with and without a connection.

Without a connection

Without a connection means that the device just broadcasts information in an advertisement. Every BLE device in the neighborhood is able to receive this information.


Some examples of BLE devices broadcasting data are:

Proximity beacons

These devices, often following Apple's iBeacon standard, broadcast their ID. Receivers calculate their approximate distance to the beacons based on the advertisement's Received Signal Strength Indicator (RSSI).


Many temperature and humidity sensors broadcast their sensor values. Most devices do this in an unencrypted fashion, but some of them encrypt the data to prevent it being read by every device in the neighborhood.

Mobile phones

After the COVID-19 pandemic started in 2020, Google and Apple collaborated on the Exposure Notifications standard for contact tracing. As part of this technology, Android phones and iPhones broadcast unique (but anonymous) numbers. Other phones can pick up these numbers and use them later to warn users that they have been in contact with someone who is known to have had COVID-19.

With a connection

The other way to communicate between BLE devices is with a connection. One device (the client) scans for BLE advertisements to find the device it wants to connect to. Then, optionally, it may do an active scan to ask the device (the server) which services are offered.

After the client connects to the server, the client can use the server's services. Each BLE service is a container of specific data from the server. You can read this data, or (with some services) write a value to the server.


Some examples of BLE devices using a connection are:

Fitness trackers

Your smartphone can connect to a fitness tracker and read your heart rate, the tracker's battery level, and other measurements.


Some environmental sensors let you read their sensor values over a BLE connection.

Proximity reporters

These devices sound an alert when their connection to another device is lost.

Advantages of BLE

Low power consumption

As its name implies, Bluetooth Low Energy is optimized for low-power applications. Its whole architecture is designed to reduce power consumption. For instance, setting up a connection, reading or writing data, and disconnecting happens in a couple of milliseconds. The radio is often the most energy-consuming part of a device. Therefore, the idea is to turn on the Bluetooth radio, create a connection, read or write data, disconnect, and turn off the radio again until the next time the device has to communicate.

This way, a well-designed BLE temperature sensor is able to work on a coin cell for ten years or more. You can use the same approach with other wireless technologies, such as Wi-Fi, but they require more power and more time to set up a connection.


BLE radio chips are ubiquitous. You can find them in smartphones, tablets, and laptops. This means that all those devices can talk to your BLE sensors or lightbulbs. Most manufacturers create mobile apps to control their BLE devices.

You can also find BLE radios in many single-board computers, such as the Raspberry Pi, and in popular microcontroller platforms such as the ESP32. 5 This makes it quite easy for you to create your own gateways for BLE devices. And, platforms such as the Nordic Semiconductor nRF5 series of microcontrollers with BLE radio even make it possible to create your own battery-powered BLE devices.

Low cost

There's no cost to access the official BLE specifications. Moreover, BLE chips are cheap, and the available development boards (based on an nRF5 or ESP32) and Raspberry Pis are quite affordable. This means you can just start with BLE programming at minimal cost.

Disadvantages of BLE

Short range

BLE has a short range (for most devices, less than 10 meters) compared to other wireless networks, such as Zigbee, Z-Wave, and Thread. It's not a coincidence that these competitors all have a mesh architecture, in which devices can forward their neighbors' messages in order to improve range. Low-power wide area networks (LPWANs), such as LoRaWAN, Sigfox, and NB-IoT, have even longer ranges.

In 2017, the Bluetooth SIG added Bluetooth Mesh, a mesh protocol. This builds upon BLE's physical and link layers with a whole new stack above them. However, Bluetooth Mesh isn't as well-established as the core BLE protocol, at least not for home use.

Limited speed

The BLE radio has a limited transmission speed. For Bluetooth 4.2 and earlier, this is 1 Mbps, while for Bluetooth 5 and later, this can be up to 2 Mbps. This makes BLE unsuitable for high-bandwidth applications.

You need a gateway

Wi-Fi devices have their own IP addresses, so you can communicate with them directly from other IP-based devices, and they're integrated in your LAN (local area network). Bluetooth doesn't have this: to integrate your BLE devices with other network devices, you need a gateway. This device has to translate Bluetooth packets to IP-based protocols such as MQTT (Message Queuing Telemetry Transport). That's why many BLE device manufacturers have smartphone apps that function as device gateways. 6

Platforms used in this book

This book focuses on Bluetooth Low Energy programming on three platforms:

BLE platforms used in this book

Programming language


Software platform

Hardware platform



Windows, Linux, macOS

Raspberry Pi or PC



Arduino framework



/ 7



These choices were made in order to demonstrate a wide range of applications compatible with many software and hardware platforms.

Python/Bleak (Raspberry Pi, PC)

Python is an easy-to-use programming language that works on all major operating systems. There are a lot of Python Bluetooth Low Energy libraries, but many of them support only a single operating system. Bleak, which stands for Bluetooth Low Energy platform Agnostic Klient, is a welcome exception. It supports:

  • Windows 10, version 16299 (Fall Creators Update) or higher

  • Linux distributions with BlueZ 5.43 or higher (also on a Raspberry Pi)

  • OS X 10.11 (El Capitan) or macOS 10.12+


Bleak is a GATT client: it's able to connect to BLE devices that act as GATT servers. It supports reading, writing, and getting notifications from GATT servers, and it's also able to discover BLE devices and read advertising data broadcast by them.

Bleak doesn't implement a GATT server. In practice this isn't a big limitation. GATT servers are typically implemented on constrained devices, so, for this purpose, the ESP32 and nRF52 hardware platforms are a better match. 8

C++/NimBLE-Arduino (ESP32)

If you're looking at microcontrollers, the Arduino framework has become quite popular, not only for the original Arduino boards, which didn't have BLE functionality, but also on ESP32 development boards, which do.


Programming for the Arduino framework is done in a variant of C++, but the framework and many Arduino libraries hide much of C++'s complexity. Even if you only know some C (which is much less complex than C++), you'll be able to use the Arduino framework.

One of the more popular BLE libraries for Arduino on the ESP32 is NimBLE-Arduino. It's a fork of NimBLE, which is part of the Apache Mynewt real-time operating system. With NimBLE-Arduino, you can easily create your own GATT server or client.

C/Zephyr (nRF52)

For even more constrained devices, typically battery-powered, you need a specialized real-time operating system (RTOS). This book uses the Zephyr Project on nRF52840-based devices from Nordic Semiconductor. Zephyr has a completely open-source Bluetooth Low Energy stack.


Zephyr's BLE stack is highly configurable. You can build Zephyr firmware for three configuration types:

Combined build

Builds the BLE controller, BLE host, and your application for a one-chip configuration.

Host build

Builds the BLE host and your application, along with an HCI driver to let your device communicate with an external BLE controller on another chip. 9

Controller build

Builds the BLE controller with an HCI driver to let your device communicate with an external BLE host on another chip.

With some basic knowledge of C, you can create your own BLE devices with Zephyr, such as BLE beacons, sensor boards, and proximity reporters. Zephyr has extensive documentation of its Bluetooth API, as well as a lot of ready-to-use examples that you can build upon.

June 11, 2022

  • Receive an ODT file (OpenDocument Text Document).
  • Everyone: opens the file with either LibreOffice or even Microsoft Office nowadays, apparently.
  • Me: uses Pandoc and LaTeX to convert the file to PDF and read it in Evince because I don’t have LibreOffice installed and I’m too lazy to upload the document to Google Docs.

I needed to review an addendum to a rental contract. (I moved! I’ll write about that later.) The addendum was sent to me in ODT format. At the time, my desktop pc was still packed in a box. On my laptop (a 2011 MacBook Air with Ubuntu 20.04) I only have the most essential software installed, which for me doesn’t include an office suite. I could install LibreOffice, but why make it easy if I can also do it the hard way? 😀

I do have Evince installed, which is a lightweight PDF viewer. To convert ODT to PDF I’m using Pandoc, which is a Swiss army knife for converting document formats. For PDF it needs the help of LaTeX, a document preparation system for typesetting.

First I installed the required software:

$ sudo apt install pandoc texlive texlive-latex-extra
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libapache-pom-java libcommons-logging-java libcommons-parent-java libfontbox-java libpdfbox-java preview-latex-style texlive-base texlive-binaries
  texlive-fonts-recommended texlive-latex-base texlive-latex-recommended texlive-pictures texlive-plain-generic tipa
Suggested packages:
  libavalon-framework-java libcommons-logging-java-doc libexcalibur-logkit-java liblog4j1.2-java texlive-xetex texlive-luatex pandoc-citeproc
  context wkhtmltopdf librsvg2-bin groff ghc php python r-base-core libjs-mathjax node-katex perl-tk xzdec texlive-fonts-recommended-doc
  texlive-latex-base-doc python3-pygments icc-profiles libfile-which-perl libspreadsheet-parseexcel-perl texlive-latex-extra-doc
  texlive-latex-recommended-doc texlive-pstricks dot2tex prerex ruby-tcltk | libtcltk-ruby texlive-pictures-doc vprerex
The following NEW packages will be installed:
  libapache-pom-java libcommons-logging-java libcommons-parent-java libfontbox-java libpdfbox-java pandoc preview-latex-style texlive texlive-base
  texlive-binaries texlive-fonts-recommended texlive-latex-base texlive-latex-extra texlive-latex-recommended texlive-pictures texlive-plain-generic
0 upgraded, 17 newly installed, 0 to remove and 1 not upgraded.
Need to get 116 MB of archives.
After this operation, 448 MB of additional disk space will be used.
Do you want to continue? [Y/n]

Just to compare, installing LibreOffice Writer would actually use less disk space. Pandoc is a lot faster though.

$ sudo apt install libreoffice-writer
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libabw-0.1-1 libboost-date-time1.71.0 libboost-filesystem1.71.0 libboost-iostreams1.71.0 libboost-locale1.71.0 libclucene-contribs1v5
  libclucene-core1v5 libcmis-0.5-5v5 libe-book-0.1-1 libeot0 libepubgen-0.1-1 libetonyek-0.1-1 libexttextcat-2.0-0 libexttextcat-data libgpgmepp6
  libjuh-java libjurt-java liblangtag-common liblangtag1 libmhash2 libmwaw-0.3-3 libmythes-1.2-0 libneon27-gnutls libodfgen-0.1-1 liborcus-0.15-0
  libraptor2-0 librasqal3 librdf0 libreoffice-base-core libreoffice-common libreoffice-core libreoffice-math libreoffice-style-colibre
  libreoffice-style-tango librevenge-0.0-0 libridl-java libuno-cppu3 libuno-cppuhelpergcc3-3 libuno-purpenvhelpergcc3-3 libuno-sal3
  libuno-salhelpergcc3-3 libunoloader-java libwpd-0.10-10 libwpg-0.3-3 libwps-0.4-4 libxmlsec1 libxmlsec1-nss libyajl2 python3-uno uno-libs-private
Suggested packages:
  raptor2-utils rasqal-utils librdf-storage-postgresql librdf-storage-mysql librdf-storage-sqlite librdf-storage-virtuoso redland-utils
  libreoffice-base gstreamer1.0-plugins-bad tango-icon-theme fonts-crosextra-caladea fonts-crosextra-carlito libreoffice-java-common
The following NEW packages will be installed:
  libabw-0.1-1 libboost-date-time1.71.0 libboost-filesystem1.71.0 libboost-iostreams1.71.0 libboost-locale1.71.0 libclucene-contribs1v5
  libclucene-core1v5 libcmis-0.5-5v5 libe-book-0.1-1 libeot0 libepubgen-0.1-1 libetonyek-0.1-1 libexttextcat-2.0-0 libexttextcat-data libgpgmepp6
  libjuh-java libjurt-java liblangtag-common liblangtag1 libmhash2 libmwaw-0.3-3 libmythes-1.2-0 libneon27-gnutls libodfgen-0.1-1 liborcus-0.15-0
  libraptor2-0 librasqal3 librdf0 libreoffice-base-core libreoffice-common libreoffice-core libreoffice-math libreoffice-style-colibre
  libreoffice-style-tango libreoffice-writer librevenge-0.0-0 libridl-java libuno-cppu3 libuno-cppuhelpergcc3-3 libuno-purpenvhelpergcc3-3
  libuno-sal3 libuno-salhelpergcc3-3 libunoloader-java libwpd-0.10-10 libwpg-0.3-3 libwps-0.4-4 libxmlsec1 libxmlsec1-nss libyajl2 python3-uno
  uno-libs-private ure
0 upgraded, 52 newly installed, 0 to remove and 1 not upgraded.
Need to get 78,5 MB of archives.
After this operation, 283 MB of additional disk space will be used.
Do you want to continue? [Y/n] n

Next, converting the file. It’s possible to tell Pandoc which file formats to use with the -f (from) and -t (to) switches, but it can usually guess correctly based on the file extensions.

$ time pandoc 2022-06-house-contract-adendum.odt -o 2022-06-house-contract-adendum.pdf

real	0m0,519s
user	0m0,475s
sys	0m0,059s

It took only half a second to convert the file. Opening LibreOffice takes a bit more time on this old laptop.

You can see the PDF document properties with pdfinfo:

$ pdfinfo 2022-06-house-contract-adendum.pdf 
Creator:        LaTeX with hyperref
Producer:       pdfTeX-1.40.20
CreationDate:   Sat Jun 11 23:32:30 2022 CEST
ModDate:        Sat Jun 11 23:32:30 2022 CEST
Tagged:         no
UserProperties: no
Suspects:       no
Form:           none
JavaScript:     no
Pages:          2
Encrypted:      no
Page size:      612 x 792 pts (letter)
Page rot:       0
File size:      64904 bytes
Optimized:      no
PDF version:    1.5

I don’t want it in letter format, I want A4:

$ time pandoc -V papersize:a4 -o 2022-06-house-contract-adendum.pdf 2022-06-house-contract-adendum.odt

real	0m0,520s
user	0m0,469s
sys	0m0,060s
$ pdfinfo 2022-06-house-contract-adendum.pdf 
Creator:        LaTeX with hyperref
Producer:       pdfTeX-1.40.20
CreationDate:   Sat Jun 11 23:40:16 2022 CEST
ModDate:        Sat Jun 11 23:40:16 2022 CEST
Tagged:         no
UserProperties: no
Suspects:       no
Form:           none
JavaScript:     no
Pages:          2
Encrypted:      no
Page size:      595.276 x 841.89 pts (A4)
Page rot:       0
File size:      64935 bytes
Optimized:      no
PDF version:    1.5

Then I could open the file with evince 2022-06-house-contract-adendum.pdf.

And yes, I know that addendum is with double d. 🙂

June 07, 2022

Lyte was just listed as a top video player on WP Glob...


June 03, 2022

I published the following diary on “Sandbox Evasion… With Just a Filename!“:

Today, many sandbox solutions are available and deployed by most organizations to detonate malicious files and analyze their behavior. The main problem with some sandboxes is the filename used to submit the sample. The file can be named like “sample.exe”, “suspicious.exe”, “<SHA256>.tmp” or “malware.tmp”… [Read more]

The post [SANS ISC] Sandbox Evasion… With Just a Filename! appeared first on /dev/random.

June 01, 2022

When watching Eurosong a couple of weeks ago -while having a tapas-like dinner for hours and having great fun- one song stood out for me but I did not really enjoy the arrangements. But then a couple of days ago I heard “Saudade, saudade” (by Maro) in a complete live version and I was almost crying. So Eurosong not only is good for an evening of kitsch, fun and food, now and again it also lets the...


May 31, 2022

We spent a week on a power catamaran exploring the British Virgin Islands (BVI). The purpose of the trip was twofold: to experience the BVI, and to come home with a boating license.

The BVI are somewhat hard to get to. It's part of what makes them so stunningly unspoiled. Getting to the BVI required flying from Boston to San Juan, and then from San Juan to Tortola. The flight to Tortola involved a very small plane, which was an experience in itself.

An airline worker stuffing luggage in the wing of a small plane
The plane to Tortola was so small that the luggage had to go in the wings. The pilot also sized each passenger up and decided where we would sit to evenly distribute the weight.

On the first day we met our captain (and instructor) and charted to our first destination; Oil Nut Bay at the Island of Virgin Gorda. It's where we got introduced to the BVI's signature drink; the "painkiller".

Four different rum cocktails lined up next to each others
Painkillers and rum punches, the most popular drinks in the BVI. Every bar and restaurant serves them.
Vanessa watching the sunset from an infinity pool while having a cocktail
Vanessa enjoying a cocktail from the pool at Nova on Oil Nut Bay. Our boat is in the background, tied to a mooring buoy.

We spent the next six days island hopping around the BVI. Each day, we'd arrive at a different near-deserted Caribbean island. We'd tie our boat to a mooring ball, and jump off the boat to swim or paddle board.

A woman standing on a paddle board, surrounded by boats on mooring balls
Taking a stand-up paddle board out in a bay.

After our swim, we'd take our dinghy to shore to explore the island of the day. On shore, there is little to nothing except maybe a few beach bars and restaurants scattered around. In the evening, we'd either cook dinner on the boat, or enjoy the rare restaurant or bar on the island.

Dinghies tied up to a dock
Taking our dinghy to a restaurant on shore.

Each island has perfect soft sand and pristine turquoise water. But each island also has something unique to offer; Cooper Island had a rum bar with a selection of 300 rums; Jost Van Dyke had an amazing beach bar (the famous Soggy Dollar who invented the Painkiller); Trellis Bay has a great sushi restaurant; and The Baths are a unique national park, and a must-see attraction.

A hand on top of a nautical chart and next to a course plotter
Navigation planning using a nautical chart, course plotter, and brass dividers.

Every day, we had classroom-style learning and practiced driving the boat. This included navigation planning, docking exercises, man-overboard maneuvers, anchoring, and more. At the end of the week, I took the theoretical and practical exams, and passed! Next time, I'll be able to charter my own boat.

May 21, 2022

At work, as with many other companies, we're actively investing in new platforms, including container platforms and public cloud. We use Kubernetes based container platforms both on-premise and in the cloud, but are also very adamant that the container platforms should only be used for application workload that is correctly designed for cloud-native deployments: we do not want to see vendors packaging full operating systems in a container and then shouting they are now container-ready.

Sadly, we notice more and more vendors abusing containerization to wrap their products in and selling it as 'cloud-ready' or 'container-ready'. For many vendors, containers allow them to bundle everything as if it were an appliance, but without calling it an appliance - in our organization, we have specific requirements on appliances to make sure they aren't just pre-build systems that lack the integration, security, maintainability and supportability capabilities that we would expect from an appliance.

Even developers are occasionally tempted to enlarge container images with a whole slew of middleware and other services, making it more monolithic solutions than micro-services, just running inside a container because they can. I don't feel that this evolution is beneficial (or at least not yet), because the maintainability and supportability of these images can be very troublesome.

This evolution is similar to the initial infrastructure-as-a-service offerings, where the focus was on virtual machines: you get a platform on top of which your virtual machines run, but you remain responsible for the virtual machine and its content. But unlike virtual machines, where many organizations have standardized management and support services deployed for, containers are often shielded away or ignored. But the same requirements should be applied to containers just as to virtual machines.

Let me highlight a few of these, based on my Process view of infrastructure.

Cost and licensing

Be it on a virtual machine or in a container, the costs and licensing of the products involved must be accounted for. For virtual machines, this is often done through license management tooling that facilitates tracking of software deployments and consumption. These tools often use agents running on the virtual machines (and a few run at the hypervisor level so no in-VM agents are needed).

Most software products also use licensing metrics that are tailored to (virtual) hardware (like processors) or deployments (aka nodes, i.e. a per-operating-system count). Software vendors often have the right to audit software usage, to make sure companies do not abuse their terms and conditions.

Now let's tailor that to a container environment, where platforms like Kubernetes can dynamically scale up the number of deployments based on the needs. Unlike more static virtual machine-based deployments, we now have a more dynamic environment. How do you measure software usage here? Running software license agents inside containers isn't a good practice. Instead, we should do license scanning in the images up-front, and tag resources accordingly. But not many license management tooling is already container-aware, let alone aligned with a different way of working.

But "our software license management tooling is not container-ready yet" is not an adequate answer to software license audits, nor will the people in the organization that are responsible for license management be happy with such situations.

Product lifecycle

Next to the licensing part, companies also want to track which software versions are being used: not just for vulnerability management purposes, but also to make sure the software remains supported and fit for purpose.

On virtual machines, regular software scanning and inventory setup can be done to report on the software usage. And while on container environments this can be easily done at the image level (which software and versions are available in which containers) this often provides a pre-deployment view, and doesn't tell us if a certain container is being used or not, nor if additional deployments have been triggered since the container is launched.

Again, deploying in-container scanning capabilities seems to be contra-productive here. Having an end-to-end solution that detects and registers software titles and products based on the container images, and then provides insights into runtime deployments (and history) seems to be a better match.

Authorization management (and access control)

When support teams need to gain access to the runtime environment (be it for incident handling, problem management, or other operational tasks) most companies will already have a somewhat finer-grained authorization system in place: you don't want to grant full system administrator rights if they aren't needed.

For containers, this is often not that easy to accomplish: the design of container platforms is tailored to situations where you don't want to standardize on in-container access: runtimes are ephemeral, and support is handled through logging and metric, with adaptation to the container images and rolling out new versions. If containers are starting to get used for more classical workloads, authorization management will become a more active field to work out.

Consider a database management system within the container alongside the vendor software. Managing this database might become a nightmare, especially if it is only locally accessible (within the container or pod). And before you yell how horrible such a setup would be for a container platform... yes, but it is still a reality for some.


Auditing is a core part of any security strategy, logging who did what, when, from where, on what, etc. For classical environments, audit logging, reporting and analysis are based upon static environment details: IP addresses, usernames, process names, etc.

In a container environment, especially when using container orchestration, these classical details are not as useful. Sure, they will point to the container platform, but IP addresses are often shared or dynamically assigned. Usernames are dynamically generated or are pooled resources. Process identifiers are not unique either.

Auditing for container platforms needs to consider the container-specific details, like namespaces. But that means that all the components involved in the auditing processes (including the analysis frameworks, AI models, etc.) need to be aware of these new information types.

In the case of monolithic container usage, this can become troublesome as the in-container logging often has no knowledge of the container-specific nature, which can cause problems when trying to correlate information.


I only touched upon a few processes here. Areas such as quality assurance and vulnerability management are also challenges for instance, as is data governance. None of the mentioned processes are impossible to solve, but require new approaches and supporting services, which make the total cost of ownership of these environments higher than your business or management might expect.

The rise of monolithic container usage is something to carefully consider. In the company I work for, we are strongly against this evolution as the enablers we would need to put in place are not there yet, and would require significant investments. It is much more beneficial to stick to container platforms for the more cloud-native setups, and even in those situations dealing with ISV products can be more challenging than when it is only for internally developed products.

Feedback? Comments? Don't hesitate to drop me an email, or join the discussion on Twitter.

May 20, 2022

I have a new laptop. The new one is a Dell Latitude 5521, whereas the old one was a Dell Latitude 5590.

As both the old and the new laptops are owned by the people who pay my paycheck, I'm supposed to copy all my data off the old laptop and then return it to the IT department.

A simple way of doing this (and what I'd usually use) is to just rsync the home directory (and other relevant locations) to the new machine. However, for various reasons I didn't want to do that this time around; for one, my home directory on the old laptop is a bit of a mess, and a new laptop is an ideal moment in time to clean that up. If I were to just rsync over the new home directory, then, well.

So instead, I'm creating a tar ball. The first attempt was quite slow:

tar cvpzf wouter@new-laptop:old-laptop.tar.gz /home /var /etc

The problem here is that the default compression algorithm, gzip, is quite slow, especially if you use the default non-parallel implementation.

So we tried something else:

tar cvpf wouter@new-laptop:old-laptop.tar.gz -Ipigz /home /var /etc

Better, but not quite great yet. The old laptop now has bursts of maxing out CPU, but it doesn't even come close to maxing out the gigabit network cable between the two.

Tar can compress to the LZ4 algorithm. That algorithm doesn't compress very well, but it's the best algorithm if "speed" is the most important consideration. So I could do that:

tar cvpf wouter@new-laptop:old-laptop.tar.gz -Ilz4 /home /var /etc

The trouble with that, however, is that the tarball will then be quite big.

So why not use the CPU power of the new laptop?

tar cvpf - /home /var /etc | ssh new-laptop "pigz > old-laptop.tar.gz"

Yeah, that's much faster. Except, now the network speed becomes the limiting factor. We can do better.

tar cvpf - -Ilz4 /home /var /etc | ssh new-laptop "lz4 -d | pigz > old-laptop.tar.gz"

This uses about 70% of the link speed, just over one core on the old laptop, and 60% of CPU time on the new laptop.

After also adding a bit of --exclude="*cache*", to avoid files we don't care about, things go quite quickly now: somewhere between 200 and 250G (uncompressed) was transferred into a 74G file, in 20 minutes. My first attempt hadn't even done 10G after an hour!

I published the following diary on “A ‘Zip Bomb’ to Bypass Security Controls & Sandboxes“:

Yesterday, I analyzed a malicious archive for a customer. It was delivered to the mailbox of a user who, hopefully, was security-aware and reported it. The payload passed through the different security layers based on big players on the market!

The file is a zip archive (SHA256:97f205b8b000922006c32c9f805206c752b0a7d6280b6bcfe8b60d52f3a1bb5f) and has a score of 6/58 on VT. The archive contains an ISO file that, once mounted, discloses a classic PE file. But let’s have a look at the file… [Read more]

The post [SANS ISC] A ‘Zip Bomb’ to Bypass Security Controls & Sandboxes appeared first on /dev/random.

May 19, 2022

Lorsque j’ai signé pour la publication de Printeurs, mon éditeur m’a fait savoir qu’il attendait de la part des auteurs un certain investissement dans la promotion de leurs livres. J’ai demandé ce qu’il entendait par là et il m’a parlé de participer à des salons, des séances de dédicaces, ce genre de choses. Salons qui furent parmi les premières victimes du COVID en 2020 et 2021.

En 2022, il est temps de rattraper le temps perdu et d’honorer ma promesse. Je serai donc présent du vendredi 20 mai après-midi jusque dimanche 22 mai après-midi aux Imaginales à Épinal, la plus célèbre foire aux boudins de l’imaginaire.

Je n’ai aucune idée de ce que je suis censé faire.

Si j’ai très souvent entendu parler des Imaginales, je n’ai aucune idée de à quoi ressemble ce genre d’événements ni ce qu’on peut y attendre d’un auteur. C’est une nouvelle expérience pour moi et j’en suis assez curieux.

Si vous êtes dans le coin, n’hésitez pas à venir faire un petit coucou et me poser des questions sur le livre qui va sortir cette année. Cherchez une machine à écrire coincée entre une pile de « Printeurs », mon roman cyberpunk, et une pile de « Aristide, le lapin cosmonaute », mon livre pour enfants dont il ne reste qu’une poignée d’exemplaires. Le type derrière le machine qui fait « clac clac clac ding », c’est moi ! Ne vous sentez pas obligé d’acheter un bouquin. Quoi ? Mon éditeur (le type derrière moi, avec le fouet dans la main et un symbole € à la place des pupilles) me dit que si, c’est obligatoire.

Pratiquement, je serai au stand PVH édition, dans une petite tente blanche face à la fontaine au milieu du parc le samedi entre 11h et 19h et, à confirmer, le dimanche matin au même endroit, à côté d’une démonstration de jeu vidéo et d’une imprimante 3D.

J’avoue avoir longuement hésité à poster ce message, mais je me suis dit que si certains d’entre vous sont dans le coin, ce serait dommage de se rater. C’est toujours un plaisir pour moi de rencontrer des lecteurs de mes livres ou de mon blog. Certains d’entre vous me suivent et me soutiennent depuis près de 15 ans et il y a dans la rencontre en chair et en os, même très brève, quelque chose que des dizaines d’emails ne pourront jamais apporter.

Pour ceux qui ne seront pas à Épinal, ce n’est, je l’espère, que partie remise (entre nous, j’ai le secret espoir de pouvoir proposer une conférence aux Utopiales à Nantes, ce qui me donnerait une bonne excuse pour m’y rendre).

Recevez les billets par mail ou par RSS. Max 2 billets par semaine, rien d’autre. Adresse email jamais partagée et définitivement effacée lors du désabonnement. Dernier livre paru : Printeurs, thriller cyberpunk. Pour soutenir l’auteur, lisez, offrez et partagez des livres.

Ce texte est publié sous la licence CC-By BE.

May 17, 2022

I published the following diary on “Use Your Browser Internal Password Vault… or Not?“:

Passwords… a so hot topic! Recently big players (Microsoft, Apple & Google) announced that they would like to suppress (or, at least, reduce) the use of classic passwords. In the meantime, they remain the most common way to authenticate users against many online services. Modern Browsers offer lightweight password management tools (“vaults”) that help users to save their passwords in a central repository. So they don’t have to remember them, and they follow the golden rule that we, infosec people, are recommending for a long time: to not share passwords across services… [Read more]

The post [SANS ISC] Use Your Browser Internal Password Vault… or Not? appeared first on /dev/random.

May 15, 2022

De bedoeling van Finland en Zweden die lid worden van het huidige NATO mag niet zijn dat we meer NATO krijgen. Maar wel dat we een groter EU leger verkrijgen.

Alleen een goed EU leger zal in de toekomst een buurland zoals Rusland koest en kalm houden. De NATO zal dat niet doen. In tegendeel, het zal Rusland onrustig maken. Want dat speelt in NATO’s kaarten: een grootschalig conflict op het grondgebied van de EU met Rusland is in het grootste belang van de NATO om te blijven bestaan als organisatie.

M.a.w. moeten wij Europeanen heel erg veel investeren in onze eigen defensie. We moeten dit niet meer overlaten aan de VS. We moeten dit financieel én operationeel in eigen handel nemen.

We moeten bereid zijn en klaar staat om agressie van bijvoorbeeld Rusland te kunnen afslaan. Zelfs te bestraffen. Dat wil dus zeggen dat ook wij nucleaire wapens nodig hebben. In EU handen. Inzetbaar. Met een strategisch EU commando dat het middel ook effectief kan en vooral zal inzetten in geval van bepaalde scenarios.

Maar vooral moeten we investeren in diplomatie en realisme, realpolitik, met Rusland. Aan de hand van hun bezorgdheden, en die van ons.

Oekraïne was een bufferstaat. Dat werkte goed. Ik zou graag willen dat het dat zou blijven en zou zijn. Terwijl het graan produceert. Terwijl het groeit. Terwijl het eventueel over een paar decennium onderdeel van de EU wordt.

Maar zouden we niet eerst de Balkan eens eindelijk na zo’n godverdomme 20 jaar lid maken van de EU?! Kosovaren bijvoorbeeld kunnen nog steeds niet zonder reis visum naar de EU komen. Hoewel we daar de grootste NAVO-basis van West-Europa hebben (KFOR) staan. We praten hier nu over Oekraïne dat morgen lid van de EU zou kunnen worden. Terwijl de gehele Balkan-regio na haar oorlogen van de jaren negentig nog steeds, in 2022, niet geïntegreerd is.

 Two books about The Witcher and eentje over onze maatschappij.


I never played The Witcher game, but I did see the TV-series' first season in the months before Covid-19. The books are about the same characters, Geralt, Ciri, Yennefer and the others, but the story details differ from the TV-series. I saw the second season before I read any of the books.

Some dialogues are identical in both books and TV. And yes, the books also mix time periods! Anyway, so far these books are entertaining and I will definitely read more (I got eight, which is all of them I think).

While looking for wine in Antwerp I came across a 'Books & Wine' store. I did not find the wine I was looking for so I bought this book.

Bart Verhoeven is een millennial (een dertiger vandaag) en geeft zijn kijk op onze maatschappij. Hij slaat met momenten de nagel op de kop en het was leuk om typische Gen X observaties te lezen, maar dan geschreven door een snotneus. Het boek mocht ook 250blz langer zijn.

Hier en daar had ik wel mijn bedenkingen, zo kon ik me niet identificeren met de 'typische mens' in het begin van het boek. Ik laat immers mijn gsm achter als ik de stad in ga (het is rustgevend om offline te zijn in First life) en heb bijna nooit een smartphone bij.

May 14, 2022

An emotional book about shame, a historical book about Constantinople and an interesting take on prehistory (and society).


Three book covers

Brene Brown has a world famous Ted talk, though I must admit I didn't really understand it back in 2010. But when a beautiful South American lady gives you a book, then you read it. I read this in the summer of 2019 I think, before Covid-19.

This book about vulnerability, about shame, gave me a lot of insight in human behaviour, including my own. I did not realise how important shame was in live. Thank you Brown for writing this.


Lost to the West was upvoted on Hackernews as an interesting read. I was not disappointed. The book is about the East Roman Empire, on which we did not spend much time in school. We studied Egypt, Greece and Rome in detail, but only the Western part of Rome until the split in East and West Roman Empires. School only mentioned that the Eastern Empire lasted for 11 centuries, but that was it.

Some people may find this book with 1100 year history of emperors boring, there is a lot of repetition, but the message is intriguing. Constantinople, now Istanbul, and sometimes called Byzantium, really did shape Western Europe. This empire is at least as important as the Greeks and the (West)Romans to the current society in Europe.

The Sapiens book has been recommended to me by several people. I like prehistory a lot, it's my favorite time period. The book is interesting, and really easy to read, but is it science? I don't know. It's a good book though!


May 11, 2022

Le concept même de logiciel n’est pas évident. Comme le rappelait Marion Créhange, la première titulaire d’un doctorat en informatique en France, la manière d’influencer le comportement des premiers ordinateurs était de changer le branchement des câbles. Un programme était littéralement un plan de câblage qui nécessitait de s’arracher les mains sur des fils.

Petit à petit, les premiers informaticiens ont amélioré la technologie. Ils ont créé des ordinateurs « programmables » qui pouvaient être modifiés si on leur fournissait des programmes au format binaire, généralement des trous sur des cartes en carton qui étaient insérées dans un ordre précis. Il fallait bien évidemment comprendre exactement comment fonctionnait le processeur pour programmer la machine.

Les processeurs ont ensuite été améliorés pour comprendre des instructions simples, appelées « assembleur ». Les informaticiens pouvaient réfléchir avec ce langage qui donnait des instructions directes au processeur. Cependant, ils utilisaient d’autres formalismes qu’ils appelèrent « langage de programmation ». Les programmes étaient écrits sur papier dans ce langage puis, grâce à des tableaux, traduits en assembleur.

Vint alors l’idée de concevoir un programme qui effectuerait cette traduction. Le premier de ces programmes fut appelé « Traducteur de formules », « Formula Translator », abrégé en « FORTRAN ». Les traducteurs de formules furent rapidement renommés « compilateurs ». Avec un compilateur, il n’était plus nécessaire de comprendre ce que faisait le processeur. Il devenait possible de créer un programme dans un langage dit « de haut niveau » et de le donner à la machine.

Il faut cependant insister sur le fait qu’à l’époque, chaque ordinateur vient avec son propre système logiciel qui est extrêmement complexe et particulier. Faire tourner un programme requiert d’apprendre l’ordinateur en question. Faire tourner le même programme sur plusieurs ordinateurs différents n’est même pas envisagé.

Vu le prix élevé d’un ordinateur, comparables à celui d’une luxueuse villa, ceux-ci sont rares et partagés entre des dizaines d’utilisateurs, le plus souvent au sein des universités. L’un des gros problèmes informatiques de l’époque est de rentabiliser l’ordinateur. Il est possible d’interagir directement avec un ordinateur à travers un télétype : un gros clavier relié à un système électrique avec une bande de papier fournissant les résultats. Le problème du télétype c’est que lorsque l’utilisateur lit les résultats et réfléchit, l’ordinateur attend sans rien faire. Un peu comme si vous achetiez une voiture à 50.000€ pour la laisser 95% du temps dans son garage (ce qui est le cas, soi dit en passant).

Pour cette raison, l’interaction directe est découragée au profit des « batch » de cartes perforées. Le programmeur créé des cartes perforées contenant toutes les instructions qu’il veut effectuer (son « programme »), les donne dans une boîte au centre de calcul qui les insère dans l’ordinateur lorsque celui-ci est inoccupé. Le résultat est imprimé est envoyé au programmeur, parfois le lendemain ou le surlendemain.

Apparait l’idée de permettre de connecter plusieurs télétypes à un ordinateur pour donner une apparence d’interactivité tout en faisant en sorte que l’ordinateur traite séquentiellement les requêtes. Un projet est mis sur pieds pour faire de ce rêve une réalité : Multics. Multics est un projet à gros budget qui fait se collaborer une grande entreprise, General Electrics, une université, le MIT, et un laboratoire de recherche dépendant d’AT&T, le Bell Labs.

Multics possède les bons programmeurs et les bonnes idées. Mais une collaboration à une telle échelle nécessite beaucoup de managers, de politiciens, d’administratif, de paperasse. Bref, au bout de 5 ans, le projet est finalement considéré comme un échec. Les managers et les administrateurs vont voir ailleurs.

La première grande collaboration

Sans s’en rendre compte tout de suite, le défunt Multics laisse désœuvrés quelques programmeurs. Parmi eux, Ken Thompson vient d’avoir un enfant. L’anecdote est importante, car son épouse lui annonce partir un mois avec le bébé pour le présenter à sa famille, qui vit de l’autre côté du pays. Thompson se retrouve quatre semaines tout seul et décide de profiter de ce temps pour mettre en place une version simplifiée de Multics qu’il a en tête. Par dérision, il l’appelle Unics. Qui deviendra Unix. Au départ écrit en assembleur, il inventera le langage B qui sera utilisé par son pote Ritchie pour inventer le langage C avec lequel sera réécrit Unix en 1973.

Thompson et Ritchie sont également les premiers prototypes des geeks de l’informatique : barbe mal entretenu, cheveux en bataille, t-shirt trop large (à une époque où même la jeunesse rebelle n’imagine pas s’afficher autrement qu’en vestes de cuir cintrées), séances de programmation jusqu’à l’aube, arrivées au laboratoire vers 13h du matin, etc.

Dans ses réflexions, Thompson n’a qu’un mot à la bouche : « simplicité ». C’est d’ailleurs lui qui va pousser Ritchie à ce que le langage « C » s’appelle ainsi. Une lettre, c’est simple, efficace. Cette idée de simplicité sous-tend toute l’architecture d’Unix : plutôt que de faire un énorme système hyper complexe qui fait tout, on va faire des petits programmes et leur permettre de s’utiliser l’un l’autre. L’idée est révolutionnaire : un programme peut utiliser un autre pour obtenir une fonctionnalité. Arrive même l’idée du « pipe » qui permet à l’utilisateur de construire ses propres chaines de programmes. Cela semble évident aujourd’hui, mais c’est un progrès énorme à une époque où les concepteurs de systèmes d’exploitation tentent de faire un énorme programme capable de tout faire en même temps. Cette simplicité est d’ailleurs encore aujourd’hui ce qui fait la puissance des systèmes inspirés d’Unix. C’est également ce qui va permettre une vague de collaboration sans précédent : chaque individu peut désormais créer un petit outil qui va accroitre exponentiellement les capacités du système global.

Ritchie et Thompson présentent le résultat de leur travail lors d’une conférence en 1973. À la même époque vient justement d’apparaitre le concept non pas de connecter des ordinateurs directement entre eux, ce qui existait déjà, mais de leur permettre de servir de relais. Deux ordinateurs peuvent désormais se parler sans être connectés directement. Cela dessine un réseau, appelé ARPANET et qui deviendra INTERNET, l’interconnexion des réseaux.

Certains historiens estiment qu’environ la moitié des personnes connectées à ARPANET à l’époque était dans la salle lors de la présentation d’Unix.

Le concept est tout de suite un véritable succès.

Une chose importante est de savoir que le Bell Labs, où a été inventé Unix, faisait partie d’AT&T. Et qu’AT&T était, à ce moment-là, sous le coup d’un procès antitrust et n’avait pas le droit de faire autre chose que de vendre de l’équipement téléphonique. L’état américain voyait d’un très mauvais œil qu’une entreprise privée puisse devenir trop puissante. Dès que c’était le cas, dès qu’une position de monopole se dessinait, l’état intervenait rapidement.

AT&T commercialisait des lignes téléphoniques. L’objectif du Bell Labs était de développer des technologies qui nécessitaient l’utilisation de lignes téléphoniques afin d’en encourager l’usage. Mais AT&T ne cherchait pas à commercialiser directement ces technologies. Le procès antitrust rendait cela beaucoup trop risqué.

Pas du tout préoccupée par l’aspect mercantile, l’équipe UNIX se met à collaborer avec les universités, les chercheurs de tout bord. À l’université de Berkeley, tout particulièrement, on se met à améliorer les fonctionnalités. On s’échange du code source, des astuces. On se connecte directement aux ordinateurs de l’un et l’autre pour comprendre les problèmes. Bref, on collabore sans réellement réfléchir à l’aspect financier.

En Australie, le professeur John Lions enseigne Unix à ses étudiants en leur donnant… l’entièreté du code source à lire. Code source qu’il commente abondamment. Son syllabus fait rapidement le tour du monde comme un outil indispensable, le tout avec la bénédiction de Ken Thompson.

Petit à petit, Unix prend de l’importance et, chez AT&T, les juristes commencent un peu à se dire qu’il y’aurait des sous à se faire. La marque UNIX est déposée. Qu’à cela ne tienne, le « UNIX USER GROUP » est renommé « Usenix ». On demande à Ritchie et Thompson de ne plus partager leur travail. Qu’à cela ne tienne, celui-ci « oublie » malencontreusement des sacs remplis de bandes magnétiques dans un parc où, justement, se promenait un ami de Berkeley.

Ça vous donne un peu l’idée du niveau de collaboration et d’esprit frondeur qui anime l’ensemble. Ils ont peut-être des barbes et des t-shirts larges. Ils n’en restent pas moins intelligents et frondeurs. Ce sont des « hackers », le terme qu’ils se donnent et qui est encore utilisé aujourd’hui.

La première confiscation

En 1980, un changement politique se fait en occident avec l’élection de Margaret Thatcher au Royaume-Uni et de Ronald Reagan aux États-Unis. Leur doctrine pourrait se résumer en « faire passer les intérêts des entreprises avant ceux des individus ». La recherche, la collaboration, le partage et l’empathie sont devenus des obstacles sur la route de la recherche de profit. Plusieurs grandes mesures vont voir le jour et avoir une importance extrêmement importante, tant sur l’industrie du logiciel que sur notre avenir.

Le terme « propriété intellectuelle », un concept inventé en 1967 et jusque là à peu près ignoré, va devenir une stratégie essentielle des entreprises pour faire du profit. Historiquement, le concept de propriété permet d’asseoir le droit de jouir d’un bien sans se le faire enlever. Mais comment peut-on « voler » une propriété intellectuelle ? Cela semble absurde, mais c’est pourtant très simple : il suffit de convaincre la population que tout concept, toute œuvre possède un propriétaire et que le simple fait d’en jouir ou de l’utiliser est une atteinte aux intérêts économiques de l’auteur. Historiquement, les brevets offraient aux inventeurs un monopole limité dans le temps sur une invention en échange du fait que cette invention deviendrait publique une fois le brevet expiré. Bien que luttant contre les monopoles, l’état savait en offrir un temporaire en échange d’un bénéfice futur pour la société. L’idéologie du profit avant tout permet d’écarter complètement cette composante de l’équation. Le terme « propriété intellectuelle » permet d’étendre les monopoles temporaires, tant en termes de temporalité que de droits. Le propriétaire de la propriété intellectuelle ne doit plus rien à la société qui n’a plus qu’une fonction : préserver ses profits bien mérités.

Grâce à près de trente années de campagnes intensives, le concept de propriété intellectuelle est tellement ancré dans les mœurs que les écoles n’osent plus faire chanter leurs enfants sans s’assurer de payer des droits auprès d’un organisme quelconque qui, bien évidemment, ne demande que ça. La propriété intellectuelle est, intellectuellement, une escroquerie. Elle sonne également le glas de la collaboration et des grands progrès académiques. Même les universités, aujourd’hui, cherchent à préserver leurs propriétés intellectuelles. Par réflexe et en dépit de leur mission première.

Les concepts de collaboration et de bien-commun sont eux immolés sur l’autel de l’anticommunisme. Faire du profit à tout prix devient un devoir patriotique pour lutter contre le communisme. Cela a tellement bien fonctionné que malgré l’écroulement total du communisme, le concept du bien commun est rayé du vocabulaire. Plus de 30 ans après la chute du mur de Berlin, les gouvernements et les institutions publiques comme les universités doivent encore justifier leurs choix et leurs investissements en termes de rentabilités et de profits futurs.

Cette évolution des mentalités se fait en parallèle à la complexification du concept de logiciel. Graduellement, le logiciel est passé d’une série d’instructions à un véritable travail, une véritable œuvre. Il peut logiquement être commercialisé. La commercialisation d’un logiciel se fait via une innovation légale : la licence. La licence est un contrat entre le fournisseur du logiciel et l’utilisateur. Le fournisseur du logiciel impose ses conditions et vous devez les accepter pour utiliser le logiciel. Grâce à la propriété intellectuelle, le logiciel reste la propriété du fournisseur. On n’achète plus un bien, on achète le droit de l’utiliser dans un cadre strictement défini.

Notons que cette innovation commerciale découle en droite ligne de l’importance morale accordée aux profits. Si l’utilisateur ne peut plus acheter, stocker, réparer et réutiliser un bien, il doit payer à chaque utilisation. L’utilisateur est clairement perdant par rapport au cas d’usage où il achèterait le logiciel comme un bien dont il peut disposer à sa guise.

Aujourd’hui, chaque logiciel que nous utilisons est muni d’une licence et dépend le plus souvent d’autres logiciels également munis de leurs propres licences. Il a été démontré qu’il est matériellement impossible de lire tous les contrats que nous acceptons quotidiennement. Pourtant, la fiction légale prétend que nous les avons acceptés consciemment. Que nous devons nous plier aux conditions qui sont décrites. Chaque fois que nous cliquons sur « J’accepte », nous signons littéralement un chèque en blanc sur notre âme, en espérant que jamais le Malin ne vienne réclamer son dû.

Pour perpétuer l’esprit UNIX initial, cet esprit frondeur et hacker, l’université de Berkeley met au point la licence BSD. Cette licence dit, en substance, que vous pouvez faire ce que vous voulez avec le logiciel, y compris le modifier et le revendre, à condition de citer les auteurs.

Le livre de John Lions est lui interdit, car contenant la propriété intellectuelle d’AT&T. Il circule désormais sous le manteau, photocopié par des générations d’étudiants qui ne cherchent pas à le moins du monde à faire de l’ombre à AT&T, mais à simplement mieux comprendre comment fonctionne ou pourrait fonctionner un ordinateur.

L’apparition des ordinateurs personnels

Les ordinateurs sont de moins en moins chers. Et de plus en plus variés. L’entreprise IBM est le plus gros fournisseur d’ordinateurs, certains sont des mastodontes, d’autres ont à peine la taille d’une grosse valise (les « mini-ordinateurs »).

IBM a l’idée de créer des ordinateurs assez petits pour tenir sur un bureau : un micro-ordinateur. Il serait bon marché, peu puissant. Son nom ? Le « personal computer », le PC.

Seulement, comme AT&T auparavant, IBM est sous le coup d’un procès antitrust. Diplomatiquement, il serait dangereux de se lancer dans un nouveau marché. Pour éviter cela, IBM va tout d’abord concevoir le PC avec une architecture ouverte, c’est-à-dire des composants que n’importe qui peut acheter ou copier (contrairement aux concurrents comme Amiga, Commodore, Atari, etc.). Le système d’exploitation, le logiciel qui fera tourner la machine, est considéré comme l’un de ces composants. Problème : les systèmes Unix sont très chers et conçus avec des fonctionnalités très complexes comme le fait d’héberger plusieurs utilisateurs. Ils ne sont donc pas adaptés à un « personal computer ». IBM travaille bien sur son propre operating system (OS2), mais, en attendant, pourquoi ne pas sous-traiter la tâche ?

Un riche et important avocat d’affaires, William Gates, qui travaille, entre autres, pour IBM, entend parler de cette histoire et annonce que son fils vient justement de lancer une entreprise d’informatique. Le fils en question, appelé également William Gates, mais surnommé Bill, n’a jamais programmé d’operating system mais il propose à IBM d’en faire un à condition d’être payé pour chaque personal computer vendu. Tant qu’il y est, il ajoute dans le contrat qu’IBM est forcé d’installer son OS sur chaque PC vendu. Empêtré dans son procès antitrust et ne voyant pas un grand avenir pour une solution bon marché comme le PC, IBM accepte ces conditions qui sont pourtant étranges.

Bill Gates n’a jamais programmé d’OS, mais il connait un jeune informaticien de 22 ans, Tim Paterson, qui a fait ce qu’il appelle un « Quick and Dirty OS », QDOS. Un truc amateur et minimaliste qui n’a même pas les fonctionnalités qu’avait Unix 15 ans auparavant. Mais ce n’est pas grave. Bill Gates propose 50.000$ pour QDOS, qu’il rebaptise PC-DOS puis MS-DOS.

À cette même époque, un conseiller du président Reagan, un certain Robert Bork, se rend compte que s’il y’a bien un truc qui empêche de maximiser les profits des entreprises, ce sont les lois antimonopoles. Pauvre AT&T, pauvre IBM. Ces entreprises américaines auraient pu coloniser le monde et faire le bonheur de leurs actionnaires. Ces entreprises pourraient affaiblir économiquement le bloc soviétique. Au lieu de cela, les Américains eux-mêmes leur ont mis des bâtons dans les roues.

Il propose donc de tout simplement autoriser les monopoles. Bien sûr, ça se verrait un peu trop si on le dit comme ça du coup il propose de n’empêcher que les monopoles dont on peut démontrer qu’ils entrainent une hausse significative du prix pour le consommateur final. Cela permet de prétendre que l’on protège le consommateur final tout en faisant oublier que, premièrement, il est impossible de démontrer qu’un prix est trop haut et que, deuxièmement, les monopoles infligent bien d’autres problèmes à la société qu’une seule augmentation des prix.

L’impact de Robert Bork est primordial. Grâce à lui, Microsoft, la société de Bill Gates, s’arroge le monopole sur les systèmes d’exploitation tournant sur les ordinateurs personnels, qui deviennent, à la grande surprise d’IBM, un énorme succès au point d’éclipser les supercalculateurs. Il faut dire qu’IBM, par peur de devenir un monopole, a permis à d’autres constructeurs de se mettre à fabriquer leur propre PC : Dell, Compaq, etc. Et rien n’empêche Microsoft de fournir DOS à ces concurrents tout en les obligeant à ne fournir leurs ordinateurs qu’avec DOS, rien d’autre. En quelques années, le terme « PC » devient synonyme de micro-ordinateur et de… « Microsoft ». Les Atari, Armstrad, Commodore et autres Amiga disparaissent complètement malgré leur avance technologique indéniable.

Il faut dire que ce DOS merdique arrange pas mal de monde : il permet aux véritables informaticiens de rester en dehors de la plèbe avec leurs supercalculateurs et aux fournisseurs de véritables ordinateurs de continuer à pratiquer des prix délirants. Le PC avec DOS n’est qu’un jouet, pas un truc professionnel.

La résistance s’organise

Tous ces événements sonnent le glas de du premier âge d’or de l’informatique. L’informatique était jusque là un domaine de passionnés qui collaboraient, elle devient un domaine extrêmement lucratif qui cherche à contrôler autant que possible ses clients pour en tirer le maximum d’argent.

Richard Stallman, un chercheur en Intelligence Artificielle du MIT se rend compte que, graduellement, tous ses collègues se font embaucher par des entreprises privées. Une fois embauchés, ceux-ci ne peuvent plus collaborer avec lui. Ils emportent avec eux leurs codes, leurs recherches. Ils continuent à utiliser les codes disponibles sous licence BSD, mais ne partagent plus rien.Pire : ils ne peuvent même plus discuter du contenu de leur travail.

Richard, qui ne vit que pour l’informatique, en est très triste, mais la goutte d’eau viendra d’une imprimante. En effet, Richard avait modifié le logiciel tournant sur l’imprimante de tout le département pour éviter les bourrages et pour envoyer un email à la personne ayant initié l’impression une fois celle-ci terminée. Cependant, l’imprimante est ancienne et est remplacée. Richard Stallman ne se pose pas trop de questions et décide d’implémenter les mêmes fonctionnalités pour la nouvelle imprimante. À sa grande surprise, il ne trouve pas le code source des programmes de celle-ci. Il fait la demande au fabricant et se voit rétorquer que le code source appartient au fabricant, que personne ne peut le consulter ou le modifier.

Richard Stallman voit rouge. L’université a payé pour l’imprimante. De quel droit le fabricant peut-il empêcher un client de faire ce qu’il veut avec son achat ? De quel droit peut-il empêcher un « hacker » de comprendre le code qui tourne dans son propre matériel. Avec une grande prescience, il comprend que si la pratique se généralise, c’est tout simplement la fin du mouvement hacker.

Ni une ni deux, RMS démissionne du MIT, où il gardera néanmoins un bureau, pour lancer la Free Software Foundation, la fondation pour le logiciel libre. Son idée est simple : l’industrie vient de confisquer aux informaticiens la liberté de faire tourner les logiciels de leur choix. Il faut récupérer cette liberté.

Il théorise alors les quatre grandes libertés du logiciel libre :

  1. Le droit d’utiliser un logiciel pour n’importe quel usage
  2. Le droit d’étudier un logiciel pour le comprendre
  3. Le droit de modifier un logiciel
  4. Le droit de partager un logiciel et/ou ses modifications

Aujourd’hui, on considère « libre » un logiciel qui permet ces quatre libertés.

Il semble évident qu’un logiciel sous licence BSD est libre. Mais Stallman se rend compte d’un problème : les logiciels sont bien libres, mais les personnes les modifiant dans des entreprises privées ne partagent jamais leurs améliorations.

Il met alors au point la licence GPL. Celle-ci, comme toute licence, est un contrat et stipule que l’utilisateur d’un logiciel a le droit de réclamer les sources, de les étudier, les modifier et les redistribuer. Par contre, s’il redistribue le logiciel, il est obligé de conserver la licence GPL.

Si les licences propriétaires restreignent au maximum les libertés des utilisateurs et les licences apparentées à BSD donnent le maximum de libertés aux utilisateurs, la GPL restreint une seule liberté : celle de restreindre la liberté des autres.

La GPL définit donc une forme de bien commun qu’il n’est pas possible de privatiser.

Notons que, comme toute licence, la GPL est un contrat entre le fournisseur et l’utilisateur. Seul l’utilisateur peut demander le code source d’un logiciel sous licence GPL. Un logiciel GPL n’est donc pas nécessairement public. De même, rien n’interdit de faire payer pour un logiciel GPL. Richard Stallman lui-même gagnera un temps sa vie en vendant le logiciel libre qu’il développe, l’éditeur Emacs.

Stallman, RMS pour les intimes, ne s’arrête pas là. Puisque les systèmes d’exploitation UNIX sont des myriades de petits logiciels coopérants entre eux, il va les réécrire un par un pour créer un système entièrement sous licence GPL : GNU. GNU est l’acronyme de « GNU is Not Unix ». C’est récursif, c’est de l’humour de geek.

RMS travaille d’arrache-pied et le projet GNU est bien lancé. Il ne manque qu’un composant pourtant essentiel : le noyau ou « kernel » en anglais. Le noyau est la partie de code centrale qui fait l’interface entre la machine et tous les outils UNIX ou GNU.

La deuxième grande collaboration

En parallèle du travail de Richard Stallman, un tremblement de terre a lieu dans le monde Unix : l’entreprise AT&T s’est soudainement réveillée et s’est rendu compte qu’elle est le berceau d’un système d’exploitation devenu très populaire et surtout très rémunérateur.

Elle attaque alors en justice l’université de Berkeley pour diffusion illégale du code source UNIX sous le nom « Berkeley Software Distribution », BSD.

La distribution de BSD est un temps interrompue. Le futur de BSD semble incertain. Il apparaitra que le code de BSD avait bien été écrit par les chercheurs de Berkeley, ceux-ci ayant graduellement amélioré le code source UNIX original au point de le remplacer complètement, dans une version moderne du mythe du bateau de Thésée. Seuls 6 fichiers seront identifiés par le juge comme appartenant à AT&T, 6 fichiers qui seront donc remplacés par des nouvelles versions réécrites.

Mais, en 1991, cette conclusion n’est pas encore connue. Le système GNU n’a pas de noyau, le système BSD est dans la tourmente. Un jeune étudiant finlandais vient, de son côté, d’acquérir un nouvel ordinateur et rêve de faire tourner UNIX dessus. Comme les UNIX propriétaires sont vraiment trop chers, il télécharge les outils GNU, qui sont gratuits et, s’appuyant dessus, écrit un mini-noyau qu’il partage sur Usenet.

Si Internet existe, le web, lui, n’existe pas encore. Les échanges se font sur le réseau Usenet, l’ancêtre des forums web et le repaire des passionnés de n’importe quel domaine.

Le noyau de Linus Torvalds, notre jeune finlandais, attire rapidement l’attention de passionnés de Unix qui le nomment du nom de son créateur : Linux. Très vite, ils envoient à Linus Torvalds des améliorations, des nouvelles fonctionnalités que celui-ci intègre pour produire de nouvelles versions.

Influencé par les outils GNU, Linus Torvalds a mis sa création sous licence GPL. Il est donc désormais possible de mettre en place un système Unix sous licence GPL : c’est GNU/Linux. Enfin, non, ce n’est pas Unix. Car Gnu is Not Unix. Mais ça y ressemble vachement…

Bon, évidemment, installer le noyau Linux et tous les outils GNU n’est pas à la portée de tout le monde. Des projets voient le jour pour faciliter l’installation et permettent d’empaqueter tous ces composants hétéroclites. Ce sont les « Distributions Linux ». Certaines offrent des versions commerciales, comme Red Hat alors que d’autres sont communautaires, comme Debian.

Outre le noyau Linux, Linus Torvalds invente une nouvelle manière de développer des logiciels : tout le monde peut étudier, critiquer et contribuer en soumettant des modifications (des « patchs »). Linus Torvalds choisit les modifications qu’il pense utiles et correctes, refuse les autres avec force discussions. Bref, c’est un joyeux bazar. Sur Usenet et à travers les mailing-lists, les hackers retrouvent l’esprit de collaboration qui animait les laboratoires Unix des débuts. Des années plus tard, Linus Torvalds inventera même un logiciel permettant de gérer ce bazar : git. Git est aujourd’hui l’un des logiciels les plus répandus et les plus utilisés par les programmeurs. Git est sous licence GPL.

La « non-méthode » Torvalds est tellement efficace, tellement rapide qu’il semble évident que c’est la meilleure manière de développer des bons logiciels. Des centaines de personnes lisant un code source sont plus susceptibles de trouver des bugs, d’utiliser le logiciel de manière imprévue, d’apporter des touches de créativité.

Eric Raymond théorisera cela dans une conférence devenue un livre : « La cathédrale et le bazar ». Avec Bruce Perens, ils ont cependant l’impression que le mot « Free Software » ne fait pas professionnel. En anglais, « Free » veut dire aussi bien libre que gratuit. Les « Freewares » sont des logiciels gratuits, mais propriétaires, souvent de piètre qualité. Eric Raymond et Bruce Perens inventent alors le terme « open source ».

Techniquement, un logiciel libre est open source et un logiciel open source est libre. Les deux sont synonymes. Mais, philosophiquement, le logiciel libre a pour objectif de libérer les utilisateurs là où l’open source a pour objectif de produire des meilleurs logiciels. Le mouvement open source, par exemple, accepte volontiers de mélanger logiciels libres et propriétaires là où Richard Stallman affirme que chaque logiciel propriétaire est une privation de liberté. Développer un logiciel propriétaire est, pour RMS, hautement immoral.

Les deux noms désignent cependant une unique mouvance, une communauté grandissante qui se bat pour regagner la liberté de faire tourner ses propres logiciels. Le grand ennemi est alors Microsoft, qui impose le monopole de son système Windows. La GPL est décrite comme un « cancer », le logiciel libre comme un mouvement « communiste ». Apple, une entreprise informatique qui n’est à cette époque plus que l’ombre de son glorieux passé va piocher dans les logiciels libres pour se donner un nouveau souffle. En se basant sur le code de FreeBSD, qui n’est pas sous licence GPL, ils vont mettre au point un nouveau système d’exploitation propriétaire : OSX, renommé ensuite MacOS. C’est également de cette base qu’ils vont partir pour créer un système embarqué : iOS, initialement prévu pour équiper l’iPod, le baladeur musical lancé par la firme.

La seconde confiscation

Pour fonctionner et donner des résultats, un logiciel a besoin de données. Séparer le logiciel des données sur lesquelles il tourne permet de réutiliser le même logiciel avec différente données. Puis de vendre des logiciels dans lesquels les utilisateurs vont entrer leurs propres données pour obtenir des résultats.

L’un des arguments pour souligner l’importance du logiciel libre est justement l’utilisation de ces données. Si vous utilisez un logiciel propriétaire, vous ne savez pas ce qu’il fait de vos données, que ce soit de données scientifiques, des données personnelles, des documents dans le cadre du travail, des courriers. Un logiciel propriétaire pourrait même envoyer vos données privées aux concepteurs sans votre consentement. L’idée paraissait, à l’époque, issue du cerveau d’un paranoïaque.

Outre les données, un autre des nombreux combats libristes de l’époque est de permettre d’acheter un ordinateur sans Microsoft Windows préinstallé et sans payer la licence à Microsoft qui s’apparente alors à une taxe. Le monopole de Microsoft fait en effet qu’il est obligatoire d’acheter Windows avec un ordinateur, même si vous ne comptez pas l’utiliser. Cela permet à Bill Gates de devenir en quelques années l’homme le plus riche du monde.

Pour lutter contre ce monopole, les concepteurs de distributions Linux tentent de les faire les plus simples à utiliser et à installer. Le français Gaël Duval est un pionnier du domaine avec la distribution Mandrake, renommée plus tard Mandriva.

En 2004 apparait la distribution Ubuntu. Ubuntu n’est, au départ, rien d’autre qu’une version de la distribution Debian simplifiée et optimisée pour une utilisation de bureau. Avec, par défaut, un joli fond d’écran comportant des personnes nues. Ubuntu étant financé par un milliardaire, Mark Shuttleworth, il est possible de commander gratuitement des Cd-roms pour l’installer. La distribution se popularise et commence à fissurer, très légèrement, le monopole de Microsoft Windows.

L’avenir semble aux mini-ordinateurs de poche. Là encore le libre semble prendre sa place, notamment grâce à Nokia qui développe ce qui ressemble aux premiers smartphones et tourne sous une version modifiée de Debian : Maemo.

Mais, en 2007, Apple lance ce qui devait être au départ un iPod avec une fonctionnalité téléphone : l’iPhone. Suivit de près par Google qui annonce le système Android, un système d’exploitation prévu au départ pour les appareils photo numériques. L’invasion des smartphones a commencé. Plusieurs entreprises se mettent alors à collaborer avec Nokia pour produire des smartphones tournant avec des logiciels libres. Mais en 2010, un cadre de chez Microsoft, Stephen Elop, est parachuté chez Nokia dont il est nommé CEO. Sa première décision est d’arrêter toute collaboration avec les entreprises « libristes ». Durant trois années, il va prendre une série de décisions qui vont faire chuter la valeur boursière de Nokia jusqu’au moment où l’entreprise finlandaise pourra être rachetée… par Microsoft.

L’iPhone d’Apple est tellement fermé qu’il n’est, au départ, même pas possible d’y installer une application. Steve Jobs s’y oppose formellement. Les clients auront le téléphone comme Jobs l’a pensé et rien d’autre. Cependant, les ingénieurs d’Apple remarquent que des applications sont développées pour l’Android de Google. Apple fait vite machine arrière. En quelques années, les « app » deviennent tendance et les « App Store » font leur apparition, reprenant un concept initié par… les distributions Gnu/Linux ! Chaque banque, chaque épicerie se doit d’avoir son app. Sur les deux systèmes, qui sont très différents. Il faut développer pour Apple et pour Google.

Microsoft tente alors de s’imposer comme troisième acteur avant de jeter l’éponge : personne ne veut développer son app en 3 exemplaires. Dans les milieux branchés de la Silicon Valley, on se contente même souvent de ne développer des applications que pour Apple. C’est plus cher donc plus élitiste. De nombreux hackers cèdent aux sirènes de cet élitisme et se vendent corps et âmes à l’univers Apple. Qui interdit à ses clients d’installer des applications autrement que via son App Store et qui prend 30% de commission sur chacune des transactions réalisées sur celui-ci. Développer pour Apple revient donc à donner 30% de son travail à l’entreprise de Steve Jobs. C’est le prix à payer pour faire partie de l’élite. Les hackers passés à Apple vont jusqu’à tenter de se convaincre que comme Apple est basée sur FreeBSD, c’est un Unix donc c’est bien. Nonobstant le fait que l’idée même derrière Unix est avant tout de pouvoir comprendre comment le système fonctionne et donc d’avoir accès aux sources.

Ne sachant sur quel pied danser face à l’invasion des smartphones et à la fin du support de Nokia pour Maemo, le monde de l’open source et du logiciel libre est induit en erreur par le fait qu’Android est basé sur un noyau Linux. Android serait Linux et serait donc libre. Génial ! Il faut développer pour Android ! Google entretient cette confusion en finançant beaucoup de projets libres. Beaucoup de développeurs de logiciels libres sont embauchés par Google qui se forge une image de champion du logiciel libre.

Mais il y’a une arnaque. Si Android est basé sur le noyau Linux, qui est sous GPL, il n’utilise pas les outils GNU. Une grande partie du système Android est bien open source, mais les composants sont choisis soigneusement pour éviter tout code sous licence GPL. Et pour cause… Graduellement, la part d’open source dans Android est réduite pour laisser la place aux composants Google propriétaires. Si vous installez aujourd’hui uniquement les composants libres, votre téléphone sera essentiellement inutilisable et la majorité des applications refuseront de se lancer. Il existe heureusement des projets libres qui tentent de remplacer les composants propriétaires de Google, mais ce n’est pas à la portée de tout le monde et ce ne sont que des pis-aller.

En se battant pour faire tourner du code libre sur leurs ordinateurs, les libristes se sont vu confisquer, malgré leur avance dans le domaine, le monde de la téléphonie et la mobilité.

Mais il y’a pire : si les libristes se battaient pour avoir le contrôle sur les logiciels traitant leurs données, les nouveaux acteurs se contentent de traiter les données des clients sur leurs propres ordinateurs. Les utilisateurs ont perdu le contrôle à la fois du code et du matériel.

C’est ce qu’on appelle le « cloud », le fait que vos données ne sont plus chez vous, mais « quelque part », sur les ordinateurs de grandes entreprises dont le business model est d’exploiter au mieux ces données pour vous afficher le plus de publicités. Un business model qui fonctionne tellement bien que toutes ces entreprises sont, nous l’avons vu, les plus grosses entreprises mondiales.

État de la situation

Les progrès de l’informatique se sont construits en deux grandes vagues successives de collaboration. La première était informelle, académique et localisée dans les centres de recherches. La seconde, initiée par Richard Stallman et portée à son apogée par Linus Torvalds, était distribuée sur Internet. Dans les deux cas, les « hackers » évoluaient dans un univers à part, loin du grand public, du marketing et des considérations bassement matérielles.

À chaque fois, l’industrie et le business confisquèrent les libertés pour privatiser la technologie en maximisant le profit. Dans la première confiscation, les industriels s’arrogèrent le droit de contrôler les logiciels tournant sur les ordinateurs de leurs clients puis, la seconde, ils s’arrogèrent également le contrôle des données desdits clients.

Nous nous trouvons dans une situation paradoxale. Chaque humain est équipé d’un ou plusieurs ordinateurs, tous étant connectés en permanence à Internet. La puissance de calcul de l’humanité a atteint des proportions démesurées. Lorsque vous regardez l’heure sur votre montre Apple, il se fait plus de calculs en une seconde dans votre poignet que dans tous les ordinateurs du programme Appolo réunis. Chaque jour, votre téléphone transmet à votre insu presque autant de données qu’il n’y en avait dans tous les ordinateurs du monde lorsqu’Unix a été inventé.

Pourtant, cette puissance de calcul n’a jamais été aussi concentrée. Le pouvoir n’a jamais été partagé en aussi peu de personnes. Il n’a jamais été aussi difficile de comprendre comment fonctionne un ordinateur. Il n’a jamais été aussi difficile de protéger sa vie privée, de ne pas se laisser influencer dans nos choix de vie.

Les pouvoirs publics et les réseaux éducatifs se sont, le plus souvent, laissé prendre au mensonge qu’utiliser les nouvelles technologies était une bonne chose. Que les enfants étaient, de cette manière, éduqués à l’informatique.

Utiliser un smartphone ou une tablette éduque autant à l’informatique que le fait de prendre un taxi éduque à la mécanique et la thermodynamique. Une personne peut faire des milliers de kilomètres en taxi sans jamais avoir la moindre notion de ce qu’est un moteur. Voyager avec Ryanair ne fera jamais de vous un pilote ni un expert en aérodynamique.

Pour comprendre ce qu’est un moteur, il faut pouvoir l’ouvrir. L’observer. Le démonter. Il faut apprendre à conduire sur des engins simplifiés. Il faut en étudier les réactions. Il faut pouvoir discuter avec d’autres, comparer un moteur avec un autre. Pour découvrir l’aérodynamique, il faut avoir le droit de faire des avions de papier. Pas d’en observer sur une vidéo YouTube.

Ce qui nous semble évident avec la mécanique a été complètement passé sous silence avec l’informatique. À dessein, les monopoles, désormais permis, tentent de créer une expérience « magique », incompréhensible. La plupart des développeurs sont désormais formés dans des « frameworks » de manière à ne jamais avoir à comprendre comment les choses fonctionnent sous le capot. Si les utilisateurs sont les clients des taxis, les développeurs devraient, dans la vision des Google, Apple et autre Facebook, être des chauffeurs Uber qui conduisent aveuglément, sans se poser de questions, en suivant les instructions.

L’informatique est devenue une infrastructure humaine trop importante pour être laissée aux mains de quelques monopoles commerciaux. Et la seule manière de leur résister est de tenter de minimiser leur impact sur nos vies. En refusant au maximum d’utiliser leurs solutions. En cherchant des alternatives. En contribuant à leur création. En tentant de comprendre ce que font réellement ces solutions « magiques », avec nos ordinateurs, nos données et nos esprits.

L’informatique n’est pas plus compliquée ni plus ésotérique qu’un moteur diesel. Elle a été rendue complexe à dessein. Pour augmenter son pouvoir de séduction. Jusqu’aux termes « high-tech » ou « nouvelles technologies » qui renforcent, volontairement, l’idée que la plupart d’entre nous sont trop bêtes pour comprendre. Une idée qui flatte d’ailleurs bon nombre d’informaticiens ou de bidouilleurs, qui se sentent grâce à cela supérieurs alors même qu’ils aident des monopoles à étendre leur pouvoir sur eux-mêmes et leurs proches.

Le chemin est long. Il y a 20 ans, le concept d’open source m’apparaissait surtout comme philosophique. Aujourd’hui, j’ai découvert avec étonnement que je me plonge de plus en plus souvent dans le code source des logiciels que j’utilise quotidiennement pour comprendre, pour mieux les utiliser. Contrairement à la documentation ou aux réponses sur StackOverFlow, le code source ne se trompe jamais. Il décrit fidèlement ce que fait mon ordinateur, y compris les bugs. Avec l’entrainement, je me rends compte qu’il est même souvent plus facile de lire le code source des outils Unix que de tenter d’interpréter des dizaines de discussions sur StackOverFlow.

Le logiciel libre et l’open source sont la seule solution que j’envisage pour que les ordinateurs soient des outils au service de l’humain. Il y a 20 ans, les idées de Richard Stallman me semblaient extrémistes. Force est de constater qu’il avait raison. Les logiciels propriétaires ont été essentiellement utilisés pour transformer les utilisateurs en esclaves des ordinateurs. L’ordinateur n’est alors plus un outil, mais un moyen de contrôle.

La responsabilité n’en incombe pas à l’individu. Après tout, comme je l’ai dit, il est presque impossible d’acheter un téléphone sans Google. L’individu ne peut pas lutter.

La responsabilité en incombe aux intellectuels et aux professionnels, qui doivent élever la voix plutôt que d’accepter aveuglément des décisions institutionnelles. La responsabilité en incombe à tous les établissements du secteur de l’éducation qui doivent poser des questions, enseigner le pliage d’avions de papier au lieu d’imposer à leurs étudiants de se créer des comptes sur les plateformes monopolistiques pour accéder aux données affichées sur les magnifiques écrans interactifs financés, le plus souvent, par Microsoft et consorts. La responsabilité en incombe à tous les militants, qu’ils soient écologistes, gauchistes, anticapitalistes, socialistes, voire même tout simplement locaux. On ne peut pas militer pour l’écologie et la justice sociale tout en favorisant les intérêts des plus grandes entreprises du monde. On ne peut pas militer pour le local en délocalisant sa propre voix à l’autre bout du monde. La responsabilité en incombe à tous les politiques qui ont cédé le contrôle de pays, de continents entiers à quelques entreprises, sous prétexte de gagner quelques voix lors de la prochaine élection.

Je ne sais pas encore quelle forme prendre la troisième grande collaboration de l’informatique. Je sais juste qu’elle est urgente et nécessaire.

Recevez les billets par mail ou par RSS. Max 2 billets par semaine, rien d’autre. Adresse email jamais partagée et définitivement effacée lors du désabonnement. Dernier livre paru : Printeurs, thriller cyberpunk. Pour soutenir l’auteur, lisez, offrez et partagez des livres.

Ce texte est publié sous la licence CC-By BE.

May 09, 2022

Two weeks later, I'm still feeling the energy from our first in-person DrupalCon in two years!

This blog post is Part 3 of my DrupalCon keynote recap. In case you missed it, you can read up on Part 1 and Part 2. Part 1 focused on Drupal 10 updates. Part 2 talked about our new vision statement.

In my keynote, I also mapped out a potential strategy for Drupal 11. In this blog post, I explain Drupal 11's strategy, and how it aligns with our updated vision statement.

Drupal 11 to focus on a Composable Core, helped by Project Browser, Starter Templates and Automated Updates

Drupal 11's strategy is focused on (1) empowering ambitious site builders and (2) accelerating innovation in our contributed modules repository.

To accomplish these two goals, Drupal will have to double down on "composability", which is reflected by the six proposed initiatives below. I'm code-naming the two-year strategy for Drupal 11 "Composable Core".

Six focus areas for Drupal 11

Project Browser

In Drupal 9, we have over 8,000 modules and themes. In those 8,000 projects are some amazing innovations. But right now, it's hard for site builders to find them.

Many first-time adopters don't even realize Drupal can be extended with all these contributed modules and themes. Some site builders even give up on Drupal because once Drupal is installed, they don't know what to do next.

So, we have an opportunity to make all these great innovations easier to find.​​ The Project Browser Initiative would recommend or highlight great Drupal modules to use. It would also enable a one-click install process.

Under the hood, modules are still installed with Composer, making them easy to maintain and update.

Check out this video to learn more about Project Browser:

Starter Templates

While Project Browser would help site builders discover and install individual modules, it is not unusual to use 30+ contributed modules to build a site. It can take a lot of work to find and configure these modules, and to make sure they all work well together.

This is where the new Starter Templates concept comes in. Starter Templates are about installing and configuring groups of modules. For example, Starter Templates for an event website or a product website would include all of the necessary modules and configuration required for that type of website.

This concept bears a lot of resemblance with Drupal's 15-year-old concept of Drupal distributions. The goal of Starter Templates, however, is to be a lot easier to build and maintain than distributions.

Drupal site starter templates compared to distributions; starter templates are easier to implement and maintain

We don't know yet how exactly we'd implement Starter Templates, but we have some initial ideas. Join the #distributions-starter-templates Slack channel if you're interested in contributing.

Automated Updates

For Drupal 11, we will continue our work on the Automated Updates Initiative, which is meant to make updates to Drupal much easier.

Check out the video below for an update on Drupal's Automated Updates initiative:

GitLab Initiative

Accelerating innovation by empowering contributors continues to be a key priority for Drupal. We will keep working on the GitLab Initiative to bring better collaboration and development tools to Drupal contributors.

Check out this video for the latest on the GitLab Initiative:

The Great Module Migration

This proposed initiative focuses on making Drupal Core smaller. How? By responsibly moving more modules from core to contrib. This mean less code to maintain in core, so that Drupal can focus on innovation. Certain modules can also innovate faster as a contributed module.

To evaluate which core modules we might migrate, we developed a ranking system. The system evaluates each module's capabilities, adoption, strategic value, and maintenance effort.

Based on this early ranking system, we found that we could remove approximately 16 modules from core and keep approximately 64. Some of these modules could already be removed in Drupal 10. Drupal 11 could be 20% smaller compared to Drupal 9.

We believe it's safe to make core smaller, especially with a strong focus on Project Browser, Starter Templates and Automatic Updates.

Drupal 11 readiness

As a part of Drupal 11 readiness, we will continue to manage our third-party dependencies to keep Drupal secure.

Should we do more?

I'd love to see us do more in Drupal 11. I wish we could invest in embracing web components, building a decoupled administration backend, modernizing Views, and much more.

Investment like this often require small teams of dedicated developers; i.e. 3-5 developers for 6 to 12 months.

To get even more done for Drupal 11, it's important that organizations consider paying Drupal developers to work on larger, long-term contributions.

I covered this concept in past blog posts, such as the privilege of free time in Open Source and balancing Makers and Takers to sustain Open Source.

In the next year, the Drupal Association will start taking additional steps towards incentivizing larger contributions. Needless to say, I'm very excited about that. Stay tuned for more on that topic.

Let's get building

The early planning phases of a new release are an exciting time to discuss Drupal's potential for the future, and focus on ideas that will make the most impact for our users. I'm excited for us all to collaborate on Drupal 11 in the coming years.

May 06, 2022

Complètement inexistante il y a à peine soixante ans, l’industrie informatique est aujourd’hui devenue la plus importante du monde. Le monde est contrôlé par l’informatique. Comprendre l’informatique est devenu l’une des seules manières de préserver notre individualité et de lutter contre les intérêts d’une minorité.

Vous n’êtes pas convaincu de l’importance de l’informatique ?

En termes de capitalisation boursière, l’entreprise la plus importante du monde à l’heure où j’écris ces lignes est Apple. La seconde est Microsoft. Si l’on trouve un groupe pétrolier en troisième place, Alphabet (ex-Google) vient en quatrième et Amazon en cinquième place. En sixième place on trouve Tesla, qui produit essentiellement des ordinateurs avec des roues et, en septième place, Meta (ex-Facebook). La place de Facebook est particulièrement emblématique, car la société ne fournit rien d’autre que des sites internet sur lesquels le temps de cerveau des utilisateurs est revendu à des agences publicitaires. Exploiter cette disponibilité de cerveau également le principal revenu d’Alphabet.

Je pense que l’on n’insiste pas assez sur ce que ce classement boursier nous apprend : aujourd’hui, les plus grands acteurs de l’économie mondiale ont pour objectif premier de vendre le libre arbitre et la disponibilité des cerveaux de l’humanité. Le pétrole du vingt-et-unième siècle n’est pas « le big-data », mais le contrôle de l’esprit humain. Alphabet et Facebook ne vendent ni matériel, ni logiciels, mais bien un accès direct à cet esprit humain dans sa vie privée. Microsoft, de son côté, tente de vendre l’esprit humain dans un contexte professionnel. Bien qu’ayant également des intérêts publicitaires, une grande partie de son business est de prendre le contrôle sur les travailleurs pour ensuite le « sous-louer » aux employeurs, trop heureux de contrôler leurs employés comme jamais.

Tesla veut contrôler les déplacements des humains. C’est d’ailleurs une constante chez Elon Musk avec ses projets d’Hyperloop, de creusage de tunnels voire de conquête spatiale. Amazon cherche à contrôler toutes vos interactions marchandes en contrôlant les commerçants, que ce soit dans les magasins physiques ou en ligne (grâce à une hégémonie sur l’hébergement des sites web à travers Amazon S3).

Apple cherche, de son côté, à obtenir un contrôle total sur chaque humain qui entre dans son giron. Regardez autour de vous le nombre de personnes affublées d’Airpods, ces petits écouteurs blancs. Lorsque vous vous adressez à l’une de ces personnes, vous ne parlez pas à la personne. Vous parlez à Apple qui décide ensuite ce qu’elle va transmettre de votre voix à son client. Le client a donc payé pour perdre le contrôle de ce qu’il entend. Le client a payé pour laisser à Apple le choix de ce qu’elle va pouvoir faire avec son téléphone et son ordinateur. Si les autres sociétés tentent chacune de contrôler le libre arbitre dans un contexte particulier, Apple, de son côté, mise sur le contrôle total d’une partie de l’humanité. Il est très simple de s’équiper en matériel Apple. Il est extrêmement difficile de s’en défaire. Si vous êtes un client Apple, faites l’expérience mentale d’imaginer vivre sans aucun produit Apple du jour au lendemain, sans aucune application réservée à l’univers Apple. Dans cette liste, Apple et Tesla sont les seules à fournir un bien tangible. Ce bien tangible n’étant lui-même qu’un support à leurs logiciels. Si ce n’était pas le cas, Apple serait comparable à Dell ou Samsung et Tesla n’aurait jamais dépassé General Motors en ayant vendu qu’une fraction des véhicules de ce dernier.

Nous pouvons donc observer qu’une partie importante de l’humanité est sous le contrôle de logiciels appartenant à une poignée de sociétés américaines dont les dirigeants se connaissent d’ailleurs intimement. Les amitiés, les contacts entre proches, les agendas partagés, les heures de nos rendez-vous ? Contrôlés par leurs logiciels. Les informations que vous recevez, privées ou publiques ?Contrôlées par leurs logiciels. Votre position ? Les photos que vous êtes encouragés à prendre à tout bout de champ ? Les produits que vous achetez ? Contrôlés par leurs logiciels ! Le moindre paiement effectué ? Hors paiements en espèce, tout est contrôlé par leurs logiciels. C’est encore pire si vous utilisez votre téléphone pour payer sans contact. Ou Paypal, la plateforme créée par… Elon Musk. Les données des transactions Mastercard sont entièrement revendues à Google. Visa, de son côté, est justement huitième dans notre classement des sociétés les plus importantes.

Les déplacements ? Soit dans des véhicules contrôlés par les mêmes logiciels ou via des transports requérants des apps contrôlées… par les mêmes logiciels. Même les transports publics vous poussent à installer des apps Apple ou Google, renforçant leur contrôle sur tous les aspects de nos vies. Heureusement qu’il nous reste le vélo.

Votre vision du monde et la plupart de vos actions sont aujourd’hui contrôlées par quelques logiciels. Au point que le simple fait de ne pas avoir un smartphone Google ou Apple est inconcevable, y compris par les pouvoirs publics, votre banquier ou, parfois, votre employeur ! Il est d’ailleurs presque impossible d’acheter un smartphone sur lequel Google n’est pas préinstallé. Faites l’expérience : entrez dans un magasin vendant des smartphones et dites que vous ne voulez pas payer pour Apple ou Google. Voyez la tête du vendeur… Les magasins de type Fnac arborent fièrement des kilomètres de rectangles noirs absolument indistinguables les uns des autres. Google paye d’ailleurs à Apple plus d’un milliard de dollars par an pour être le moteur de recherche par défaut des iPhones. Même les affiches artisanales des militants locaux ne proposent plus que des QR codes, envoyant le plus souvent vers des pages Facebook ou des pétitions en ligne hébergées par un des monopoles suscités.

Vous pouvez trouver cet état de fait confortable, voire même pratique. Pour moi, cet état de fait est à la fois triste et dangereux. C’est cet engourdissement monopolistique qui nous paralyse et nous empêche de résoudre des problématiques urgentes comme le réchauffement climatique et la destruction des écosystèmes. Tout simplement, car ceux qui contrôlent nos esprits n’ont pas d’intérêts directs à résoudre le problème. Ils gagnent leur pouvoir en nous faisant consommer, nous faisant acheter et polluer. Leur business est la publicité, autrement dit nous convaincre de consommer plus que ce que nous aurions fait naturellement. Observez que, lorsque la crise est pour eux une opportunité, les solutions sont immédiates. Contre le COVID, nous avons accepté sans broncher de nous enfermer pendant des semaines (ce qui a permis la généralisation de la téléconférence et des plateformes de télétravail fournies, en majorité, par Google et Microsoft) et de voir notre simple liberté de déplacement complètement bafouée avec les pass sanitaires entérinant l’ubiquité… des smartphones et des myriades d’applications dédiées. Nous nous sommes moins déplacés (au grand plaisir de Facebook qui a servi d’intermédiaire dans nos relations sociales) et les smartphones sont devenus quasi-obligatoires pour présenter son QR code à tout bout de champ.

Nous avons accepté, sans la moindre tentative de rébellion, de nous faire enfermer et de nous faire ficher par QR code. En termes de comparaison, rappelons que la simple évocation de l’augmentation du prix de l’essence a entrainé l’apparition du mouvement des gilets jaunes. Mouvement qui s’est construit sur Facebook et a donc augmenté l’utilisation de cette plateforme.

Pour regagner son libre arbitre, je ne vois qu’une façon de faire : comprendre comment ces plateformes agissent. Comprendre ce qu’est un logiciel, comment il est apparu et comment les logiciels se sont historiquement divisés en deux catégories : les logiciels propriétaires, qui tentent de contrôler leurs utilisateurs, et les logiciels libres, qui tentent d’offrir de la liberté à leurs utilisateurs.

Le pouvoir et la puissance des logiciels nous imposent de les comprendre, de les penser. Sans cela, ils penseront à notre place. C’est d’ailleurs déjà ce qui est en train de se produire. Les yeux rivés sur notre écran, les oreilles bouchées par des écouteurs, nous réagissons instinctivement à ce qui s’affiche sans avoir la moindre idée de ce qui s’est réellement passé.

Les logiciels ne sont pas « magiques », ils ne sont pas « sexys » ni « hypercomplexes ». Ce ne sont pas des « nouvelles technologies ». Tous ces mots ne sont que du marketing et l’équivalent sémantique du « lave plus blanc que blanc de nos lessives ». Ce ne sont que des mots infligés par des entreprises au pouvoir démesuré dont le cœur est le marketing, le mensonge.

En réalité, les logiciels sont une technologie humaine, compréhensible. Une série de choix arbitraires qui ont été faits pour des raisons historiques, des séries de progrès comme des retours en arrière. Les logiciels ne sont que des outils manipulés par des humains. Des humains qui, parfois, tentent de nous faire oublier leur responsabilité, de la camoufler derrière du marketing et des icônes aux couleurs scintillantes.

Les logiciels ont une histoire. J’ai envie de vous la raconter…

(à suivre)

Recevez les billets par mail ou par RSS. Max 2 billets par semaine, rien d’autre. Adresse email jamais partagée et définitivement effacée lors du désabonnement. Dernier livre paru : Printeurs, thriller cyberpunk. Pour soutenir l’auteur, lisez, offrez et partagez des livres.

Ce texte est publié sous la licence CC-By BE.

May 05, 2022

Autoptimize can help improve your site’s performance, but in some cases after installing and activating you might encounter issues with your site. Although frustrating and maybe even scary, these problems can generally be easily resolved by re-configuring Autoptimize and I’ll be happy to share how you can do that. First off: if the problem is limited to just one (or two) page(s), go to that page’s...


May 04, 2022

With Drupal 10 around the corner, it's time to start laying out Drupal 11's development roadmap.

It's important we begin that work by reflecting on Drupal's purpose. Drupal's purpose has evolved over the years. In the past, the goal might have been to build the world's most powerful CMS. Today, I believe Drupal has become much bigger than a CMS alone.

Drupal enables everyone to participate in an Open Web. The web is one of the most important public resources. As a result, the Drupal community's shared purpose is to make that resource open, safe, and accessible to all. With 1 in 30 websites running on Drupal, we have a lot of influence on building the future of the web we want to see. In fact, we have an opportunity to help build a digital future that is better than the one we have today.

Drupal enables everyone to participate in an Open Web, a decentralized, public resource that is open, safe and accessible to all

To align with that purpose, and to drive the most impact, our vision also has to evolve. Five years ago, I declared that Drupal is for ambitious digital experiences. I'd argue that we have achieved that vision by investing in headless Drupal, Media, Layout Builder, and additional features that help enable the creation of ambitious digital experiences.

That is why I propose evolving our vision statement to "Drupal is for ambitious site builders".

Drupal is for ambitious site builders

Attracting more Drupal site builders will increase Drupal's potential user base, and in turn create a more open, accessible and inclusive web for all.

This shift also brings us back to our roots, which I've talked about in several of my previous DrupalCon keynotes.

What is an ambitious site builder?

An ambitious site builder sits in between the developer hand-coding everything using a framework, and the content author using a SaaS solution. There is a gap between developers and content authors that Drupal fills really well.

Drupal's unique strength is the Ambitious Site Builder

An ambitious site builder can get a lot of things done by installing and configuring modules, and using Drupal through the UI. But when needed, they can use custom code to make their site exactly how they want it to be. Ambitious site builders are the reason why Drupal became so successful in the first place.

I'm excited to see this vision come to life through the key initiatives for Drupal 11, which I'll talk about in my next blog post.

May 03, 2022

Last week, 1,300 Drupalists gathered in Portland, Oregon for DrupalCon North America. It was the first in-person DrupalCon in more than two years. I can't tell you how amazing it was to see everyone face-to-face.

In good tradition, I delivered my State of Drupal keynote. You can watch the video of my keynote or download my slides (262 MB).

I covered a lot of ground in this presentation, so I broke down my written summary into a three-part blog series. Part 1 below focuses on Drupal 10 updates. I'll be publishing Part 2 and Part 3 later this week, which will focus on Drupal's evolved vision and Drupal 11 proposed initiatives.

Drupal stands with Ukraine

I couldn't begin my presentation without acknowledging the loss of life and destruction in Ukraine. It's impacting many in the Drupal community, which is heartbreaking.

You may not be aware, but Ukraine is the sixth most active country in the world in terms of Drupal contributions. If you were to look at these contributions per capita, Ukraine's contributions are even more significant.

Both myself and the Drupal Association strongly condemn the Russian attacks on Ukraine. Many of us might want to know how to help. The Drupal Association has compiled a list of organizations that are accepting charitable donations.

Updates on Drupal 10

From there, I gave an update on Drupal 10. We had targeted a Drupal 10 release date of June 2022, but we made the decision to postpone until December 2022.

We had to move the date back because we have more work to do on the CKEditor 5 migration path. We're upgrading from CKEditor 4 to CKEditor 5. CKEditor 5 is a complete rewrite, with no upgrade path or backwards compatibility.

The Drupal community (and Acquia in particular) has spent thousands of hours working on an upgrade path for CKEditor to make the upgrade easy for all Drupal users. While that has gone well, we need some additional time to work through the remaining upgrade challenges. Fortunately, we are getting great support from CKSource, the company behind CKEditor.

Next, I walked through three important facts about Drupal 10.

  1. Symfony 6.2 — Drupal 10 will upgrade Symfony – a PHP framework that Drupal relies on heavily – from Symfony 4 to Symfony 6.2. At the time of the Drupal 10 release, Symfony 6.2 will be the latest and greatest release. For planning purposes, if you use Symfony components in your custom Drupal modules, you will have to upgrade those to Symfony 6.x.
  2. PHP 8.1 — We have changed the minimum PHP requirement from PHP 7.4 for Drupal 9 to PHP 8.1 for Drupal 10. This is in large part because Symfony 6.2 will require PHP 8.1. Drupal users will benefit from various improvements in the new version of PHP. It also means you might have to upgrade any custom code. Because Drupal 9.3 works with PHP 8.1, you could start that work now with Drupal 9.3. It's a good way to prepare for Drupal 10.
  3. Drupal 9 end-of-life — Drupal 9 end-of-life will happen in November 2023. Once Drupal 10 is released, you will have 11 months to upgrade your Drupal 9 sites to Drupal 10. The good news is, this should be the easiest upgrade in the history of Drupal. On Drupal 9's release date, 71% of deprecated API uses in contributed projects had automated conversions. Today, 93% of deprecated API uses for Drupal 10 across all contributed projects have automated conversions. And we're working on getting that even higher by the time that Drupal 10 is released.

With that, I provided some exciting updates on the five major Drupal 10 initiatives.


Drupal's new frontend theme, named Olivero, is now stable. It's the most accessible theme we've ever shipped. During DrupalCon, Olivero also became the default theme for Drupal 10. Everyone who installs Drupal 10 will be greeted by a new frontend theme. That is significant because we used the current default theme, Bartik, for 11 years.


Drupal's new backend theme, called Claro, also became the new default administration theme at DrupalCon. Another major milestone and reason to celebrate!


Starterkit, a new way of creating themes in Drupal, is on track to be stable by Drupal 10's new release date. Releasing Starterkit means that we can move faster with theming improvements in Drupal Core. It also means that end users won't need to worry about whether upgrading Drupal breaks any of their sites' themes.

Instead of sub-theming a core base theme, Starterkit generates a starter theme for you from its latest defaults. This new theme will be more of a clone or fork, and will not have a runtime dependency on a core base theme.

CKEditor 5

We have made great progress on our content authoring experience. Check out this video for the latest update:

Automated updates

Automated updates, the Drupal community's number one feature request, is progressing well.

The plan is to have Automatic Updates in one of the first minor versions of Drupal 10, or even in 10.0 in December if the community can help us test and finalize it in time. Check out this video to learn more:

In Parts 2 and 3 of this blog series later this week, I'll focus on our strategy and proposed initiatives for Drupal 11.

I'd like to thank everyone who made our first in-person DrupalCon in two years a reality. It was amazing to see everyone's faces again and collaborate in person. Your contributions and hard work, as always, are inspiring to me!

I would also like to thank all the people that helped with my keynote. In no particular order, they are: Ash Sullivan, Alex Bronstein, Matthew Grasmick, Gábor Hojtsy, Jess (xjm), Ted Bowman, Baddý Sonja Breidert, Leslie Glynn, Tim Lehnen, Adam Bergstein, Adam Goodman, Théodore Biadala, and Alex Pott.

April 29, 2022

Here we go with day 3! In the morning, there are always fewer people due to the short night. The gala dinner is always a key activity during Botconf!

The last day started with “Jumping the air-gap: 15 years of nation-state efforts” presented by Alexis Dorais-Joncas and Facundo Munoz. Does “air-gap” means a big castle in the middle of the Internet? That’s the image that usually pops un in our minds. They covered malware targeting “protected environments”. Such malware implement an offline, covert communication mechanism between the compromised systems and the attacker. Think about “Stuxnet”. They found 17 families of such malware and, as usual, attribution was not easy, sometimes controversial. They are two categories:

  • Connected frameworks (with a connected side and an air-gapped side). A classic approach is initial compromise (spear phishing) and a weaponised USB stick is used to reach the air-gapped side. Results are stored back to the USB drive hopping that the user will connect the USB back to the connected side. Another technique is to write commands from the C2 on the USB drive.
  • Offline frameworks (no Internet connectivity). A user must “import” the malware

Automated execution is the most effective technique to launch the malware, for example via LNK remote code execution. In the case of non-automated execution, the main techniques are:

  • Abuse of Windows auto run
  • Planting decoy files to lure victims
  • Rig existing files with malicious code

They reviewed some well-known malware sample and explained the techniques used to interact with the air-gapped systems. To exfiltrate data, they used modified directory entries to hide the content on the USB drive. By example, if you create an invalid directory name, Windows will ignore it and it will be hidden. Another technique is to hook some file-related API and when a specific file is used (ex: Word document), data is appended to documents. This is how the Ramsay malware works.
How to defend against those types of attacks? USB drives is the key element. So, disable/prevent usage at much as possible. When you can’t, disable automatic execution, sanitize USB drives before inserting them in the air-gapped system.

The next talk was presented by Eric Freyssinet: “A vision on Cyberthreats”. There were already talks in the past about the French law enforcement services. Eric today presented a picture of what he’s doing with his team and the challenges they are facing. Years ago, fighting cybercrime was a niche but today, it’s a key element. A keyword mentioned multiple times was “together”: “we have to share together, we have to talk and act together”. A cyberspace command has been created to not only fight cybercrime to also to be present on the Internet and offer services to citizens, such as a 24×7 chat. About the cyber threat landscape, in 2020, there are 100K cases (+21% over 2019). In Q1-Q2 2021, +38% over 2020!. Mail challenges today are fewer data available in cleartext. more and more data to process, cloud environments, and more to come! Criminals also evolve very quickly: “Crime as a Service”, more and more facing open cyber-criminal ecosystems.

After a welcome coffee break, we attended “Detecting and Disrupting Compromised Devices based on Their Communication Patterns to Legitimate Web Services”, presented by Hen Tzaban. This was a remote presentation because the speaker was not able to join us in Nantes. Hen is specialized in data analysis. Today, enterprise protection switched from a blacklist system (too complex to manage and prone to issues) to behavioral monitoring. In the past, look for IOC and block bad IP/domains in proxies/firewalls. Today, it shifted to user behavior because criminals use sites like Twitter, Google, GitHub, Pastebin, etc. Legitimate services! For example: the malware HAMMERTOSS uses Twitter. Akamai developed a framework based on PSD (Power Spectral Density and Neural Networks model. The goal is to detect compromised hosts inside the enterprise. For example for DNS traffic: beaconing, multi-stage channels, and DGA are common techniques. Hen explained how they implemented this technique at Akamai.

The next one was “ProxyChaos: a year-in-review of Microsoft Exchange exploitation” by Mathieu Tartare. Except if you live on a small island, you should be aware of this massive issue. So big that FBI decided itself to clean up infected systems. Quick overview: It’s a suite of vulnerabilities:

  • ProxyLogin
  • When chained, pre-auth RCE
  • On-premise Exchange 2013, 2016 & 2019 are affected (not the cloud version)

It started in January 2021, before being reported to Microsoft, which decided to release an out-of-band patch. In March 2021, mass exploitation started. How does it work? They use CVE-2021-26855 then install a WebShell (ChinaChopper). The name of the webshell is controlled by the attacker, so attribution is easier. What appended in the wild? More than 10 APT groups used this vulnerability. Multiple actors could be on the same server at the same time. Pre-auth means a huge amount of scans. Hafnium was the first group to use the vulnerability. Mathieu reviewed multiple groups’ activities. Matthieu also reviewed “ProxyShell”. The exploitation is a bit different but very similar to ProxyLogon. Vulnerabilities are exploited in chain and a malicious PST file will be used to drop the webshell and more fun happen.

Then, Eric Leblond presented “Suricata and IOCs” (in preview for a workshop in 2023?). After a quick introduction to his company (Stamus Networks) that develops Suricata. Some advanced features were covered by Eric: IPrep, Lua scripting support and dataset. The concept is list matching on sticky buffer keywords. By example:

alert http … (http_user_agent;dataset:isnotset,official_agents;)

You can also use IOC matching with datasets. Here is another example:

alert dns … (dns.rename; dataset:isset,ioc_d,string,load ioc_domains.lst;)

Dataset can be modified on packet path, for example, build a list of HTTP user agents seen on the network! You can also combine datasets. Ex: build a set of UA agents but not for the site from Alexa1M. To improve the integration of MISP and Suricata, a tool has been developed by Sebdraven: IOCmite Concept: improve the integration of MISP & Suricata. MISP > IOCmite > (stocket) > Suricata

After the lunch break, Souhail Hammou presented “Privateloader – The malware behind a havoc-wreaking Pay-Per-Install service”. PPI services monetise wide distribution of malware. There exist public and private PPI services. Once the malware is installed, the loader sent back info to the C2 server for “accounting” purposes. Then the “customer” is billed based on usage. The “PrivateLoader” was detected by Intel471 in 2021. It is developed in C++, uses HTTP for C2 communications and is heavily maintained. Main distribution channel is malicious websites delivering cracked software. The loader has a core module which disables some security features and grabs its configuration. One of the information retrieved is the geographical location. Based on it, different payloads will be sent. It can also target specific hosts depending on a “profile”. Two types of payloads can be downloaded: PE files and browser extensions (for Chromium). Payloads are delivered through Discord URLs. Installed payloads list is sent back to the C2 server. What about tracking PrivateLoader? They created fake bots but “passive” (to not ring a bell) and analyzed the malware dropped on victims.

The very last talk was “Qakbot malware family evolution” presented by Markel Picado Ortiz and Carlos Rubio Ricote. This was the second talk about Qbot. They spent a lot of time analyzing plenty of samples. Qbot has many versions! They showed the multiple changes found in the code. After reviewing the version changes, they gave some statistics about affiliate IDs, versions, and timestamps to visualize who used which version in time.

What about this 9th edition of Botconf? It was so great to meet people in real life! There was 300 attendees coming from almost all continents, avibrant and diverse community. As usual, they already announced the 10th edition that will be held in April 2023 in Strasbourg! Kudos to the crew for this awesome event!

The post Botconf Day 3 Wrap-Up appeared first on /dev/random.

April 28, 2022

The second day is already over. Here is my recap of the talks. The first one was “Identifying malware campaigns on a budget” by Max “Libra” Kersten and Rens Van Der Linden. The idea was to search for malicious activity without spending too much money. Read: “using as few resources as possible”. The solution proposed must be scalable, reusable, and repurposable. From a budget point of view, it was based on Raspberry Pi 3B (~65€) + the cost of electricity and free software. In their research, they used a dataset of 500K malicious emails (that can’t be disclosed but the same applies to any dataset). They normalized the data then applied different modules to them:

  • The first module was used to check the email subjects and, using the Levenshtein distance (number of character changes), they found clusters of emails.
  • The second module was used on lure images (the logos used in phishing campaings to make the victim more confident).
  • The third one was focusing on URLs with passive reconnaissance techniques as well as active techniques.

I was a bit surprised to see the last slides… without really demonstrating the scripts they used (also, nothing was shared). Too bad, I was expecting something that could be reused (like a GitHub repo to clone). An interesting question from the audience: why not use Karton to automate these processes?

Max stayed on stage for a second (long) presentation: “See ya Sharp: A Loader’s Tale”. He explained his research about a specific loader: Cyax-Sharp. What is a loader? It is used to “load” a remote/local payload. It is usually encrypted, obfuscated, and has anti-debugging features. If classic malware samples are analyzed, loaders attract less attention and we lack reports but they are an essential stage in the infection process. The malware ecosystem lacks a naming convention and this payload can be referenced as “ReZer0” or later “Cyax-Shart. This is confusing. He reviewed some capabilities of the loader like disabling WinDefender, and anti-sandboxing techniques (searching for some DLLs). Then, how the configuration is managed. What are the changes over time?

  • The configuration changed: new features added
  • Sleep is configurable and message box can be displayed

Max gave some statistics about his research. He collected 513 samples. Process hollowing is present in 72% of cases. The remaining is spread across MSBuild hollowing, vbc, regsvc or direct launch
Persistence is used in 54%, based on scheduled tasks. Regarding protections, 79% had both enabled (anti-vm, anti-analysis). Payload families? 54% was AgentTesla, others

After a short coffee break, we were back with “Into The Silent Night” presented by Yuta Sawabe and Ryuichi Tanabe. If restrictions are lighter regarding the COVID, they are still some travel issues between countries, and the speakers were not able to join Nantes. They recorded the presentation. Silent Night is the new name of ZLoader. The goal of this research was to track C2 servers. In this case, a DGA is used and make the analysts’ life more difficult. They build a tracking system to collect data, extract threat intel and analyze the results. Silent Night is a modular trojan from the Zeus family, delivered via exploit kits, fake software, phishing, etc. Its C2 communications can be identified via /cp.php, /gate.php or /logs.
The process they used:

  • collect sampled (VT,, Triage)
  • extract config via triage
  • calculate DGA domains
  • collect log files from C2 servers

Some results they shared:

  • 453 samples
  • 22 RC4 keys
  • Peak of Number of infections was in Sep 2021
  • Main country was US

When you know the DGA, domains are registered in advance and you can trace the future attack activities. 32 domains generated per day (not all of them used)

We continued with “A fresh look into the underground card shop ecosystem” with Beatriz Pimenta Klein and Lidia Lopez Sanz. This was interesting because I’ve no experience with these platforms. Where are cards sold?

  • Automated vending cards (AVCS)
  • Marketplaces
  • Forums & chats

They focused on the first type. But, how are they stolen? Via PoS malware that dumps from memory but skimmers remain a classic attack.CVVs are also known as “cards”: phishing pages, digital skimmers, leaks, info stealers. In the next part of the talk, they presented some card shops and compared them:

  • Brian’s Club
  • Legendary Rescator

By the way, the price of a cart can go from $3 to $269 depending on the country, the bank, the expiration date, etc. A lot of card shops are inactive because they organized their own closure, they have been seized by law enforcement agencies, or … exit scan (the most common one). It was interesting to learn that typosquatting is very common in card shops. They share the same cards and… deliver malware samples!

The next talk was presented by Dominika Regéciová: “Yara: Down the Rabbit Hole Without Slowing Down“. This talk was a review of YARA, performances, and changes. Dominika started with a quick review of YARA (who does not this tool developed by VT?). Writing YARA rules is pretty easy but when you need to scan a huge set of data (size or number of files), you’ll quickly face issues… like warnings from YARA or the required scan time. You’ll have to optimize the rules! The first optimization was to take into account “atoms” selection from strings. How YARA handles strings. Regular expressions are a common issue with YARA and may drastically affect the speed. The next issue was related to the “too many matches” problem. Dominika explained how to write better rules. She demonstrated the optimization with an example that was executed in 3 seconds instead of 45 mins (without optimization). If you’re interesting int this topic, have a look here.

Then, we had a talk provided by Alibaba Cloud: “Detecting emerging malware on cloud before VirusTotal can see it” by Anastasia Poliakova and Yuriy Yuzifovich. Why this research? Third-party validation has a cost (latency, costs!). Sometimes tools like VT give ambiguous results. Is a low VT score a sign of maliciousness? Also, many malware samples targeting Chinese customers are underreported to VT. To avoid these problems, Alibaba Cloud decided to start its own detection tool based on ssdeep… They explained in a lot of detail how to build a tool more efficiently than… VT! (that’s what they said). I had a discussion with other people about this and we all had the same feeling: Are they prepared a competitor to VT?

After the lunch break, we restarted with “Warning! Botnet is in your house…” by Vitaly Simonovich and Sarit Yerushalmi. For sure, I was curious about this title but it was not what I expected, however, the content was good. The research goals were: how botnets operate, for which purpose, and how it started.
The initial discovery was CVE-2017-9841 (target: PHPUnit RCE). It starts with a POST request and the return data is a PHP script with a system() and a curl + payload execution. The payload is “” which install a Python script in a crontab. Python payload grabs a zip file, unzip it and executes the new Python payload “”. This payload makes an HTTP request with a user-agent. In return, you get some JSON data. They found multiple bundles of files that targeted multiple vulnerabilities (RCE, RFI, …)
But what was the botnet purpose? To understand this, they created a honeypot and simulated a fake compromised host. After 1h, the attacker contacted the host. He added a second web shell, escalated his privileges, and got full control of the server. Third-party services were also used: GitHub & Pastebin to store more payloads. The bot was called “KashmirBlack”, why? It was the name of a git repo.
Later, they found the use of a dropbox account… and the associated token to access it.
Some numbers:

  • 285 bots
  • 480 attacks / day / bot
  • 140K attacks / day
  • 0.5% success
  • 1000 new bots / day

The next one was “How Formbook became XLoader and migrated to macOS” by Alexey Bukhteyev and Raman Ladutska. Here again, they were not able to travel and the talk was presented via an interactive Zoom session. Overview of the malware: banker & stealer malware. 100+ apps targeted. 6y old, 3000+ campaigns, worldwide targets. Now, called XLoader and targets macOS & Windows. First spotted in 01/2016, may 2018 last post from authors. In Oct 2020, XLoader was born. Formbook sales stopped and the XLoader model changed. They explained carefully how obfuscation is used to hide the functions and strings. More information is available here.

After the coffee break, Vasiliy Berdnikov and Aseel Kayal presented “SandyBlacktail: Following the footsteps of a commercial offensive malware in the Middle East”. This one was presented under TLP:Amber. Great reviews of the malware with plenty of details.

The next one was “Smoke and Fire – Smokeloader Historical Changes and Trends” presented by Marcos Alvarez. He started with a question to the audience. Many people know SmokeLoader but not many of us put our hands in the code. He did… intensively! His talk covered the findings and all changes across the years. But first, he explained with this loader is popular: Based on its simple business model, the cost, and complexity. Indeed it has many core features like anti-analysis, persistence, network & crypto features, payload injection, and extensions (modules). In the next part of the presentation, Marco presented all changes since 2011(!).

Why is it a successful loader?

  • Business model (direct with the author)
  • Cost
  • Complexity

Its core features are: anti-analysis, persistence, network, crypto, payload injection and… extensions (plugins) From an operational aspect: Initial recon + modules -> Data harvesting + infostealer -> Final payload (banker, ransomware, RAT).

The last talk was “PARETO: Streaming Mimicry” presented by Inna Vasilyeva. This was a sponsored talk but technical enough! PARETO is a botnet that infected Android devices (1M) to spook CTV apps. Inna explained that the malware mimics a streaming TV product to generate a higher price for ad impressions. This is achieved via the TopTopSDK. After technical details, she explained that a takedown operation has been started. Google and Roku were contacted as well as LE agencies.

This day ended with a round of funny/interesting lightning talks about the following topics:

  • ONYPHE (with a demo of a specific URL shown earlier today : /upl.php
  • Advanced Persistent Speaker @ Botconf and DESKTOP-Group status
  • Crowdsourcing the demise of Twitter’s business model
    • JusticeRage/twitter-blocklist
  • WTF VT?!
  • Should we care about formula injection?
  • Binary Analysis course
  • Hunting with Nuclei
  • Iranian & Russian eCrime: It’s complicated
  • Yet another dev fail?
  • Botnet Tracker
  • DDX – Detection, Detonation & Config eXtraction
  • Where’s my botconf recording?

Day 2 is over, the gala dinner is over, it’s now time to get some sleep hours for the last day!

The post Botconf Day 2 Wrap-Up appeared first on /dev/random.

April 27, 2022

Incredible! Here is my first wrap-up for two years! Now that the COVID seems under control, it’s so good to be back at conferences and meet a lot of good friends. Like most of the events, Botconf was canceled, postponed, uncertain until the COVID situation was better and, finally, it occurs live! For this edition, we are in Nantes, France. I arrived yesterday to attend a workshop performed by about MWDB. I learned some interesting concepts and will probably write one or two blog articles about this tool.

The first day started with some words by Eric Freyssinet, the boss of the conference. This edition was back to normal with around 300 people registered, and coming from multiple countries. After some words about the sponsors (without them, no conference), he remembered that Botconf respects the TLP and privacy of attendees (about pictures, by example). With this edition, we are also back to the roots, the very first edition was already organized in Nantes in… 2013!

The first time slot was assigned to Berk Albayrak and Ege Balci who presented “Behind the Scenes of QBot”. The talk was given under TLP:Amber so I respect what Eric said and I won”t disclose any information they provided. They make an in-depth analysis of the QBot infrastructure. QBot (also known as Qakbot) is a well-known bot that is active for a long time. They provided a lot of useful information about the botnet internals, how it works, and some statistics about victims.

The second talk was “RTM: sink-holing the botnet” presented by Rustam Mlirkasymov and Semyon Rogachev. They started to work on this case in 2019 with the help of law enforcement agencies across multiple countries that helped to collect enough pieces of evidence to catch the attackers behind the botnet. It’s not a secret that Russia remains the top-1 provider of malware. Most banking groups in 2008-2017 spoke Russian. The RTM is spread through spear-phishing emails and has multiple stages:

  • First stage: reconnaissance module (verifiy the presence of financial activity)
  • Second stage (RTM Core): download of the malware from a C2 server like Pony Stealer. It has many commands like reboot, shutdown, video-process, …
  • Third module (RTM Modules): many modules can be installed (like lateral movement, money stealing)

Of course, ransomware can also be deployed! The reconnaissance phase is based on the browser history (looking for the presence of interesting URLs). The most interesting part was the different ways used by the malware to connect to C2 servers: via blogs, via .bit domains or… based on Bitcoin transactions! The technique was explained, the IP address bytes are extracted from two transactions (2 x 2 bytes). Note that all C2 were proxy servers. When they understood how the Bitcoin transactions were used to generate the C2 IP. They create specifically crafted ones to “insert” a rogue IP address (that they managed) as a fake C2 server. This server was used to collect information (playing Man in the Middle) and redirect the traffic to official C2 servers. Brilliant technique!

The next presentation was “Private Clubs For Hackers: How Private Forums Shape The Malware Market” by David Décary-Hétu and Luca Brunoni. David is a legal guy and explained that there is a huge gap between legal people and “techies” but they have to work together to fight against criminals. The idea of this talk was to reduce this gap. They followed the criminal behavior of bad guys across different forums. These forums are used as sharing platforms. Sometimes, they are also used to perform transactions. Some of them are “public” while others are restricted (“private”) to keep out law enforcement agencies, researchers, etc. They try to create a safer and trusted environment… in theory! The initial question was: “Is there a myth of the elite or private forums?”. They compared two forums: one public with ~60K users and a private one with ~185K users and focused on malware trends. First finding, there is not a big difference in malware types (the goal remains the same: access the compromised computer and exfiltrate data). The type of access is RAT or bot but, on the private forum, more RAR were offered. About the exfiltration, the public forum offered more “stealers”. They also looked at prices, the reputation of vendors. What is the key difference? Not much:

  • On the private forum, reputation and creation of good profiles is key
  • On the private forum, they asked to not attack Russia
  • Both provide a high sense of inpunity.

Interesting talk, not technical but it provided a good overview of the “underground” market!

After the lunch, Leon Böck presented “Insights and Experiences from Monitoring Multiple P2P Botnets“. Based on the blind men and the elephant; Leon talked about similarities with botnets: what are the targeted devices? the behavior? the affected regions? First, efforts are necessary to perform the reserve engineering of the malware and be able to understand the P2P protocol used to communicate with the C2 infrastructure. Leon explained the approach that was used in this research, based on crawlers (getting data from an external point of view) and sensors (which are part of the P2P network). The goal was to create a “BMS” or Botnet Monitoring System. After a detailed review of the infrastructure in place, Leon completed the talk with some statistics he gathered, like the presence of a diurnal pattern in many botnets.

The next talk was tagged as TLP:Green: “TA410: APT10’s distant cousin” presented by Alexandre Côté Cyr and Matthieu Faou. They mentioned that a blog post will be released by Eset soon…

Then, “Operation GamblingPuppet: Analysis of a multivector and multiplatform campaign targeting online gambling customers” was presented by Jaromir HOREJSI and Daniel Lunghi. This research started with a sample of Xnote connected to the Operation DRBControl’s domain name. The infection vector was a fake chat application called “Mimi” (“secret” in Chinese). It targeted Windows and macOS computers. Built on ElectronJS, the malicious payload was delivered via extra code added at the end of the file electron-main.js. Another technique was a persistent XSS combined with a fake Flash installed. Yes, even if Flash is dead for a while, this technique still works. A third infection vector discovered was a fake .dmg to install BitGet (a Singapore cryptocurrency company application). Then, some payloads were reviewed (example: oRAT on macOS or AsyncRAT on Windows). Finally, the infrastructure was reviewed: 50 C2 servers, and 12 different RAT families(!). Based on “rude” strings, comments, it was clear that the actors were Chinese people:

After the afternoon coffee break, the next presentation was “Fingerprinting Bot Shops: Venues, Stealers, Sellers” by Bryan Oliver and Austin Turecek. The idea behind this research was to understand how bot shops and their ecosystems are used today. Some facts:

  • Infostealers are rent, data exfiltrated and used to bot shops
  • Bots are used to obtain initial access and/or monetised
  • Combo “email:pass” is no longer enough for initial access brokers! Bot shops are the way to go with infostealer and their data (ex: cookies, MFA details, …)
  • They covered 38 account shops, 5 bot shops over the last 3y
  • Main components are bot shops, malware developers, cloud providers
  • Some well-known bot shops: Genesis, Russian Market, Amigos, 2Easy
  • Some cloud providers: Ross Cloud, Cash Cloud, Dark Logs Cloud, …Cloud Altery

What about monetization?

  • Logs may be sold by category (and resold!)
  • Logs can be used by multiple actors
  • Persistent infections opens up new opportunities with status updates
  • Cashing out? Cryptocurrency of course!
  • Slack, Citrix, SSO, Okta access are sold and searchable (used for lateral movement)
  • Some bots on Russian market are identical: rent it on one, it disappear on the second

Techniques are also constantly updated: Browsers, proxies, new emulations, new data points.

The next one was “How to Eavesdrop on Winnti in a Live Environment Using Virtual Machine Introspection (VMI)” presented by Philipp Barthel and Sebastian Eydam. The goal was to explain a typical usage of a tool called Tycho to perform malware analysis but from the hypervisor point of view. The selection malware was Winnit, a classic APT RAT that was used to attack many DAX corporations. First, they explained what is “VMI” or Virtual Machine Introspection. It’s a kind of IDS to collect and detect suspicious behavior. From the IDS world, we have HIDS (host) and NIDS (network). VMI is the best of both. It connects to the hypervisor (to the malware does not detected the presence of an agent in the sandbox). Tycho can be used to interact with the OS and collected data. By example:

calc = tycho.open_process(“calc.exe”)

It seems to be a very powerful tool but… for me, the presentation was too much focused on a commercial tool. Indeed, Tycho is not free but it deserves to be tested. Based on Tycho, they reviewed how Winnit encrypts data, how it communicates with its C2 server, etc.

The last presentation was “Evolution of the Sysrv mining botnet” with György Luptak and Dorka Palotay. The idea was to explain how to reverse Golang binaries using Ghidra. Why? More and more malware samples are written in Go (IoT, Linux) and Sysrv was a good example. What are the (some) issues with Go (from a reverse engineering point of view):

  • Huge binaries (statically linked)
  • Unusual strings handling
  • No symbol names (stripped binaries)

Compared to other tools, Ghidra does not have all the capabilities by default. After a quick presentation of Sysrv (found in 2020, wormable and cryptominer), they explained how to use Ghidra to analyze Go code. Go programs are organized in packages. A package is a collection of source files in the same directory that are compiled together. They already exist tools to deobfuscate Go programs like obfuscate. But what about Ghidra? When you load Sysrc, Ghidra will find 3800+ functions! Where to start? Which one(s) is/are interesting? In the next part of the presentation, Dorka explained in detail how Go uses strings. In Go, they don’t end with a NULL character. After some examples, some Ghidra scripts were introduced to automatically extract strings (and function names) from Go programs. It was for me, the best talk of this first day! All scripts are available here.

Ready for day 2!

The post Botconf Day 1 Wrap-Up appeared first on /dev/random.

27 avril 2022

S’il y’a une personne qui n’est guère enchantée de me voir déconnecté, c’est mon éditeur. Certes, il comprend l’expérience. Mais il a un livre à promouvoir. Après tout, il a investi beaucoup d’argent et d’énergie pour produire la version audio de mon roman Printeurs et il espère me voir en faire la promotion, tant au format papier, électronique qu’audiolivre. Il attend de moi que je vous répète à longueur de journée que l’audiolivre lu par Loïc Richard m’a procuré des frissons, que Printeurs est un super roman pour dénoncer les abus de la publicité et de la surveillance mais pas que la version pirate est disponible sur

Mais comment promouvoir une œuvre si l’artiste ne tente pas d’occuper l’espace sur les réseaux sociaux ? C’est une problématique très actuelle pour de nombreux musiciens, comédiens, écrivains. Facebook, c’est mal. Mais c’est essentiel pour se faire connaître. Ou du moins, ça semble essentiel. C’est d’ailleurs la raison pour laquelle j’ai moi-même mis tellement de temps à supprimer mon compte.

Comme le souligne David Bessis dans son livre « Mathematica », si l’intuition et le rationnel ne s’accordent pas, il ne faut pas choisir entre l’un et l’autre. Il faut creuser jusqu’à comprendre d’où provient la dichotomie, jusqu’à ce que l’intuition et le rationnel soient alignés.

Reposons la question autrement : pourquoi les artistes ont-ils l’impression que les réseaux sociaux sont essentiels à leur carrière ? Parce qu’ils ont des retours : des commentaires, des likes, des partages. Des statistiques détaillées sur « l’engagement de leur communauté ». Qui leur fournit ces retours ? Les réseaux sociaux eux-mêmes !

Qui sont les artistes qui ont le plus de followers sur les réseaux sociaux ? Les artistes qui ont du succès… en dehors des réseaux sociaux !

Les réseaux sociaux nous font confondre la cause et l’effet. En soi, ils ne sont la cause d’aucun succès, ils ne font que souligner les succès existants. Ils ne font que récompenser l’utilisation de leur plateforme par une monnaie de singe qu’ils contrôlent. Le « Like ».

Lors d’un récent voyage en train, j’ai pu observer une jeune femme qui a passé le trajet sur son smartphone. D’un coup de pouce, elle faisait scroller son écran à une vitesse effrayante, ne s’arrêtant parfois qu’une milliseconde pour mettre un like avant de continuer. Le « Like » tant convoité n’est, en réalité, qu’une microfraction de seconde. Il ne représente rien. N’a aucune valeur. Pire, il est souvent ajouté par convention sociale (la jeune femme a notamment liké une photo représentant une main avec une bague à l’annulaire avant de reprendre son défilement effréné).

Poster du contenu sur les réseaux sociaux pour obtenir des likes est une quête chimérique. L’artiste travaille littéralement au profit du réseau social pour l’alimenter, pour donner une raison aux utilisateurs de venir le consulter. En échange, il peut avoir la chance de recevoir une impression virtuelle de succès.

Il arrive, parfois, de faire le buzz et de se faire connaître à travers les réseaux sociaux. J’ai fait cette expérience plusieurs fois durant ma carrière de blogueur. Certains de mes billets ont été vus par plusieurs centaines de milliers de personnes en une journée. D’autres m’ont valu des séquences à la télévision nationale. Aucun n’a eu le moindre impact durable sur ma vie si ce n’est d’être parfois reconnu comme « le blogueur qui… ».

Je parle d’expérience : le buzz n’a, la plupart du temps, aucun impact durable. Il ne permet pas de gagner autre chose que des statistiques. Il est complètement imprévisible, aléatoire. C’est le Graal de millions de marketeux qui passent leur journée à pondre des dizaines de tentatives de buzz.

Pour un artiste, vouloir faire le buzz sur les réseaux sociaux, c’est l’équivalent de jouer au lotto. Dix fois par jour. Contre une armée de professionnels qui jouent mille fois par jour et n’ont pas la moindre morale ou pudeur artistique. C’est commencer à réfléchir au nombre de messages à poster, le jour idéal pour « maximiser l’engagement ». C’est un métier. C’est stupide. C’est immoral. C’est tout sauf de l’art…

Au fond, qu’est-ce qu’un artiste ? Ou un artisan ?

C’est quelqu’un qui se consacre à son métier, qui tente en permanence de s’améliorer. Dans son « Mathematica » susnommé, David Bessis donne l’exemple du jeune Ben Underwood qui, après avoir perdu l’usage de ses yeux très jeune, a développé une capacité à explorer son environnement en émettant des clics avec la langue et en écoutant le son produit. Cette technique, qui parait incroyable, serait à la portée de tout un chacun. Les premiers résultats s’obtiendraient après une dizaine d’heures d’apprentissage.

Dix heures, cela ne parait rien. Mais dix heures concentrées entièrement consacrées à un unique sujet, c’est beaucoup. Il n’y a pas beaucoup de domaines auxquels nous consacrons une dizaine d’heures. Une dizaine d’heures, cela permet probablement de se lancer, de comprendre ce qui est possible. Une dizaine d’heures de piano permettent de jouer un petit morceau.

Pour devenir bon, il faut aller plus loin. Des centaines, des milliers d’heures. À partir de mille heures consacrées avec concentration sur un sujet, vous devenez un expert. Et à partir de dix mille heures, vous devenez, je crois, un véritable artiste, un orfèvre. Ce que vous produisez devient plus personnel, plus précis. Différent. Vous commencez à apporter une réelle plus-value au monde, vous créez quelque chose qui n’existe pas, que personne d’autre ne pourrait faire. Je me souviens d’avoir entendu que, tous les matins, Michael Jordan passait deux heures à lancer des ballons vers le panier de son terrain de basket personnel. Qu’ils soient bons ou mauvais, il y passait deux heures. Tous les matins. Tiger Woods affirme faire pareil sur les practices de golf, avouant que rien ne le rend plus heureux que d’avoir une pyramide de balles à frapper à la suite. Ce sont des stars, des artistes. Nous voyons leurs succès, nous les likons sur les réseaux sociaux. Mais nous ne voyons pas leur travail, les milliers d’heures passées à échouer mécaniquement dans l’ombre.

Les réseaux sociaux nous font apparaitre le succès comme une sorte de recette magique, une poudre de perlimpinpin avec effet immédiat. Il suffirait de la trouver, d’essayer encore et encore. Comme s’il suffisait de jouer encore et encore au lotto pour devenir riche.

C’est évidemment un mensonge. Un mensonge facile. Les algorithmes des réseaux sociaux récompensent ceux qui sont les plus actifs en mettant en avant leurs publications, en encourageant voire en créant de toutes pièces des likes. J’ai personnellement fait l’expérience d’acheter de la publicité sur Twitter. J’ai récolté beaucoup de likes. J’ai réussi à démontrer que la plupart étaient faux. Sur Facebook, le mensonge est encore plus transparent : le nombre de « clics » augmente comme par magie dès que l’on paye. Mais ces clics en question ne se transforment que très rarement en une action concrète.

Les plateformes marketing ont été pensées par le marketing pour le marketing. Elles ont été créées par des gens dont le métier est de vendre des cigarettes à des enfants de douze ans, de l’alcool aux adolescents, des SUVs aux citadins. De vous faire oublier que vous polluez en vous faisant polluer plus. De vous rendre malheureux pour vous faire croire que vous seriez heureux en consommant plus. De diluer la vérité pour la rendre indistinguable du mensonge.

Le simple fait d’utiliser une plateforme dédiée au marketing nous transforme en professionnels du marketing. En menteurs amoraux. Les militants écologistes, anticapitalistes ou les promoteurs d’actions locales qui utilisent ces réseaux sociaux sont, sans le savoir, complètement corrompus. Ils militent, sans s’en rendre compte, pour de l’ultra-consumérisme permanent. C’est se rendre en jet privé, la cigarette à la bouche, à une manifestation pour dénoncer l’inaction climatique. C’est tenir une réunion d’organisation du potager partagé dans un MacDonalds.

Comme l’explique Jaron Lanier dans « Who Owns the Future? », les réseaux sociaux promeuvent l’existence de « superstars » dans un modèle économique de type « The winner takes it all ». Un artiste est soit multimillionnaire, soit pauvre et ignoré. Il n’y a plus de juste milieu. La culture s’uniformise, s’industrialise. Si nous voulons, au contraire, promouvoir des arts plus variés, des communautés à taille humaine, refuser les règles monopolistiques est une simple question de bon sens. Et de survie.

Tout cela m’est apparu comme évident le jour où j’ai effacé mon compte Facebook. Tant que mon compte existait, j’étais incapable de le voir, de le vivre. J’avais beau me dire que je n’utilisais plus vraiment Facebook, le simple fait d’avoir des milliers de followers me donnait l’illusion d’une communauté à entretenir, d’une foule attendant avidement quelques mots de ma part. Une illusion de succès.

Mes posts avaient beau n’avoir que très rarement un impact, j’autojustifiais la nécessité de garder mon compte. Une bouffée de fierté m’envahissait lorsque mon compteur faisait un bon en avant.

L’illusion s’est dissipée à la seconde où mon compte a été supprimé.

J’ai l’intuition que l’art est l’exact contraire du marketing. Il faut consacrer du temps à s’améliorer, à s’exprimer.

Si nous voulons être artistes, nous devons refuser les règles du marketing. Chaque heure de disponible doit être consacrée à notre art au lieu d’être consacrée à devenir un expert… en marketing sur les réseaux sociaux.

C’est difficile. C’est long.

Nicholas Taleb, l’auteur du livre « Black Swan », a coutume de dire que « si c’est une bonne chose, mais qu’il n’y a aucun feedback immédiat, alors c’est qu’il y’a un avantage, un edge ». Si vous travaillez votre art dans votre cave au lieu de poster sur les réseaux sociaux, vous deviendrez meilleur. Si vous vous consacrez à faire des concerts locaux, à aller à la rencontre de votre public existant sans chercher à tout prix à l’agrandir, alors il s’agrandira sans que vous vous en rendiez compte. Vous n’aurez plus un compteur, mais des véritables humains en face de vous.

Lorsqu’un artiste se consacre aux réseaux sociaux, lorsqu’il parle de « sa communauté » pour désigner le chiffre inscrit sous le mot « followers », il trahit son art. Il abandonne la création pour faire du marketing. Sans surprise, il attire alors une foule de followers qui est sensible au marketing, qui clique sans trop réfléchir, qui suit la mode du moment, qui change d’avis à la moindre distraction. Sur les réseaux sociaux, le compteur ne reflète souvent que la version frustrée, aigrie, qui s’ennuie du véritable être humain qui respire, rit, chante et danse sans son téléphone. Sur les réseaux sociaux, les véritables amateurs d’art sont forcément déçus. Ils viennent pour l’art et sont, à la place, bombardés de publicités pour l’art en question. Plutôt que de lire un nouveau livre, ils reçoivent cent messages les invitant à lire un livre déjà lu.

Au plus je me suis éloigné des réseaux sociaux, au plus j’ai rencontré des personnes qui n’y étaient pas. Par conviction ou par simple incapacité d’y trouver de l’intérêt. Des humains qui lisent des livres plutôt que de suivre les auteurs sur Twitter. Qui vont à des expos photo plutôt que de scroller sur Instagram. Des lecteurs de mon blog qui me demandaient sincèrement d’arrêter d’écrire pour les réseaux sociaux, mais d’écrire pour eux. Je n’arrivais pas à les entendre.

Des millions de personnes ne sont pas sur les réseaux sociaux. Elles ne sont tout simplement pas représentées dans les statistiques. Elles n’existent pas pour le marketing. Elles changent le monde de manière probablement bien plus efficace que ceux qui créent des pages Facebook pour promouvoir l’écologie.

Les réseaux sociaux corrompent. Êtes-vous moralement et artistiquement alignés avec le fait que toutes les données de votre « communauté » sur Twitter vont désormais être la propriété privée d’Elon Musk, l’individu le plus riche de la planète qui, à l’heure où j’écris ces lignes, parle de racheter la plateforme ? L’élan artistique qui nous anime, nous transcende, nous dépasse ne nécessite-t-il pas, pour exister, d’être aligné avec nos valeurs morales les plus profondes ?

Peut-être que la responsabilité sociétale des artistes est d’utiliser leur pouvoir pour refuser la toute-puissance de quelques monopoles publicitaires. Simplement en refusant d’y être. En mettant en place une newsletter (si possible pas sur une plateforme à visée monopolistique) et un site web avec un flux RSS. En créant une véritable relation avec leur public. Une communauté se construit sur le long terme, en accueillant et respectant chaque nouveau membre, en étant patient, en espérant que fonctionne le bouche-à-oreille.

Les réseaux sociaux nous font croire qu’il n’y a pas d’alternative pour exister autre que de hurler « Regardez ! J’existe ! » à tout bout de champ. Il y’en a une. Celle qui consiste à chuchoter « Merci à vous d’être présents ce soir. Votre présence me réchauffe le cœur et m’inspire. »

Les artistes et les activistes n’ont jamais eu autant de pouvoir pour rendre le monde meilleur qu’aujourd’hui, alors qu’ils peuvent encore tout arrêter et rendre les plateformes marketing de moins en moins utiles.

Encore faut-il qu’ils en aient le courage, qu’ils abandonnent le rêve entretenu par les plateformes qu’ils pourraient devenir la prochaine superstar. Qu’il leur suffit de continuer de jouer à la roulette, d’acheter le prochain ticket. Que le succès véritable leur tend les bras pour peu qu’ils investissent 10, 20 ou 1000€ dans une publicité ciblée.

Si quitter les réseaux sociaux et leur ubiquité est difficile pour l’individu, elle est un devoir pour les créateurs, les artistes, les activistes. Cette prise de conscience est bien tardive de ma part, moi qui ai, pendant des années, succombé aux sirènes de l’apparence de succès, vous appelant à me suivre et à me liker.

À tous ceux qui m’ont écouté, je m’excuse sincèrement. Supprimez vos comptes. Puissent ces quelques lignes tenter de réparer une partie du mal auquel j’ai contribué. À tous ceux qui m’ont prévenu, je m’excuse de ne pas avoir réussi à vous entendre.

Recevez les billets par mail ou par RSS. Max 2 billets par semaine, rien d’autre. Adresse email jamais partagée et définitivement effacée lors du désabonnement. Dernier livre paru : Printeurs, thriller cyberpunk. Pour soutenir l’auteur, lisez, offrez et partagez des livres.

Ce texte est publié sous la licence CC-By BE.

April 25, 2022

I published the following diary on “Simple PDF Linking to Malicious Content“:

Last week, I found an interesting piece of phishing based on a PDF file. Today, most of the PDF files that are delivered to end-user are not malicious, I mean that they don’t contain an exploit to trigger a vulnerability and infect the victim’s computer. They are just used as a transport mechanism to deliver more malicious content. Yesterday, Didier analyzed the same kind of Word document. They are more and more common because they are (usually) not blocked by common filters at the perimeter… [Read more]

The post [SANS ISC] Simple PDF Linking to Malicious Content appeared first on /dev/random.

April 22, 2022

I use CrashPlan for cloud backups. In 2018 they stopped their Home solution, so I switched to their Business plan.

It works very well on Linux, Windows and Mac, but it was always a bit fickle on my QNAP NAS. There is a qpkg package for CrashPlan, and there are lots of posts on the QNAP support forum. After 2018, none of the solutions to run a backup on the NAS itself stopped working. So I gave up, and I didn’t have a backup for almost 4 years.

Now that I have mounted most of the network shares on my local filesystem, I can just run the backup on my pc. I made 3 different backup sets, one for each of the shares. There’s only one thing that I had to fix: if Crashplan runs when the shares aren’t mounted, then it thinks that the directories are empty, and it will delete the backup on the cloud storage. As soon as the shares come back online, the files are backed up again. It doesn’t have to upload all files again, because Crashplan doesn’t purge the files on it’s cloud immediately, but the file verification still happens. That takes time and bandwidth.

I contacted CrashPlan support about this issue, and this was their reply:

I do not believe that this scenario can be avoided with this product – at least not in conjunction with your desired setup. If a location within CrashPlan’s file selection is detached from the host machine, then the program will need to rescan the selection. This is in inherent drawback to including network drives within your file selection. Your drives need to retain a stable connection in order to avoid the necessity of the software to run a new scan when it sees the drives attached to the device (so long as they’re within the file selection) detach and reattach.

Since the drive detaching will send a hardware event from the OS to CrashPlan, CrashPlan will see that that hardware event lies within its file selection – due to the fact that you mapped your network drives into a location which you’ve configured CrashPlan to watch. A hardware event pointing out that a drive within the /home/amedee/Multimedia/ file path has changed its connection status will trigger a scan. CrashPlan will not shut down upon receiving a drive detachment or attachment hardware event. The program needs to know what (if anything) is still there, and is designed firmly to track those types of changes, not to give up and stop monitoring the locations within its file selection.

There’s no way around this, aside from ensuring that you either keep a stable connection. This is an unavoidable negative consequence of mapping a network drive to a location which you’ve included in CrashPlan’s file selection. The only solution would be for you to engineer your network so as not to interrupt the connection.

Nathaniel, Technical Support Agent, Code42

I thought as much already. No problem, Nathaniel! I found a workaround: a shell script that checks if a certain marker file on the network share exists, and if it doesn’t, then the script stops the CrashPlan service, which will prevent CrashPlan from scanning the file selection. As soon as the file becomes available again, then the CrashPlan service is started. This workaround works, and is good enough for me. It may not be the cleanest solution but I’m happy with it.

I first considered using inotifywait, which listens to filesystem events like modifying or deleting files, or unmount. However when the network connection just drops for any reason, then inotifywait doesn’t get an event. So I have to resort to checking if a file exists.


all_files_exist () {
    while read -r line; do
        [ -f "$line" ]
        if ! (exit $status); then
            echo "$line not found!"
            return $status
    done < "$file_list"

start_crashplan () {
    /etc/init.d/code42 start

stop_crashplan () {
    /etc/init.d/code42 stop

while true; do
    if all_files_exist; then
    sleep 60
  • file_list.txt contains a list of testfiles on different shares that I want to check. They all have to be present, if even only one of them is missing or can’t be reached, then the service must be stopped.
  • I can add or remove shares without needing to modify the script, I only need to edit file_list.txt – even while the script is still running.
  • Starting (or stopping) the service if it is already started (or stopped) is very much ok. The actual startup script itself takes care of checking if it has already started (or stopped).
  • This script needs to be run at startup as root, so I call it from cron (sudo crontab -u root -e):
@reboot /home/amedee/bin/

This is what CrashPlan support replied when I told them about my workaround:

Hello Amedee,

That is excellent to hear that you have devised a solution which fits your needs!

This might not come in time to help smooth out your experience with your particular setup, but I can mark this ticket with a feature request tag. These tags help give a resource to our Product team to gauge customer interest in various features or improvements. While there is no way to use features within the program itself to properly address the scenario in which you unfortunately find yourself, as an avenue for adjustments to how the software currently operates in regards to the attachment or detachment of network drives, it’s an entirely valid request for changes in the future.

Nathaniel, Technical Support Agent, Code42

That’s very nice of you, Nathaniel! Thank you very much!

April 20, 2022

I have a NAS, a QNAP TS-419P II. It’s about a decade old and it has always served me well. Due to various reasons I have never used it in an efficient way, it was always like a huge external drive, not really integrated in the rest of my filesystems.

The NAS has a couple of CIFS shares with very obvious names:

  • backup
  • Download
  • Multimedia, with directories Music, Photos and Videos

(There are a few more shares, but they aren’t relevant now.)

In Ubuntu, a user home directory has these default directories:

  • Downloads
  • Music
  • Pictures
  • Videos

I want to store the files in these directories on my NAS.

Mounting shares, the obvious way

First I moved all existing files from ~/Downloads, ~/Music, ~/Pictures, ~/Videos to the corresponding directories on the NAS, to get empty directories. Then I made a few changes to the directories:

$ mkdir backup
$ mkdir Multimedia
$ rmdir Music
$ ln -s Multimedia/Music Music
$ rmdir Pictures
$ ln -s Multimedia/Photos Pictures
$ rmdir Videos
$ ln -s Multimedia/Videos Videos

The symbolic links now point to directories that don’t (yet) exist, so they appear broken – for now.

The next step is to mount the network shares to their corresponding directories.

The hostname of my NAS is minerva, after the Roman goddess of wisdom. To avoid using IP addresses, I added it’s IP address to /etc/hosts:	localhost     modem	minerva

The shares are password protected, and I don’t want to type the password each time I use the shares. So the login goes into a file /home/amedee/.smb:


Even though I am the only user of this computer, it’s best practice to protect that file so I do

$ chmod 400 /home/amedee/.smb

Then I added these entries to /etc/fstab:

//minerva/download	/home/amedee/Downloads	cifs	uid=1000,gid=1000,credentials=/home/amedee/.smb,iocharset=utf8 0 0
//minerva/backup	/home/amedee/backup	cifs	uid=0,gid=1000,credentials=/home/amedee/.smb,iocharset=utf8 0 0
//minerva/multimedia	/home/amedee/Multimedia	cifs	uid=0,gid=1000,credentials=/home/amedee/.smb,iocharset=utf8 0 0
  • CIFS shares don’t have a concept of user per file, so the entire share is shown as owned by the same user. uid=1000 and gid=1000 are the user ID and group ID of the user amedee, so that all files appear to be owned by me when I do ls -l.
  • The credentials option points to the file with the username and password.
  • The default character encoding for mounts is iso8859-1, for legacy reasons. I may have files with funky characters, so iocharset=utf8 takes care of that.

Then I did sudo mount -a and yay, the files on the NAS appear as if they were on the local hard disk!

Fixing a slow startup

This all worked very well, until I did a reboot. It took a really, really long time to get to the login screen. I did lots of troubleshooting, which was really boring, so I’ll skip to the conclusion: the network mounts were slowing things down, and if I manually mount them after login, then there’s no problem.

It turns out that systemd provides a way to automount filesystems on demand. So they are only mounted when the operating system tries to access them. That sounds exactly like what I need.

To achieve this, I only needed to add noauto,x-systemd.automount to the mount options. I also added x-systemd.device-timeout=10, which means that systemd waits for 10 seconds, and then gives up if it’s unable to mount the share.

From now on I’ll never not use noauto,x-systemd.automount for network shares!

While researching this, I found some documentation that claims you don’t need noauto if you have x-systemd.automount in your mount options. Yours truly has tried it with and without noauto, and I can confirm, from first hand experience, that you definitely need noauto. Without it, there is still the long waiting time at login.

April 18, 2022

Jag brukade skriva på den här bloggen på nederländska. Nu är det mest på engelska, men undantagsvis är det här blogginlägget på svenska.

I september 2020 började jag lära mig svenska på kvällsskolan i Aalst. Varför? Det finns flera anledningar:

  • Jag spelar nyckelharpa, ett typiskt svenskt musikinstrument. Jag gÃ¥r pÃ¥ kurser hemma och utomlands, ofta frÃ¥n svenska lärare. Det var sÃ¥ jag lärde känna människor i Sverige och dÃ¥ är det bra att prata lite svenska för att hÃ¥lla kontakten online.
  • När man slÃ¥r upp nÃ¥got pÃ¥ nätet om nyckelharpa är det ofta pÃ¥ svenska. Jag har ocksÃ¥ en underbar bok “Nyckelharpan – Ett unikt svenskt kulturarv” av Esbjörn Hogmark och jag vill kunna läsa den och inte bara titta pÃ¥ bilderna.
  • Jag tycker att Sverige är ett vackert land som jag kanske vill besöka nÃ¥gon gÃ¥ng. Norge ocksÃ¥, och där talar man en märklig dialekt av svenska. 😛
  • Jag vill gÃ¥ en kurs pÃ¥ Eric Sahlström Institutet i Tobo nÃ¥gon gÃ¥ng. DÃ¥ skulle det vara bra att förstÃ¥ lärarna pÃ¥ deras eget sprÃ¥k.
  • Jag gillar sprÃ¥k och sprÃ¥kinlärning! Det hÃ¥ller min hjärna fräsch och frisk. 😀

And if you didn’t understand anything: there’s always Google Translate!

April 17, 2022

I have a user account (yes really) in a Hyundai Kona electric car.

A while ago there was a software update and now the owner cannot play radio (or any other music) through the car when Bluetooth on her smartphone is active. The car demands that music is played through the smartphone?!

Disabling Bluetooth on the smartphone solves this problem, but then phone calls are not handsfree?! The owner never accepted the new EULA for the update...

Yesterday I drove the car with my user account and was confronted with the new EULA. I decided to read it, but even though my account is in English (and the other account is in Dutch), this EULA was presented in French?!

I declined this EULA (the choice was 'agree' or 'disagree' in English even though the text was in French). The car immediately said "Audio Off". I could not open the "radio" menu on the screen, and also could not access the "media" menu to play the songs that I had been playing in that car from a USB stick since this summer?!

I find this very scary. 

Luckily I don't "own" a car. But can it even be considered "owning" if features can be disabled by the manufacturer?!

April 15, 2022

Now that Autoptimize has had “critical CSS” for over 2 years, it is time to let the old “Autoptimize Power-Up” which still has over 10K active installs finally go pining for the fjords. I pushed out an update for it which will see it deactivate itself if Autoptimize is at version 2.7 or higher.


Armed with the information from my previous research on a possible kernel bug, I opened a bug report on the Ubuntu bug tracker:

It wasn’t long until my bug got confirmed. Someone else chimed in that they had also experienced USB issues. In their case it were external drive devices. Definitely a showstopper!

As of this date, there is a beta for Ubuntu 22.04, and my hope is that this version will either include a new enough kernel (5.16 or up), or that Ubuntu developers have manually cherry-picked the commit that fixes the issue. Let’s check with the Ubuntu Kernel Team:

Ubuntu Kernel Team

Oops… based on upstream 5.15… that’s not good. Maybe they cherry-picked upstream commits? I checked and the kernel is currently at The changelog doesn’t mention anything about xhci or usb. I guess I still have to wait a bit longer…

April 13, 2022

"With everyone and their dog shifting to containers, and away from virtual machines (VMs), we realized that running vendor-provided software on VMs at Google was slowing us down. So we moved."

Bikram co-authored this blog post last year about DASInfra's experience moving workloads from Corp to Anthos. The group I run at work is going down a similar path by migrating VMs to Anthos on bare metal for on-prem.

Taken from The Playlist - a curated perspective on the intersection of form and content (subscribe, discuss)

flattr this!

"Without a next action, there remains a potentially infinite gap between current reality and what you need to do."

David Allen's Getting Things Done is the non-fiction book I've reread the most in my life. I reread it every couple of years and still pick up on new ideas that I missed before, or parts that resonate better now and I'm excited to implement. Before Google, I used to give this book to new employees as a welcome gift.

The book got an update in 2015, and I haven't read the new version yet, so I'm planning an extended GTD book club at work in Q2, spreading the book out over multiple sessions. (In fact, I did just that for the young adult version of the book with my 16 year old godson back home in Belgium) If you've run a GTD book club, drop me a line!

Find out more at Getting Things Done® - David Allen's GTD® Methodology

"Too many meetings end with a vague feeling among the players that something ought to happen, and the hope that it’s not their personal job to make it so. [...] ask “So what’s the next action on this?” at the end of each discussion point in your next staff meeting"

Taken from The Playlist - a curated perspective on the intersection of form and content (subscribe, discuss)

flattr this!

"Most women fight wars on two fronts, one for whatever the putative topic is and one simply for the right to speak, to have ideas, to be acknowledged to be in possession of facts and truths, to have value, to be a human being."

In honor of International Women's Day 2022 (this past March 8th), some quotes from the 2008 article that inspired the term "mansplaining": to comment on or explain something to a woman in a condescending, overconfident, and often inaccurate or oversimplified manner.

I've certainly been (and probably still am) guilty of this behavior, and this is a standing invitation to let me know when I'm doing it to you.

Read the original article with a new introduction at Men Explain Things to Me – Guernica

"None was more astonishing than the one from the Indianapolis man who wrote in to tell me that he had “never personally or professionally shortchanged a woman” and went on to berate me for not hanging out with “more regular guys or at least do a little homework first,” gave me some advice about how to run my life, and then commented on my “feelings of inferiority.” He thought that being patronized was an experience a woman chooses to, or could choose not to have–and so the fault was all mine. Life is short; I didn’t write back."

Taken from The Playlist - a curated perspective on the intersection of form and content (subscribe, discuss)

flattr this!

In the ever more vertical company that Google is becoming, it is even more important to collaborate on some of your communication - more people want to contribute to the message and get it right, and more thought needs to be given to the ever wider audience you're sending mails to.

A while back I copied over AppScript code from an internal Google project to send meeting notes to make a different tool which makes it easy to go from Google Docs draft to a mail in GMail and avoid embarrassing copy/paste errors. I'm happy to be able to retire that little side project in favor of a recently released built-in feature of Google Docs: Draft emails from Google Docs - Docs Editors Help

Taken from The Playlist - a curated perspective on the intersection of form and content (subscribe, discuss)

flattr this!

In previous blogposts I wrote about how I found a possible bug in the Linux kernel, or more precisely, in the kernel that Ubuntu derived from the mainline kernel.

To be able to install any kernel version 5.15.7 or higher, I also had to install libssl3.

The result is that I now have 37 kernels installed, taking up little over 2 GiB disk space:

$ (cd /boot ; ls -hgo initrd.img-* ; ls /boot/initrd.img-* | wc -l)
-rw-r--r-- 1 39M mrt  9 09:54 initrd.img-5.13.0-051300-generic
-rw-r--r-- 1 40M mrt  9 09:58 initrd.img-5.13.0-19-generic
-rw-r--r-- 1 40M mrt  9 09:58 initrd.img-5.13.0-20-generic
-rw-r--r-- 1 40M mrt  9 09:57 initrd.img-5.13.0-21-generic
-rw-r--r-- 1 44M mrt 30 17:46 initrd.img-5.13.0-22-generic
-rw-r--r-- 1 40M mrt  9 09:56 initrd.img-5.13.0-23-generic
-rw-r--r-- 1 40M mrt  9 09:56 initrd.img-5.13.0-25-generic
-rw-r--r-- 1 40M mrt  9 09:56 initrd.img-5.13.0-27-generic
-rw-r--r-- 1 40M mrt  9 09:55 initrd.img-5.13.0-28-generic
-rw-r--r-- 1 40M mrt  9 09:55 initrd.img-5.13.0-30-generic
-rw-r--r-- 1 45M mrt  9 12:02 initrd.img-5.13.0-35-generic
-rw-r--r-- 1 45M mrt 24 23:17 initrd.img-5.13.0-37-generic
-rw-r--r-- 1 45M mrt 30 17:49 initrd.img-5.13.0-39-generic
-rw-r--r-- 1 39M mrt  9 09:54 initrd.img-5.13.1-051301-generic
-rw-r--r-- 1 39M mrt  9 09:54 initrd.img-5.13.19-051319-generic
-rw-r--r-- 1 37M mrt  9 09:53 initrd.img-5.13.19-ubuntu-5.13.0-22.22
-rw-r--r-- 1 37M mrt  9 09:53 initrd.img-5.13.19-ubuntu-5.13.0-22.22-0-g3ab15e228151
-rw-r--r-- 1 37M mrt  9 09:52 initrd.img-5.13.19-ubuntu-5.13.0-22.22-317-g398351230dab
-rw-r--r-- 1 37M mrt  9 09:52 initrd.img-5.13.19-ubuntu-5.13.0-22.22-356-g8ac4e2604dae
-rw-r--r-- 1 37M mrt  9 09:52 initrd.img-5.13.19-ubuntu-5.13.0-22.22-376-gfab6fb5e61e1
-rw-r--r-- 1 37M mrt  9 09:51 initrd.img-5.13.19-ubuntu-5.13.0-22.22-386-gce5ff9b36bc3
-rw-r--r-- 1 37M mrt  9 09:51 initrd.img-5.13.19-ubuntu-5.13.0-22.22-387-g0fc979747dec
-rw-r--r-- 1 37M mrt  9 09:50 initrd.img-5.13.19-ubuntu-5.13.0-22.22-388-g20210d51e24a
-rw-r--r-- 1 37M mrt  9 09:50 initrd.img-5.13.19-ubuntu-5.13.0-22.22-388-gab2802ea6621
-rw-r--r-- 1 37M mrt  9 09:50 initrd.img-5.13.19-ubuntu-5.13.0-22.22-391-ge24e59fa409c
-rw-r--r-- 1 37M mrt  9 09:49 initrd.img-5.13.19-ubuntu-5.13.0-22.22-396-gc3d35f3acc3a
-rw-r--r-- 1 37M mrt  9 09:49 initrd.img-5.13.19-ubuntu-5.13.0-22.22-475-g79b62d0bba89
-rw-r--r-- 1 37M mrt  9 09:48 initrd.img-5.13.19-ubuntu-5.13.0-23.23
-rw-r--r-- 1 40M mrt  9 09:48 initrd.img-5.14.0-051400-generic
-rw-r--r-- 1 40M mrt  9 10:31 initrd.img-5.14.21-051421-generic
-rw-r--r-- 1 44M mrt  9 12:39 initrd.img-5.15.0-051500-generic
-rw-r--r-- 1 46M mrt  9 12:16 initrd.img-5.15.0-22-generic
-rw-r--r-- 1 46M mrt 28 23:27 initrd.img-5.15.32-051532-generic
-rw-r--r-- 1 46M mrt 17 21:12 initrd.img-5.16.0-051600-generic
-rw-r--r-- 1 48M mrt 28 23:19 initrd.img-5.16.16-051616-generic
-rw-r--r-- 1 45M mrt 28 23:11 initrd.img-5.17.0-051700-generic
-rw-r--r-- 1 46M apr  8 17:02 initrd.img-5.17.2-051702-generic
  • Versions 5.xx.yy-zz-generic are installed with apt.
  • Versions 5.xx.yy-05xxyy-generic are installed with the Ubuntu Mainline Kernel Installer.
  • Versions 5.xx.yy-ubuntu-5.13.0-zz.zz-nnn-g<commithash> are compiled from source, where <commithash> is the commit of the kernel repository that I compiled.

The kernels in bold are the kernels where something unexpected happens with my USB devices:

  • Ubuntu kernels 5.13.23 and up – including 5.15 kernels of Ubuntu 22.04 LTS (Jammy Jellyfish).
  • Ubuntu compiled kernels, starting 387 commits after kernel 5.13.22.
  • Mainline kernels 5.15.xx.

When Ubuntu finally bases their kernel on mainline 5.16 or higher, then the USB bug will be solved.

April 11, 2022

So what was DDD Ghent like?


I’m especially interested in sprinting on the CKEditor 5 module for Drupal core, since that’s what I am currently working on for Acquia, because that is one of the biggest must-haves/blockers for Drupal 10. 86% of issues worked on at DDD Ghent was not CKEditor 5, so … I’m hoping others will do blog posts similar to this one! :D

New contributors

I worked with at least a dozen people who’d never contributed to CKEditor 5 before. I mentored in various ways: how to do the issue write-up, how to debug, how to find examples, how to write a kernel test, how to use data providers, how to run and write a functional JS test, how to create a contrib-to-core CKE5 button upgrade path, etc.
I know that (my colleague and fellow CKEditor 5-in-core contributor) lauriii mentored scott_euser to help us get external images support, and he helped someone else write a complex CKE5 plugin that the popular token_filter module will be able to use for its upgrade path too.

Thanks to all of you who contributed to the CKEditor 5 module in Drupal core last week (in alphabetical order): andreasderijcke, brentg DieterHolvoet, Dom., Eli-T, ifrik, jcnventura, joevagyok, marcvangend, mpp and seanB. Better still: several of these people started issues of their own and ended up collaborating on each other’s issues!


The #1 takeaway for Lauri and I was that the upgrade path we had written assumed valid text format + CKEditor 4 configuration, which was definitely a faulty assumption, since just like the text format admin UI had done historically, there was no validation for any of this: the site builder is expected to know valid filter orders and which filters ought not to be enabled while using CKEditor 4. This utter lack of validation and hence guidance is what CKEditor 5 definitely does much better. But … we need to get those sites upgraded to CKEditor 5 too. That was the top critical we found, and it’s already fixed: #3273312. Basically, most long-time Drupalists apparently create new text formats and always add filter_autop and filter_url to them out of habit. The majority of people testing the upgrade path ran into this!

But extra special thanks go to ifrik and Dom. — they worked on CKEditor 5 the entire week and both not only reported but also contributed to lots of issues!

The second most frequent hurdle was contrib CKE4 plugins not having any actionability: the user feels stuck. We’re improving on that in #3273325. And more importantly, we’re starting to see that some modules are obsolete, which means core can (and MUST!) provide an upgrade path for certain contrib modules — see #3274278 for the first of that, and we now have a Drupal handbook page where coordination is now happening.

And despite not feeling well at all, lauriii still attended the magnificent live accessibility testing that we got from Bram Duvigneau, where he basically applauded our CKEditor 5 toolbar configuration admin UI. (And found some hurdles in CKEditor 5 itself when using NVDA.)

So I’d say: the sprints at DDD were a big success!

And not just on the technical front: I got to show my hometown to many fellow Drupalists, so I have many beautiful memories to look back to :)

… but you don’t need --- at the start of a YAML file in Ansible.

What does the Ansible documentation say?

I know, I know, if you look at the official documentation on, then all of the examples start with ---. And if the official examples do it, then everyone should just blindly copy that without thinking, right?

Wrong! The Ansible documentation on YAML syntax says:

There’s another small quirk to YAML. All YAML files (regardless of their association with Ansible or not) can optionally begin with --- and end with .... This is part of the YAML format and indicates the start and end of a document.

© Copyright Ansible project contributors.

I’ve added the emphasis: optionally. They then continue with one example with --- at the start and ... at the end. The funny thing is, that’s about the only example on the Ansible documentation site (that I could find) that ends with .... So the end marker ... is clearly optional. What about the start marker ---?

What does the YAML specification say?

Ansible uses version 1.2 of the YAML specification and unless you are doing something really exotic, that’s the only version you should care about. Revision 1.2.0 was published in July 2009 and revision 1.2.2 in October 2021. That last revision doesn’t make any changes to the specification, it only corrects some errors and adds clarity.

Chapter 9 of the YAML spec introduces two concepts: documents and streams.

A stream can contain zero or more documents. It’s called a (character) stream because it can be something else than a file on your hard disk, for example some data that’s sent over a network connection. So your Ansible playbook file with extension .yml or .yaml is not a YAML document, it’s a YAML stream.

A document can have several parts:

  • Document prefix: optional character encoding and optional comment lines.
    Seriously, it’s 2022, are you going to make life hard for yourself and use any other encoding than ASCII or UTF-8? The default encoding that every YAML processor, inclusing Ansible, must support is UTF-8. So You Ain’t Gonna Need It.
    Comments can be placed anywhere, so don’t worry.
  • Document directives: these are instructions to the YAML processor and aren’t part of the data structure. The only directive I’ve occasionally seen in the wild is %YAML 1.2, to indicate the version of YAML used. That’s the default version for Ansible anyway, so You Ain’t Gonna Need It.
  • Document markers: a parser needs some way to know where directives stop and document content begins. That’s the directives end marker, ---. There is also a document end marker, ..., which tells a parser to stop looking for content and start scanning for directives again. If there are no markers and the first line doesn’t start with % (a directive), then a parser knows that everything is content. In real life you probably won’t ever have multiple documents in the same stream (file), instead you’ll organize your Ansible code in separate .yaml files, with playbooks and roles and tasks etc.
  • Document content: that’s the only really interesting stuff you care about.

YAML knows 3 types of documents:

  • Bare documents: don’t begin with directives or marker lines. Such documents are very “clean” as they contain nothing other than the content. This is the kind of YAML documents I prefer for Ansible.
  • Explicit documents: begin with an explicit directives end maker (---) but have no directives. This is the style that many people use if they just copy/paste examples from Stack Overflow.
  • Directives documents: start with some directives, followed by an explicit directives end marker. You don’t need directives for Ansible.

Configuring yamllint

I use ansible-lint and yamllint in a pre-commit hook to check the syntax of my Ansible files. This is currently my .yamllint.yml:

    present: false
    allowed-values: ['true', 'false', 'yes', 'no']

document-start makes sure that there is no --- at the start of a file. I also have opinions on truthy: an Ansible playbook is supposed to be readable both by machines and humans, and then it makes sense to allow the more human-readable values yes and no.

Do you also have opinions that make you change the default configuration of your linters?

April 08, 2022

Ubuntu mainline kernel packages 5.15.7 and later bump a dependency from libssl1.1 (>= 1.1.0) to libssl3 (>= 3.0.0~~alpha1).

However, package libssl3 is not available for Ubuntu 21.10 Impish Indri. It’s only available for Ubuntu 22.04 Jammy Jellyfish (which is still in beta as of time of writing) and later.

libssl3 further depends on libc6>=2.34 and debconf, but they are available in 21.10 repositories.

Here are a few different ways to resolve the dependency:

Option 1

Use apt pinning to install libssl3 from a Jammy repo, without pulling in everything else from Jammy.

This is more complicated, but it allows the libssl3 package to receive updates automatically.
Do all the following as root.

  • Create an apt config file to specify your system’s current release as the default release for installing packages, instead of simply the highest version number found. We are about to add a Jammy repo to apt, which will contain a lot of packages with higher version numbers, and we want apt to ignore them all.
$ echo 'APT::Default-Release "impish";' \
    | sudo tee /etc/apt/apt.conf.d/01ubuntu
  • Add the Jammy repository to the apt sources. If your system isn’t “impish”, change that below.
$ awk '($1$3$4=="debimpishmain"){$3="jammy" ;print}' /etc/apt/sources.list \
    | sudo tee /etc/apt/sources.list.d/jammy.list
  • Pin libssl3 to the jammy version in apt preferences. This overrides the Default-Release above, just for the libssl3 package.
$ sudo tee /etc/apt/preferences.d/libssl3 >/dev/null <<%%EOF
Package: libssl3
Pin: release n=jammy
Pin-Priority: 900
  • Install libssl3:
$ sudo apt update
$ sudo apt install libssl3

Later, when Jammy is officially released, delete all 3 files created above

$ sudo rm --force \
    /etc/apt/apt.conf.d/01ubuntu \
    /etc/apt/sources.list.d/jammy.list \

Option 2

Download the libssl3 deb package for Jammy and install it manually with dpkg -i filename.deb.

This only works if there aren’t any additional dependencies, which you would also have to install, with a risk of breaking your system. Here Be Dragons…

April 07, 2022

 I regularly fly between Belgium and my second home country Latvia. How much am I sponsoring Vladimir when doing that? About 25€. Back of the envelope calculation.

  • CRL - RIX return = 330 kg CO2 (source)
  • 1 l jet fuel a1 = 2.52 kg CO2 (source)
  • 1 l jet fuel = 0.85€ (source, some currency and SI conversion required)
  • refinery and distribution margin ~ 15% (conservative ballpark guesstimate based upon price/barrel for crude and jet a1 fuel)
  • percentage of Russian crude in EU: 27% (source)
  • (330/2.52)*.85*.85*.27 = 25.55€

P.S. More source countries have "interesting" policies. For example. 8% of EU imports are from Saudi Arabia.

P.P.S. Our upcoming holiday will be by night train. Exciting!

April 05, 2022

Je vous avais annoncé en grande pompe la suppression de mon compte LinkedIn puis la suppression d’autres comptes comme Facebook et Twitter. C’était un effort conscient, une volonté de le faire et d’être reconnu publiquement pour cet effort. C’était difficile.

Il en est parfois autrement. La suppression d’un service perçu comme incontournable se fait automatiquement.

La plupart de mes proches ont rejoint Signal et la gestion journalière de ma famille se fait sur Signal. Whatsapp me servait essentiellement pour les « groupes » d’amis, la famille élargie et quelques amis récalcitrants à Signal. La particularité de ces groupes est d’être particulièrement bavards et pas spécialement urgents. J’ai donc coupé complètement les notifications de Whatsapp il y a de cela déjà plus d’un an, le vérifiant manuellement tous les quelques jours pour voir « si je ne ratais rien ».

Alors que je me rendais chez une cousine à l’étranger, qui n’est pas sur Signal, j’ai lancé Whatsapp qui m’a affiché une erreur. Je n’ai pas prêté attention et j’ai utilisé le bon vieux SMS. Il y’a quelques jours, cette erreur m’est revenue en tête. La version de Whatsapp sur mon téléphone n’était plus valide depuis février, car je n’avais pas accepté une modification des conditions. Cela faisait donc près de deux mois que j’avais littéralement oublié de vérifier Whatsapp, sans doute porté par ma déconnexion. Comme je ne le vérifiais pas, mon téléphone l’a mis dans le « frigo » et comme il était dans le frigo, il n’a pas été mis à jour.

Curieux de voir ce que j’avais « raté » comme messages durant ces deux mois, j’ai mis à jour le logiciel et relancé l’application qui m’a annoncé que mon compte était déconnecté du téléphone. Je l’ai reconnecté, acceptant probablement implicitement les nouvelles conditions, pour découvrir que j’avais été déconnecté de toutes les conversations depuis février. Aucun message après cette date ne m’est parvenu.

Je ne sais pas ce qu’ont vu ceux qui ont tenté de me contacter, mais il est tout de même intéressant de constater que le système n’accepte pas qu’on puisse se déconnecter pour une durée assez longue. Nos téléphones sont littéralement conçus pour nous occuper tout le temps. Pour qu’on s’occupe d’eux.

Finalement, cette anti-fonctionnalité s’est révélée intéressante.

Car j’ai immédiatement été dans les préférences de mon compte et je l’ai supprimé définitivement sans avoir le moindre scrupule ou la moindre angoisse de rater quelque chose. Ai-je raté des opportunités ? Ai-je brisé des amitiés à cause de ce silence sur la plateforme appartenant à Facebook ? Je ne le saurai jamais, Whatsapp s’en est chargé à ma place…

Comme de nombreux services modernes, Whatsapp n’est indispensable que parce qu’on veut qu’il le soit. Parce que Facebook cherche à vous le faire croire en exploitant la peur ancestrale d’être exclus d’un groupe social.

Il suffit de s’en passer pour observer que le monde continue à tourner. Qu’il tourne probablement un tout petit mieux avec un compte Whatsapp de moins.

=> Suppression de mon compte Linkedin le 13 avril 2021

=> Suppression de mes comptes Facebook/Twitter en octobre 2021.

Recevez les billets par mail ou par RSS. Max 2 billets par semaine, rien d’autre. Adresse email jamais partagée et définitivement effacée lors du désabonnement. Dernier livre paru : Printeurs, thriller cyberpunk. Pour soutenir l’auteur, lisez, offrez et partagez des livres.

Ce texte est publié sous la licence CC-By BE.

April 04, 2022

We know that many of you are waiting on your FOSDEM T-shirt and hoodie. We finally have some news, but first we would like to apologize not only for not delivering your T-shirt in time, but also for not communicating or informing you of the status of your order. Now onto the better news: it took a very long time for the order to arrive at our T-shirt supplier. We currently are investigating why it took so long and we didn't receive an update earlier, but the good news is that they are finally printing and will be shipped舰

April 01, 2022

Petite vulgarisation du fonctionnement d’Internet et de son impact sur notre cerveau et notre société


Ce texte vous parait long, rébarbatif, indigeste. Pas d’animations, pas de vidéos. Il y’a de grandes chances que votre cerveau ait graduellement perdu sa capacité de concentration. Vous préférez désormais papillonner entre deux messages au lieu de lire un long texte. Si vous êtes plus jeune, vous n’avez peut-être jamais eu cette capacité à vous concentrer.

Ce n’est pas de votre faute. Votre cerveau est, à dessein, manipulé pour perdre sa capacité de concentration. Pour devenir une meilleure éponge publicitaire. Ce n’est pas une théorie du complot, mais une simple observation des mécanismes techniques mis en œuvre. La bonne nouvelle c’est que cette capacité de concentration peut être retrouvée.

Ce texte comme la vidéo du chaton trop mignon et le message « kess tu fé? lol! » qui vient de s’afficher sur votre écran ne sont, à la base, que des impulsions électriques envoyées depuis mon ordinateur vers le vôtre (que vous appelez téléphone, mais cela reste un ordinateur). Des 1 et des 0. Rien d’autre.

Comment est-ce possible ? Comment des 1 et des 0 peuvent-ils donner le pouvoir d’apprendre tout en nous faisant perdre la capacité de le faire ?

Compter en n’utilisant que 1 et 0 : le binaire

Tout système de communication est doté d’un alphabet, un ensemble de caractères arbitraires qui peuvent être assemblés pour former des mots. Certaines langues disposent de milliers de caractères (comme l’écriture chinoise).

Notre système de numération, hérité des Arabes, compte 10 chiffres qui permettent d’écrire une infinité de nombres. On pourrait également l’utiliser pour coder un message en remplaçant les lettres de l’alphabet. 01 serait A, 02 serait B et 26 serait Z. « BONJOUR » s’écrirait donc simplement « 02151410152118 ». Cela nous semble complexe, mais peut-être que si nous l’apprenions très jeune, nous pourrions lire ce système couramment. À noter que j’ai sciemment utilisé le 0 pour différencier le « 11 = AA (deux fois 1) » de « 11 = K (onze) ».

Nous avons donc réduit notre alphabet de 26 caractères à 10 via cette simple méthode.

Comment pourrions-nous réduire encore ? Par exemple en supprimant le chiffre « 9 ». Sans le chiffre 9, nous pouvons compter 1,2,3,4,5,6,7,8…10. 8+1 = 10 ! C’est ce qui s’appelle compter en base « 9 », car il n’y a que 9 chiffres.

Il faut bien reconnaitre que le fait de compter en base 10 nous semble naturel, mais que c’est tout à fait arbitraire. Les Romains, eux-mêmes, étaient incapables de le faire. Les Babyloniens, portant des sandales ou étant pieds nus, comptaient en base 20 (et nous tenons d’eux cette propension à dire « quatre-vingt », une « vingtaine »). D’autres comptaient en base douze. Certaines peuplades, comptant sur leurs phalanges au lieu de leurs doigts, utilisaient la base 14 (essayez sur vos phalanges, vous verrez).

Mais revenons à notre base 10, devenue base 9. Si nous retirons le 8, nous obtenons que 7+1 = 10. Et, logiquement, 77 + 1 = 100. De la même manière, nous pouvons retirer tous les nombres jusqu’à n’avoir plus que 0 et 1. Auquel cas, on pourra compter de la manière suivante : 0, 1, 10, 11, 100, 101, 110, 111, 1000, 1001, …

Cette arithmétique binaire, notamment décrite par Leibniz, était une curiosité mathématique. Elle va cependant acquérir son importance lorsque vint l’idée de transmettre des messages à travers un câble électrique.

Sur un fil électrique, il n’y a que deux états possibles. Soit le courant passe, soit le courant ne passe pas. On ne peut transmettre que deux lettres, que nous notons désormais arbitrairement 0 et 1.

Vous remarquez qu’il est indispensable de se mettre d’accord sur la signification à donner à ces lettres. Au début du XIXe siècle, Samuel Morse propose le code qui porte son nom et qui est encore utilisé aujourd’hui. Mais ce code n’est pas du binaire ! En effet, il joue sur la longueur d’un signal et sur les silences entre les signaux. Techniquement, il y’a quatre lettres dans l’alphabet morse : le court, le long, le silence court et le silence long). Le morse est particulièrement adapté à la compréhension humaine. Les opérateurs télégraphiques qui l’utilisent quotidiennement deviennent capables de comprendre les messages en morse presque en temps réel.

Vers la fin du XIXe siècle apparaissent les machines à écrire et avec elles l’idée de transmettre des caractères écrits via une ligne électrique voire via ce qu’on appelle encore l’invention de Marconi : la radio. Pour simplifier, nous allons considérer que toute onde radio (radio, gsm, wifi, 3G, 4G, 5G) n’est jamais qu’un fil invisible. Dans tous les cas, on sait faire passer des 1 et des 0 d’une extrémité à l’autre du fil.

L’un des premiers codes proposant de convertir les lettres en binaire est le code Baudot, qui utilise 5 bits (le terme « bit » signifie « binary digit » ou « chiffre binaire »). 5 bits permettent 32 caractères possibles, ce qui est très peu. L’alphabet latin comporte 26 caractères, en majuscules et minuscules, ce qui fait 52, 10 chiffres, des symboles de ponctuation. Les langues comme le français rajoutent des caractères comme À,Ê,É,Ǜ,….

Les télétypes font leurs apparitions au début du XXe siècle. Il s’agit de machines à écrire reliées à un câble de communication. À chaque pression de la lettre du clavier, le code correspondant est envoyé et active l’impression du caractère correspondant à l’autre bout du câble. Un réseau de communication basé sur ce système se met en place mondialement: le réseau télex, notamment utilisé par les journalistes. Les particuliers peuvent également s’envoyer des télégrammes, qui sont facturés au mot ou à la lettre.

Envoyer des données binaires n’est pas une mince affaire, car le courant électrique a tendance à s’affaiblir avec la distance (on parle de « dispersion »). De plus, un courant n’est jamais parfaitement allumé ou éteint. It trace des courbes en forme de sinusoïdes. Il faut donc déterminer arbitrairement à partir de quand on considère un signal reçu comme un 1 ou un 0. Il faut également déterminer combien de temps dure chaque bit pour différencier 00000 de 0. Et que faire si le signal varie durant la période d’un bit? Prendre la valeur moyenne du courant?

La grande difficulté consiste donc à se mettre d’accord, à standardiser. C’est ce qu’on appelle un protocole. Un protocole n’est utile que si chacun peut le comprendre et l’utiliser à sa guise pour coder ou décoder des messages. Le langage parlé et le langage écrit sont des exemples de protocoles : nous associons des concepts à des sons et des images complètement arbitraires. Mais nous nous comprenons tant que cette association arbitraire est partagée.

Pour remplacer le code Baudot, chaque fabricant d’ordinateurs développe son propre codage. Ce n’est évidemment pas pratique aussi les Américains développent-ils l’ASCII, un codage sur 7 bits. Cela permet l’utilisation de 128 caractères au lieu de 32. Remarquons que la seule réelle innovation de l’ASCII est de mettre tout le monde d’accord, de créer un protocole, un langage.

En ASCII, A s’écrit 1000001, B 1000010, etc. Le « a » minuscule, lui, s’écrit 1100001. C’est pratique, le deuxième bit change pour identifier les majuscules des minuscules. À savoir que l’ASCII est particulièrement optimisé pour l’utilisation sur télétypes. L’ASCII prévoit des codes de contrôle de la machine comme le retour à la ligne, le fait d’activer une sonnette, de débuter ou de terminer une transmission.

Les premiers ordinateurs sont alimentés en données via des cartes perforées (un trou représente un bit 1, pas de trou un bit 0), mais, très vite, l’idée vient d’utiliser un clavier. Comme les télétypes sont disponibles, ceux-ci sont utilisés. Très naturellement, les premiers ordinateurs se mettent à stocker leurs données au format ASCII qui se prête bien à l’écriture sur carte perforée.

L’ASCII ne permet cependant que d’écrire en anglais. Beaucoup de caractères pour le français n’existent pas et les langues utilisant d’autres alphabets sont tout bonnement intraduisibles. Plusieurs solutions techniques ont été utilisées au cours du temps. Depuis les années 2010, le codage UTF-8 s’impose graduellement. Il permet l’écriture de la plupart des langues connues, y compris les langues mortes, les symboles mathématiques, scientifiques, mais également des centaines d’émojis. La particularité de l’UTF-8 est d’être compatible avec l’ASCII. Les caractères ASCII gardent exactement le même code binaire en UTF-8.

Les limites de l’ASCII se ressentent encore souvent dans l’informatique moderne : il n’est pas toujours possible de créer une adresse email possédant un accent ou de taper certains caractères dans la communication d’un virement chez certaines banques. L’utilisation d’encodages anciens fait parfois s’afficher des caractères bizarres.

Stocker des données : les formats

Si n’importe quelle donnée peut être convertie en bits, nous remarquons très vite que le point essentiel est de se mettre d’accord sur la manière de les convertir. Cette conversion se fait pour transformer la donnée et la stocker, c’est ce qu’on appelle le « format de fichier ». Un format ne repose pas toujours sur du texte. Pour stocker une image ou un son, par exemple, il faut définir d’autres formats que les formats texte. Il faut être capable de transformer une donnée en bits pour le stocker et, inversement, de transformer les bits en données pour y accéder.

Il existe deux grandes catégories de formats sur les ordinateurs. Les formats « texte », qui reposent sur un encodage de texte (ASCII, UTF-8 ou autres) et les autres, dits « formats binaires ». La particularité d’un format texte c’est que n’importe quel ordinateur dans le monde pourra toujours les ouvrir pour y lire le texte. Les formats binaires, eux, sont complètement incompréhensibles si on ne dispose pas de l’explication sur la manière de le traiter. On parle de « format ouvert » lorsque cette explication est disponible et de « format propriétaire » lorsqu’elle ne l’est pas.

Le texte a cependant des limites. Imaginons que nous souhaitions lui ajouter une mise en forme. L’une des solutions serait de définir un format complètement différent du texte standard (ASCII ou UTF-8). C’est ce qu’a fait par exemple Microsoft avec Word et le format .doc (ensuite devenu .docx). L’intérêt est évident pour l’entreprise : une fois qu’un utilisateur sauve ses données au format .doc, il est obligé d’utiliser Microsoft Word pour y accéder. Il ne peut pas utiliser un concurrent, car le format est propriétaire et que seul Microsoft Word permet d’ouvrir les documents. L’utilisateur doit donc convertir toutes ses données, ce qui peut être très long, voire impossible. L’utilisateur est prisonnier d’un logiciel appartenant à une entreprise. Ce n’est pas un détail, c’est une technique commerciale sciemment mise au point. Le terme technique est « vendor lock-in ».

Le format .doc étant tellement populaire, il finira malgré tout par être « compris » et implémenté dans des logiciels concurrents, cela malgré l’opposition active de Microsoft (on parle de « rétro-ingéniérie »). Pour répondre à des accusations légales d’abus de position dominante, Microsoft sortira le format successeur, le .docx, en le proclamant « format ouvert », les spécifications techniques étant disponibles. Cependant, et je parle d’expérience, il s’avérera que les spécifications techniques étaient d’une complexité ahurissante, qu’elles étaient par moment incomplètes voire fausses. De cette manière, si un concurrent comme LibreOffice offrait la possibilité d’ouvrir un fichier .docx, de subtiles différences étaient visibles, ce qui convainquait l’utilisateur que LibreOffice était buggué.

À l’opposé, des formats existent pour utiliser du texte afin de définir des styles.

Le plus connu et utilisé aujourd’hui est l’HTML, inventé par Tim Berners-Lee. Le principe du HTML est de mettre des textes entre des balises, également en texte. Le tout n’est donc qu’un unique texte.

Ces mots sont <b>en gras (bold)</b> et en <i>italique</i>.

Vous pouvez constater que, même sans comprendre le HTML, le texte reste « lisible ». Si vous sauvez vos données en HTML, vous êtes certains de toujours pouvoir les lire, quel que soit le logiciel. Le HTML permet d’insérer des références vers des images (qui seront alors intégrées à la page) ou vers d’autres pages, ce qu’on appelle des « liens ».

Utiliser les données : les algorithmes

Un ordinateur n’est jamais qu’une machine à calculer qui effectue des opérations sur des suites de bits pour les transformer en une autre suite de bits. Ces opérations sont déterminées par un programmeur. Un ensemble d’opérations est généralement appelé un « algorithme ». L’algorithme est une abstraction mathématique qui n’existe que dans la tête du programmeur. Lorsqu’il se décide à les écrire, dans un format de texte en suivant un « language », cet algorithme est transformé en « programme ». Oui, le programme est à la base un fichier texte. Les programmeurs écrivent donc du texte qui va servir à transformer des textes en d’autres.

Il est important de comprendre qu’un programme ne fait que ce qu’un programmeur lui a demandé. Il prend des données en entrées (des « inputs ») et fournit des données en sorties (des « outputs »). Un navigateur web prend en input un fichier HTML et le transforme pour l’afficher sur votre écran (votre écran est donc l’output).

Parfois, le programme ne fonctionne pas comme le programmeur l’avait imaginé, souvent parce que l’input sort de l’habituel. On parle alors d’un « bug », traduit désormais en « bogue ». Le bug est une erreur, un imprévu. Qui peut même résulter en un « crash » ou « plantage » (le programme ne sait plus du tout quoi faire et s’interrompt brutalement).

Tout ce que fait un programme est donc décidé à l’avance par un être humain. Y compris les crashs, qui sont des erreurs humaines du programmeur ou de l’utilisateur qui n’a pas respecté les consignes du programmeur.

Il existe cependant une nouvelle catégorie de programmes auxquels le nom spectaculaire a donné une grande visibilité : l’intelligence artificielle. Sous ce terme trompeur se cache un ensemble d’algorithmes qui ne sont pas du tout des robots tueurs, mais qui sont essentiellement statistiques. Au lieu de donner un output fixé par le programmeur, les programmes « intelligents » vont donner un résultat statistique, une probabilité.

Si un programme doit décider si une photo représente un homme ou un singe, il va, à la fin de son algorithme, fournir une valeur binaire : 1 pour l’homme et 0 pour le singe. Le programmeur humain va, par exemple, tenter de détecter la taille relative du visage et du crâne. Mais il est conscient qu’il peut se tromper. S’il est consciencieux, il va peut-être même consulter des zoologues et des anatomistes pour leur demander quelques règles générales.

Les algorithmes statistiques (dits « d’intelligence artificielle ») fonctionnent tous sur le même principe. Au lieu de demander à un programmeur de déterminer les règles qui différencient un singe d’un humain, les programmeurs vont concevoir un algorithme qui « s’initialise » avec une série de photos d’humains et une série de photos de singes. À charge du programme de détecter des corrélations qui échapperaient à l’œil humain. En output, l’algorithme va fournir une probabilité que la photo soit un humain ou un singe.

Le problème c’est que ces méthodes sont incroyablement sensibles aux biais de la société. Imaginons que l’équipe détectant le logiciel humain/singe injecte dans l’algorithme des photos d’eux-mêmes et de leur famille. Ils vont également au zoo local pour prendre les photos de singes. Le logiciel est testé et il fonctionne.

Ce que personne n’a réalisé c’est que toute l’équipe est composée de personnes de race blanche. Leur famille également. Les membres l’ayant testé également. Or, au zoo, le pavillon des chimpanzés était fermé.

Il s’ensuit que l’algorithme a très bien compris comment reconnaitre un singe : la photo est plus foncée. La première personne de race noire qui se présente devant le logiciel se fera donc traiter de singe. Le biais raciste de la société s’est vu renforcé alors même qu’aucun des programmeurs n’était raciste.

Les algorithmes apprenant avec des données issues de leurs propres algorithmes, ces biais se renforcent. Dans certaines villes aux États-Unis, les polices ont été équipées d’algorithmes « d’intelligence artificielle » pour prédire les prochaines infractions et savoir où envoyer des patrouilles. Ces algorithmes ont fait exploser le taux d’infractions dans les quartiers pauvres.

Le fait d’avoir des patrouilles en permanence à fait en sorte que les policiers furent bien plus à même d’observer et d’agir sur les petits délits (vente de drogue, tapage, jet de déchets, etc.). Ces délits renforcèrent la conviction que ces zones pauvres connaissaient plus de délits. Et pour cause : il n’y avait plus de policiers ailleurs. Le nombre d’interventions augmenta, mais la qualité de ces interventions chuta. Les policiers furent moins présents pour les crimes passionnels et les cambriolages, plus rares et également répartis dans les quartiers riches.

Nous pouvons voir un effet majeur des biais de ces « intelligences artificielles » sur Facebook : un algorithme pense que vous serez intéressé par la guerre en Ukraine. Vous cliquez, car il n’y a rien d’autre à lire et c’est désormais acté dans les algorithmes que vous êtes intéressés par la guerre en Ukraine. Vous vous verrez donc proposer des nouvelles sur la guerre en Ukraine. Comme elles vous sont proposées, vous cliquez dessus, ce qui renforce la conviction que vous êtes un véritable passionné de ce sujet.

Sous le terme « Intelligence artificielle », nous avons en fait conçu des systèmes statistiques à prophéties autoréalisatrices. Le simple fait de croire que ces systèmes puissent avoir raison crée de toutes pièces une réalité dans laquelle ces algorithmes ont raison.

Un autre problème éthique majeur soulevé par ces algorithmes, c’est que le programmeur n’est plus nécessairement informé de la problématique de base. Un algorithme de différenciation de photos, par exemple, sera développé génériquement pour diviser une série de photos dans une catégorie A et une catégorie B. Si on lui fournit des humains en A et des singes en B, il va apprendre à détecter cette différence. On peut également lui fournir des hommes en A et des femmes en B. Ou bien des citoyens reconnus en A et une minorité ethnique à éliminer en B.

Si une intelligence artificielle entrainée à trouver des rebelles en Afghanistan apprend que les terroristes sont susceptibles de changer de carte SIM plusieurs fois par jour près de la frontière avec le Pakistan, qu’un médecin effectuant la navette quotidienne vers plusieurs hôpitaux est mis par erreur sur cette liste et qu’il est tué par un drone lors d’une frappe ciblée (cas réel), est-ce la faute du programmeur de l’algorithme, de ceux qui ont générés les données concernant les terroristes ou ceux qui ont entré ces données dans l’algorithme ?

À noter que, scientifiquement, ces algorithmes sont incroyablement intéressants et utiles. Leur utilisation doit, cependant, être encadrée par des personnes compétentes qui en comprennent les forces et les faiblesses.

Transmettre des données

Stocker les données n’est pas suffisant, encore faut-il pouvoir les transmettre. De nouveau, le nœud du problème est de se mettre d’accord. Comment transmettre les bits ? Dans quel ordre ? À quelle vitesse ? Comment détecter les erreurs de transmission ?

C’est le rôle du protocole.

La particularité des protocoles, c’est qu’on peut les empiler en couches successives, les « encapsuler ».

Physiquement, un ordinateur ne peut transmettre des données qu’aux ordinateurs auxquels il est directement relié, que ce soit par câble ou par wifi (qui est encore un protocole, mais que vous pouvez imaginer comme un fil invisible). Le protocole le plus utilisé pour cela aujourd’hui est Ethernet. Observez votre routeur (votre « box »), il comporte généralement des emplacements pour connecter des câbles Ethernet (entrées jaunes et rectangulaires, le format de ce connecteur étant appelé RJ-45, car il y’a aussi un protocole pour le format des prises, on parle alors de « norme » ou de « standard »).

Dans les années 70, une idée géniale voit le jour : celle de permettre à des ordinateurs non connectés directement de s’échanger des messages en passant par d’autres ordinateurs qui serviraient de relais. Le protocole est formalisé sous le nom « INTERNET PROTOCOL ». Chaque ordinateur reçoit donc une adresse IP composée de quatre nombres entre 0 et 255 : (par exemple). Tout ordinateur ayant une adresse IP fait donc partie d’Internet. Le nombre de ces adresses est malheureusement limité et, pour résoudre cela, de nouvelles adresses voient le jour : les adresses IPv6. Les adresses IPv6 ne sont pas encore la norme, mais sont disponibles chez certains fournisseurs.

Le protocole IP (sur lequel on rajoute le protocole TCP, on parle donc souvent de TCP/IP) permet de relier les ordinateurs entre eux, mais ne dit pas encore comment négocier des échanges de données. Ce n’est pas tout de savoir envoyer des bits vers un ordinateur n’importe où dans le monde, encore faut-il les envoyer dans un langage qu’il comprend afin qu’il réponde dans un langage que moi je comprends.

Les premiers temps de l’Internet virent l’explosion de protocoles permettant d’échanger différents types de données, chacun définissant son propre réseau. Le protocole UUCP, par exemple, permettant la synchronisation de données, fut utilisé par le réseau Usenet, l’ancêtre des forums de discussions. Le protocole FTP permet d’échanger des fichiers. Le protocole Gopher permet d’échanger des textes structurés hiérarchiquement (selon le format Gophermap). Le protocole SMTP permet d’échanger des emails (selon le format MIME). Chaque protocole est, traditionnellement, associé avec un format (sans que ce soit une obligation). En 1990, Tim Berners-Lee propose le protocole HTTP auquel il associe le format HTML. Le réseau HTTP+HTML est appelé le Web. Il est important de noter que le Web n’est qu’une petite partie d’Internet. Internet existait avant le Web et il est possible d’utiliser Internet sans aller sur le web (on peut télécharger ses mails, lire sur le réseau Gopher voire sur le tout nouveau réseau Gemini, consulter les forums sur Usenet, le tout sans aller sur le web ni lancer le moindre navigateur web).

Le web utilise un format assez traditionnel dit « client/serveur ». Un ordinateur va faire une requête vers un autre ordinateur qui sert de serveur.

Supposons que votre ordinateur (ou téléphone, montre, tablette, routeur, frigo connecté, c’est pareil, ce sont tous des ordinateurs à l’architecture similaire) souhaite accéder à Il va tout d’abord déterminer l’adresse IP qui correspond au domaine « ». Il va ensuite créer une requête au format HTTP. Cette requête dit, en substance : « Donne-moi le contenu de la page ». Le serveur répond un paquet HTTP qui dit « Le voici dans cette boîte ». La boîte en question contient un fichier texte au format HTML.

Ce fichier HTML est interprété par votre navigateur. Si le navigateur s’aperçoit qu’il y’a des références à d’autres fichiers, par exemple des images, il va envoyer les requêtes automatiquement pour les avoir.

Il est important de noter que rien ne distingue un ordinateur client d’un ordinateur serveur si ce n’est le logiciel installé. Il est tout à fait possible de transformer votre téléphone en serveur. Ce n’est juste pas pratique, car il faut être disponible 24h/24 pour répondre aux requêtes. C’est la raison pour laquelle on a mis en place des « data-centers », des salles dans lesquelles des ordinateurs tournent en permanence pour servir de serveurs et sont surveillés pour être automatiquement remplacés en cas de panne. Mais un ordinateur reste un ordinateur, qu’il soit un laptop, un téléphone, un rack dans un data-center, un routeur, une montre connectée ou un GPS dans une voiture. L’important est que tous ces ordinateurs sont reliés par câbles, les plus importants étant des câbles sous-marins qui quadrillent les océans et les mers.

Lorsque votre téléphone se connecte à Internet, il cherche, sans fil, le premier ordinateur connecté par câble qu’il peut trouver. C’est soit votre borne Wifi (qui est un ordinateur auquel il ne manque qu’un écran et un clavier), soit l’ordinateur de votre fournisseur téléphonique qui se trouve dans la tour 3/4/5G la plus proche. Les fameuses antennes GSM (pour simplifier, on peut imaginer que ces antennes sont simplement de grosses bornes Wifi, même si les protocoles GSM et Wifi sont très différents).

À noter que les satellites n’interviennent à aucun moment. L’utilisation de satellites pour accéder à Internet est en effet très rare même si on en parle beaucoup. Lorsqu’elle existe, cette utilisation ne concerne que le « dernier maillon », c’est à dire faire le lien entre l’utilisateur et le premier ordinateur connecté par câble.

L’hégémonie du web

La confusion entre Internet et le Web est courante. Le Web est en effet devenu tellement populaire que la plupart des logiciels sont désormais réécrits pour passer par le web. La plupart d’entre nous consultent désormais leurs emails à travers un « webmail » au lieu d’un logiciel parlant le protocole SMTP nativement. Les documents sont également rédigés en ligne et stockés « dans le cloud ». Évidemment, cela se fait au prix d’une complexité accrue. Au lieu de recevoir des données par clavier et les afficher sur un écran, il faut désormais les envoyer via HTTP au serveur qui les convertit en HTML avant de les renvoyer, en HTTP, sur votre écran.

L’une des raisons du succès du web est que ce modèle renforce le « vendor lock-in » évoqué préalablement. Si vous aviez sauvegardé vos données au format .doc, il vous fallait Microsoft Word pour les ouvrir, mais les données restaient malgré tout en votre possession.

Le marketing lié au terme « cloud computing » a permis de populariser l’idée auparavant complètement incroyable de stocker ses données, même les plus personnelles, chez quelqu’un d’autres. Vos données, vos photos, vos documents, vos messages sont, pour la plupart d’entre vous, en totalité chez Google, Microsoft, Facebook et Apple. Quatre entreprises américaines se partagent la totalité de votre vie numérique et la possibilité de vous couper l’accès à vos données, que ce soit volontairement ou par accident (ce qui arrive régulièrement).

Ces entreprises ont construit un monopole sur l’accès à vos souvenirs et sur l’observation de vos actions et pensées. Y compris les plus secrètes et les plus inconscientes.

Car, rappelez-vous, en visitant une page Web, vous allez automatiquement envoyer des requêtes pour les ressources sur cette page. Il suffit donc d’ajouter dans les pages des ressources « invisibles » pour savoir sur quelle page vous êtes allé. Cela porte le nom de « analytics » ou « statistiques ». L’immense majorité du web contient désormais des « Google Analytics » ou des « widgets Facebook ». Cela signifie que ces entreprises savent exactement quelles pages vous avez visitées, avec quel appareil, à quelle heure, en provenant de quelle autre page. Elles peuvent même souvent connaitre votre position. Ces données sont croisées avec vos achats par carte de crédit (le mieux c’est si vous utilisez Google Pay/Apple Pay, mais Google possède un accord de partage de données avec Mastercard).

Pour faire de vous un client, une entreprise devait auparavant développer un logiciel puis vous convaincre de l’installer sur votre ordinateur. Désormais, il suffit de vous convaincre de visiter une page web et d’y entrer des données. Une fois ces données entrées, vous êtes et resterez pour toujours dans leurs bases de données clients. J’ai personnellement fait l’expérience de tenter de lister et de me désinscrire de plus de 500 services web. Malgré le RGPD, il s’est avéré impossible d’être supprimé pour plus d’un quart de ces services.

L’Université Catholique de Louvain est un bon exemple pour illustrer la manière dont ce mécanisme se met en place. Historiquement, l’UCL était un pionnier dans le domaine d’Internet et plus spécialement de l’email. La toute première liste de diffusion email ne concernait que des universités américaines et canadiennes avec deux exceptions : une université en Écosse et l’Université Catholique de Louvain. Le thème et l’expertise dans ce domaine sont donc importants. La faculté d’ingénierie, aujourd’hui École Polytechnique de Louvain, comprit très vite l’importance d’offrir des adresses email à ses étudiants. Les emails étaient, bien entendus, gérés en interne dans des ordinateurs de l’université.

Début des années 2010, ce service a été étendu à toute l’université, ce qui a entrainé une surcharge de travail, mais, surtout, une perte de contrôle de la part de la faculté d’informatique. L’administration de l’université, malgré l’opposition de membres éminents de la faculté d’informatique, a décidé de migrer les adresses des étudiants sur les serveurs Google, mais de garder les adresses du membre du personnel sur un serveur interne de type Microsoft Outlook.

Après quelques années, Microsoft a annoncé que si, au lieu d’utiliser Outlook en interne, les comptes mails étaient désormais hébergés sur les ordinateurs de Microsoft, les utilisateurs bénéficieraient de 100Go de stockage au lieu de 5Go. Les étudiants ont été également transférés de Google à Microsoft.

Au final, absolument toutes les données universitaires, y compris les plus intimes, y compris les plus confidentielles, sont dans les mains toutes puissantes de Microsoft. Parce que c’était plus facile et que chaque utilisateur y gagnait 95Go pour stocker l’incroyable quantité de mails que l’université se sent obligée d’envoyer à chacun de ses membres sans leur permettre de se désabonner. Parce que tout le monde le fait et qu’on ne peut en vouloir à ceux qui prennent ces décisions.

Toute donnée envoyée sur le cloud doit être considérée comme publique, car il est impossible de savoir exactement qui y a accès ni de garantir qu’elles seront un jour effacées. De même, toute donnée sur le cloud doit être considérée comme pouvant disparaitre ou pouvant être modifiée à chaque instant.

Analyse de la situation

Comme nous l’avons vu tout au long de cette explication, la communication repose sur l’existence d’un protocole ouvert et partagé. Le contrôle du langage est d’ailleurs l’une des premières armes des tyrans. Cependant, l’existence d’un protocole nécessite un accord. Se mettre d’accord est difficile, prend du temps, nécessite de faire des choix et des compromis.

La tendance actuelle est de chercher à éviter de faire des choix, à se recentraliser sur ce que les autres utilisent sans se poser de questions. On se recentralise sur le Web au point de le confondre avec Internet. On se recentralise sur Google/Facebook au point de les confondre avec le Web. Les développeurs informatiques eux-mêmes se recentralisent sur la plateforme Github (appartenant à… Microsoft), la confondant avec le logiciel de développement décentralisé Git.

Par confort, nous cherchons à éviter de faire trop de choix, mais le prix à payer est que d’autres font ces choix à notre place et nous en oublions que ces choix sont même possibles. Ces choix étant oubliés, ils deviennent de plus en plus difficiles à imaginer. Un cercle vicieux se met en place : au plus les monopoles ont du pouvoir, au plus il est difficile de ne pas utiliser un monopole, ce qui entraine le renforcement du pouvoir du monopole en question.

Quelques entreprises, toutes issues d’un même pays avec des ingénieurs qui se connaissent et qui viennent des mêmes universités, contrôlent : les ordinateurs que nous utilisons, les logiciels que nous y installons, les données traitées dans ces logiciels. Elles contrôlent également ce que nous allons voir, ce que nous allons lire, ce que nous allons acheter. Elles peuvent imposer des délais et des tarifs aux fournisseurs. Étant la principale source d’information des électeurs, les politiciens leur mangent dans la main.

Ces entreprises ont également un seul et unique but commun : nous faire passer un maximum de temps devant notre écran afin de nous afficher un maximum de publicités et de nous faire régulièrement renouveler notre matériel. Toute l’incroyable infrastructure du web et des milliers de cerveaux parmi les plus intelligents du monde se consacrent à une seule et unique tâche : comment faire en sorte que nous soyons le plus possible sur l’ordinateur dans notre poche sans jamais nous poser la question de savoir comment il fonctionne.

Grâce aux algorithmes statistiques, tout cela est désormais automatique. Personne chez Facebook ou Google ne va promouvoir des théories complotistes ou des discours d’extrême droite. C’est tout simplement que l’algorithme a appris ce qui fait revenir et réagir les utilisateurs, ce qui les empêche de réfléchir. Dans la catégorie A, l’utilisateur a été soumis à des textes de Hugo et Zola entrecoupés d’articles du Monde Diplomatique. Dans la catégorie B, un utilisateur a été soumis à des dizaines de « Incroyable : la vérité enfin dévoilée », « vous ne croirez pas ce que cette dame a fait pour sauver son enfant » et « Le candidat d’extrême droite traite les musulmans de cons ». Lequel de A ou B a cliqué sur le plus de lien et passé le plus de temps sur son téléphone ? Dans quelle catégorie d’articles va tenter d’apparaitre le politicien cherchant à se faire élire ?

La presse « traditionnelle » a été complètement détruite par ce modèle. Non pas à cause de l’érosion des ventes, mais parce que les journalistes sont désormais jugés aux articles qui font le plus de « clics ». Le rédacteur en chef ne pose plus des choix humains, il se contente de suivre les statistiques en temps réels. La plupart des salles de rédaction disposent désormais d’écrans affichant, en temps réels, les articles qui fonctionnent le mieux sur les réseaux sociaux. Même les blogs les plus personnels ne peuvent se passer de statistiques.

La plupart des entreprises, depuis votre boulangerie de quartier aux multinationales, utilisent les services de Google et/ou Microsoft. Cela signifie que toutes leurs données, toute leur infrastructure, toute leur connaissance, toute leur logistique sont confiées à une autre entreprise qui peut, du jour au lendemain, devenir un concurrent ou entrer en conflit. On a fait également croire que cette infrastructure était nécessaire. Est-ce que votre boucherie de quartier a vraiment besoin d’une page Facebook pour attirer des clients ? Est-ce que l’association locale d’aide aux démunis doit absolument communiquer sur Twitter ?

Les politiciens, la presse et l’économie d’une grande partie du monde sont donc entièrement soumises à quelques entreprises américaines, entreprises dont le business-model établi et avoué est de tenter de manipuler notre conscience et notre libre arbitre en nous espionnant et en abusant de nos émotions. Ces entreprises vivant du budget alloué au marketing nous font en permanence croire que nous devons, tous et tout le temps, faire du marketing. Du personnal-branding. Mettre en évidence notre carrière et nos vacances de rêves. Communiquer sur les actions associatives. Se montrer au lieu de faire. Prétendre au lieu d’être.

Ces entreprises cherchent également à cacher le plus possible le fonctionnement d’Internet tel que je vous l’ai expliqué. Elles tentent de le rendre incompréhensible, magique, mystique. Elles s’opposent légalement à toute tentative de comprendre les protocoles et les formats qu’elles utilisent. C’est à dessein. Parce que la compréhension est la première étape, nécessaire et indispensable, vers la liberté.

Internet est aujourd’hui partout. Il est incontournable. Mais plus personne ne prend la peine de l’expliquer. C’est de l’IA avec des blockchains dans un satellite. C’est magique. Même les développeurs informatiques utilisent des « frameworks REACT dans un Docker virtualisé » pour éviter de se poser la question « Que suis-je en train de construire réellement ? ».

Tenter de le comprendre est un devoir. Une rébellion. Si mon écran me captive autant, s’il affiche ces données particulières, c’est parce que d’autres êtres humains y ont un intérêt majeur. Parce qu’ils l’ont décidé. Et ce n’est probablement pas dans mon intérêt de leur obéir aveuglément. Ni dans celui de la société au sens large.

Lectures recommandées

Sur l’influence et la problématique des monopoles : « Monopolized: Life in the Age of Corporate Power » , David Dayen.
Sur le traitement de nos données et l’invasion dans notre vie privée : « The Age of Surveillance Capitalism », Shoshana Zuboff
Sur l’impact d’Internet sur nos facultés mentales : « Digital Minimalism », Cal Newport et « La fabrique du crétin digital », Michel Desmurget
Sur le fonctionnement des réseaux sociaux : « Ten Arguments For Deleting Your Social Media Accounts Right Now », Jaron Lanier

Recevez les billets par mail ou par RSS. Max 2 billets par semaine, rien d’autre. Adresse email jamais partagée et définitivement effacée lors du désabonnement. Dernier livre paru : Printeurs, thriller cyberpunk. Pour soutenir l’auteur, lisez, offrez et partagez des livres.

Ce texte est publié sous la licence CC-By BE.

March 31, 2022

"The global COVID-19 pandemic has had countless impacts on society. One interesting effect is that it has created an environment in which many people have been able to explore their gender identity and, in many cases, undergo a gender transition. As organizations return to in-person work, be it full-time or hybrid, there is a greater chance of “out” transgender, non-binary, or gender non-conforming employees in the workforce." (From the "5 Ally Actions Newsletter - Mar 25, 2022")

March 31 is the Transgender Day of Visibility. The COVID Cocoon is a nickname given for the phenomenon of people discovering their gender diversity during the pandemic environment.

The full report is an interesting read; one recommendation that we can all contribute to is on Culture and Communication: Proactively communicating that gender diversity is accepted, asking staff for their input, and being open and ready to listen helps create a culture where employees can feel safe, welcome, and valued.

Taken from The Playlist - a curated perspective on the intersection of form and content (subscribe, discuss)

flattr this!

March 29, 2022

Hier in België hebben wij arbeidsregels. Jullie hebben die in Nederland ook.

Wanneer een bedrijf onze Belgische regels aan haar laars lapt dan kan het gebeuren dat we de zaakvoerder van dat bedrijf in een Belgische gevangenis stoppen. Dat is niet uitgesloten.

Het kan daarna ook gebeuren dat een belangrijke klant van dat bedrijf onmiddellijke vragen heeft. En dus daamee eigenlijk aangeeft dat het heel binnenkort geen klant meer van dat bedrijf zal zijn.

Ik kan me voorstellen dat binnen de ééngemaakte EU markt, PostNL met haar handelspraktijken, het het Belgische BPost oneerlijke concurrentie heeft aangedaan. Daarvoor moet er dus ook een aanzienlijke schadevergoeding komen. Uiteraard bovenop de gevangenisstraf voor de CEO van PostNL. Een beetje slavenarbeid hier komen introduceren mag niet gezien worden als een goedkope onderneming zonder echte straf. Dat begrijpen jullie toch?

Nederlanders die hier in België wat komen “ondernemen” doen er goed aan onze arbeidsregels te bestuderen. Want het kan zo maar eens gebeuren dat we jullie ondernemers en aangestelde zaakvoerders in onze Belgische gevangenissen opvangen. Dat we hun depots verzegelen en sluiten. Ongeacht de economische consequenties. Ongeacht wat jullie er van vinden. Want wij vinden soms iets anders. En het is wat wij er van vinden dat er toe doet. Gezien hier de Belgische wetgeving van toepassing is.

Ga maar aan jullie kant van de grens mensenhandel, zwartwerk, en zo verder organiseren. Doe dat maar in jullie eigen land (hoewel ik vermoed dat de EU dat ook niet heel grappig zal vinden, maar goed dat is dan jullie eigen godverdomme probleem). Jullie ondernemers die dat hier wensen te doen zijn niet welkom in België. Komen ze toch, dan worden ze veroordeeld en opgesloten in onze gevangenissen.

Tot de volgende keer.

"Your Second Brain is for preserving raw information over time until it's ready to be used, because information is perishable. Your Second Brain is the brain that doesn't forget." - Tiago Forte

Personal Knowledge Management is going through a wave of innovation with new tools like Roam, Logseq, Obsidian, Notion, RemNote, and others gaining traction over Evernote, OneNote and the like. It's a great time to get curious or reacquaint yourself with the tools and processes that strengthen learning, processing, and expressing your knowledge work.

The expression "Second Brain" has been popularized by Tiago Forte, who's been running an online cohort-based class called Building a Second Brain I took the class last year and found it a powerful distillation of an approach to PKM and note-taking. If you want to learn more, they just wrapped up the Second Brain Summit and posted all videos online: Second Brain Summit 2022 - Full Session Recordings - YouTube

The next class cohort is open for enrollment until March 30th midnight ET, at Building a Second Brain: Live 5-Week Online Course, and runs from April 12th to May 10th, 2022.

"Taking notes is the closest thing we have to time travel." - Kendrick Lamar

Taken from The Playlist - a curated perspective on the intersection of form and content (subscribe, discuss)

flattr this!

March 28, 2022

Set back in the woods, in the Vermont foothills, only accessible by a dirt road, you'll find the perfect weekend cabin called the "Baby Barn".

A great room with 20 foot ceiling, tall glass windows and a large fire place
Leica M10-R + Summilux-M 35mm f/1.4 ASPH
The great room of the Baby Barn in Londonderry, Vermont.
Baby barn
Leica M10-R + Noctilux-M 50mm f/0.95
Baby barn
Leica M10-R + Noctilux-M 50mm f/0.95

On Saturday, Vanessa and I went on a 14 km (9 mile) hike, called "Griffith Lake Loop". It is part of the Appalachian Trail. The hike took us more than 6 hours to complete. Not only did we have 640 meters (2,100 feet) of elevation gain, we also had to cross multiple streams, and hike through mud and snow. Because of the snow at higher altitudes, parts of the trail were hard to follow and quite exhausting. Two days later, my legs still hurt.

Vanessa crossing a stream by stepping from rock to rock
Leica M10-R + Summilux-M 35mm f/1.4 ASPH
Vanessa crossing one of many streams on the Griffith Lake Loop trail in Vermont.

March 25, 2022

I published the following diary on “XLSB Files: Because Binary is Stealthier Than XML“:

In one of his last diaries, Brad mentioned an Excel sheet named with a .xlsb extension. Now, it was my turn to find one… What’s the magic behind this file extension? “XLS” means that we are facing an Excel sheet and “B” means that we have a binary workbook file. Within the current Microsoft office files format, data are stored in XML. In this case, they are stored in binary. For Microsoft Office, to open a normal or binary file is the same… but for an attacker, the plus-value is the increased level of obfuscation! Indeed, it’s more difficult to extract interesting information like… [Read more]

The post [SANS ISC] XLSB Files: Because Binary is Stealthier Than XML appeared first on /dev/random.

March 22, 2022

Recently I wanted to print some PDF files containing sheet music. The tedious way to do that, would be to open them one by one in Evince and press the print button. Surely there must be a more efficient way to do that?

$ ls -l --human-readable *.pdf
-r--r--r-- 1 amedee amedee 217K apr 15  2020 'Arthur original.pdf'
-r--r--r-- 1 amedee amedee 197K apr 13  2020 'Canal en octobre.pdf'
-r--r--r-- 1 amedee amedee  14K apr 13  2020  DenAndro.pdf
-r--r--r-- 1 amedee amedee  42K apr 14  2020 'Doedel you do.pdf'
-r--r--r-- 1 amedee amedee  57K apr 13  2020  Flatworld.pdf
-r--r--r-- 1 amedee amedee  35K apr 16  2020 'Jump at the sun.pdf'
-r--r--r-- 1 amedee amedee 444K jun 19  2016 'Kadril Van Mechelen.pdf'
-r--r--r-- 1 amedee amedee  15K apr 13  2020  La-gavre.pdf
-r--r--r-- 1 amedee amedee  47K apr 13  2020 'Le petit déjeuner.pdf'
-r--r--r-- 1 amedee amedee 109K apr 13  2020  LesChaminoux__2016_04_24.cached.pdf
-r--r--r-- 1 amedee amedee 368K apr 13  2020 'Mazurka It.pdf'
-r--r--r-- 1 amedee amedee 591K apr 13  2020 'Narrendans uit Mater.pdf'
-r--r--r-- 1 amedee amedee 454K apr 13  2020 'Neverending jig.pdf'
-r--r--r-- 1 amedee amedee 1,1M apr 14  2020 'Red scissors.pdf'
-r--r--r-- 1 amedee amedee  35K apr 13  2020  Scottish-à-VirmouxSOL.pdf
-r--r--r-- 1 amedee amedee  76K apr 14  2020 'Tarantella Napolitana meest gespeelde versie.pdf'
-r--r--r-- 1 amedee amedee 198K apr 15  2020 'Zot kieken!.pdf'

There are 2 console commands for printing: lp and lpr. One comes from grandpa System V, the other from grandpa BSD, and both are included in CUPS. The nice thing about these commands is that they know how to interpret PostScript and PDF files. So this is going to be easy: just cd into the directory with the PDF files and print them all:

$ lp *.pdf
lp: Error - No default destination.

Oops. A quick Google search of this error message tells me that I don’t have a default printer.

Configuring a default printer

First I use lpstat to find all current printers:

$ lpstat -p -d
printer HP_OfficeJet_Pro_9010_NETWORK is idle.  enabled since za 12 mrt 2022 00:00:28
printer HP_OfficeJet_Pro_9010_USB is idle.  enabled since za 12 mrt 2022 00:00:17
no system default destination

I have a HP OfficeJet Pro 9012e printer, which Ubuntu recognizes as a 9010 series. Close enough. It’s connected over network and USB. I’m setting the network connection as default with lpoptions:

$ lpoptions -d $(lpstat -p -d | head --lines=1 | cut --delimiter=' ' --fields=2)
copies=1 device-uri=hp:/net/HP_OfficeJet_Pro_9010_series?ip= finishings=3 job-cancel-after=10800 job-hold-until=no-hold job-priority=50 job-sheets=none,none marker-change-time=0 media=iso_a4_210x297mm number-up=1 output-bin=face-down print-color-mode=color printer-commands=none printer-info printer-is-accepting-jobs=true printer-is-shared=true printer-is-temporary=false printer-location printer-make-and-model='HP Officejet Pro 9010 Series, hpcups 3.22.2' printer-state=3 printer-state-change-time=1649175159 printer-state-reasons=none printer-type=4124 printer-uri-supported=ipp://localhost/printers/HP_OfficeJet_Pro_9010_NETWORK sides=one-sided

I can then use lpq to verify that the default printer is ready:

$ lpq
HP_OfficeJet_Pro_9010_NETWORK is ready
no entries

Printing multiple files from console

I found that if I naively do lp *.pdf, then only the last file will be printed. That’s unexpected, and I can’t be bothered to find out why. So I just use ls and feed that to a while-loop. It’s quick and dirty, and using find+xargs would probably be better if there are “special” characters, but that’s not the case here.

There’s one caveat: when the PDF files are printed one by one, then the first page will be at the bottom of the paper stack, so I need to print them in reverse order.

$ ls --reverse *.pdf | while read f; do lp "$f"; done

With that command I got 17 print jobs in the printer queue, one for each file.

Now that I know how to print from console, I’ll probably do that more often. The man page of lp describes many useful printing options, like printing double sided:

$ lp -o media=a4 -o sides=two-sided-long-edge filename

March 18, 2022

Leica M10-R + Summilux-M 35mm f/1.4 ASPH
Leica M10-R + Summilux-M 35mm f/1.4 ASPH

Snapped these photos on my commute home. I love both the detail and the motion.