I use GnuPG to compute cryptographic signatures for my emails, git commits/tags, and software release artifacts (tarballs). Part of GnuPG is gpg-agent which talks to OpenSSH, which I login to remote servers and to clone git repositories. I dislike storing cryptographic keys on general-purpose machines, and have used hardware-backed OpenPGP keys since around 2006 when I got a FSFE Fellowship Card. GnuPG via gpg-agent handles this well, and the private key never leaves the hardware. The ZeitControl cards were (to my knowledge) proprietary hardware running some non-free operating system and OpenPGP implementation. By late 2012 the YubiKey NEO supported OpenPGP, and while the hardware and operating system on it was not free, at least it ran a free software OpenPGP implementation and eventually I setup my primary RSA key on it. This worked well for a couple of years, and when I in 2019 wished to migrate to a new key, the FST-01G device with open hardware running free software that supported Ed25519 had become available. I created a key and have been using the FST-01G on my main laptop since then. This little device has been working, the signature counter on it is around 14501 which means around 10 signatures/day since then!
Currently I am in the process of migrating towards a new laptop, and moving the FST-01G device between them is cumbersome, especially if I want to use both laptops in parallel. That s why I need to setup a new hardware device to hold my OpenPGP key, which can go with my new laptop. This is a good time to re-visit alternatives. I quickly decided that I did not want to create a new key, only to import my current one to keep everything working. My requirements on the device to chose hasn t changed since 2019, see my summary at the end of the earlier blog post. Unfortunately the FST-01G is out of stock and the newer FST-01SZ has also out of stock. While Tillitis looks promising (and I have one to play with), it does not support OpenPGP (yet). What to do? Fortunately, I found some FST-01SZ device in my drawer, and decided to use it pending a more satisfactory answer. Hopefully once I get around to generate a new OpenPGP key in a year or so, I will do a better survey of options that are available on the market then. What are your (freedom-respecting) OpenPGP hardware recommendations?
FST-01SZ circuit board
Similar to setting up the FST-01G, the FST-01SZ needs to be setup before use. I m doing the following from Trisquel 11 but any GNU/Linux system would work. When the device is inserted at first time, some kernel messages are shown (see /var/log/syslog or use the dmesg command):
usb 3-3: new full-speed USB device number 39 using xhci_hcd
usb 3-3: New USB device found, idVendor=234b, idProduct=0004, bcdDevice= 2.00
usb 3-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 3-3: Product: Fraucheky
usb 3-3: Manufacturer: Free Software Initiative of Japan
usb 3-3: SerialNumber: FSIJ-0.0
usb-storage 3-3:1.0: USB Mass Storage device detected
scsi host1: usb-storage 3-3:1.0
scsi 1:0:0:0: Direct-Access FSIJ Fraucheky 1.0 PQ: 0 ANSI: 0
sd 1:0:0:0: Attached scsi generic sg2 type 0
sd 1:0:0:0: [sdc] 128 512-byte logical blocks: (65.5 kB/64.0 KiB)
sd 1:0:0:0: [sdc] Write Protect is off
sd 1:0:0:0: [sdc] Mode Sense: 03 00 00 00
sd 1:0:0:0: [sdc] No Caching mode page found
sd 1:0:0:0: [sdc] Assuming drive cache: write through
sdc:
sd 1:0:0:0: [sdc] Attached SCSI removable disk
Interestingly, the NeuG software installed on the device I got appears to be version 1.0.9:
jas@kaka:~$ head /media/jas/Fraucheky/README
NeuG - a true random number generator implementation
Version 1.0.9
2018-11-20
Niibe Yutaka
Free Software Initiative of Japan
What's NeuG?
============
jas@kaka:~$
I could not find version 1.0.9 published anywhere, but the device came with a SD-card that contain a copy of the source, so I uploaded it until a more canonical place is located. Putting the device in the serial mode can be done using a sudo eject /dev/sdc command which results in the following syslog output.
usb 3-3: reset full-speed USB device number 39 using xhci_hcd
usb 3-3: device firmware changed
usb 3-3: USB disconnect, device number 39
sdc: detected capacity change from 128 to 0
usb 3-3: new full-speed USB device number 40 using xhci_hcd
usb 3-3: New USB device found, idVendor=234b, idProduct=0001, bcdDevice= 2.00
usb 3-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 3-3: Product: NeuG True RNG
usb 3-3: Manufacturer: Free Software Initiative of Japan
usb 3-3: SerialNumber: FSIJ-1.0.9-42315277
cdc_acm 3-3:1.0: ttyACM0: USB ACM device
Now download Gnuk, verify its integrity and build it. You may need some additional packages installed, try apt-get install gcc-arm-none-eabi openocd python3-usb. As you can see, I m using the stable 1.2 branch of Gnuk, currently on version 1.2.20. The ./configure parameters deserve some explanation. The kdf_do=required sets up the device to require KDF usage. The --enable-factory-reset allows me to use the command factory-reset (with admin PIN) inside gpg --card-edit to completely wipe the card. Some may consider that too dangerous, but my view is that if someone has your admin PIN it is game over anyway. The --vidpid=234b:0000 is specifies the USB VID/PID to use, and --target=FST_01SZ is critical to set the platform (you ll may brick the device if you pick the wrong --target setting).
jas@kaka:~/src$ rm -rf gnuk neug
jas@kaka:~/src$ git clone https://gitlab.com/jas/neug.git
Cloning into 'neug'...
remote: Enumerating objects: 2034, done.
remote: Counting objects: 100% (2034/2034), done.
remote: Compressing objects: 100% (603/603), done.
remote: Total 2034 (delta 1405), reused 2013 (delta 1405), pack-reused 0
Receiving objects: 100% (2034/2034), 910.34 KiB 3.50 MiB/s, done.
Resolving deltas: 100% (1405/1405), done.
jas@kaka:~/src$ git clone https://salsa.debian.org/gnuk-team/gnuk/gnuk.git
Cloning into 'gnuk'...
remote: Enumerating objects: 13765, done.
remote: Counting objects: 100% (959/959), done.
remote: Compressing objects: 100% (337/337), done.
remote: Total 13765 (delta 629), reused 907 (delta 599), pack-reused 12806
Receiving objects: 100% (13765/13765), 12.59 MiB 3.05 MiB/s, done.
Resolving deltas: 100% (10077/10077), done.
jas@kaka:~/src$ cd neug
jas@kaka:~/src/neug$ git describe
release/1.0.9
jas@kaka:~/src/neug$ git tag -v git describe
object 5d51022a97a5b7358d0ea62bbbc00628c6cec06a
type commit
tag release/1.0.9
tagger NIIBE Yutaka <gniibe@fsij.org> 1542701768 +0900
Version 1.0.9.
gpg: Signature made Tue Nov 20 09:16:08 2018 CET
gpg: using EDDSA key 249CB3771750745D5CDD323CE267B052364F028D
gpg: issuer "gniibe@fsij.org"
gpg: Good signature from "NIIBE Yutaka <gniibe@fsij.org>" [unknown]
gpg: aka "NIIBE Yutaka <gniibe@debian.org>" [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: 249C B377 1750 745D 5CDD 323C E267 B052 364F 028D
jas@kaka:~/src/neug$ cd ../gnuk/
jas@kaka:~/src/gnuk$ git checkout STABLE-BRANCH-1-2
Branch 'STABLE-BRANCH-1-2' set up to track remote branch 'STABLE-BRANCH-1-2' from 'origin'.
Switched to a new branch 'STABLE-BRANCH-1-2'
jas@kaka:~/src/gnuk$ git describe
release/1.2.20
jas@kaka:~/src/gnuk$ git tag -v git describe
object 9d3c08bd2beb73ce942b016d4328f0a596096c02
type commit
tag release/1.2.20
tagger NIIBE Yutaka <gniibe@fsij.org> 1650594032 +0900
Gnuk: Version 1.2.20
gpg: Signature made Fri Apr 22 04:20:32 2022 CEST
gpg: using EDDSA key 249CB3771750745D5CDD323CE267B052364F028D
gpg: Good signature from "NIIBE Yutaka <gniibe@fsij.org>" [unknown]
gpg: aka "NIIBE Yutaka <gniibe@debian.org>" [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: 249C B377 1750 745D 5CDD 323C E267 B052 364F 028D
jas@kaka:~/src/gnuk/src$ git submodule update --init
Submodule 'chopstx' (https://salsa.debian.org/gnuk-team/chopstx/chopstx.git) registered for path '../chopstx'
Cloning into '/home/jas/src/gnuk/chopstx'...
Submodule path '../chopstx': checked out 'e12a7e0bb3f004c7bca41cfdb24c8b66daf3db89'
jas@kaka:~/src/gnuk$ cd chopstx
jas@kaka:~/src/gnuk/chopstx$ git describe
release/1.21
jas@kaka:~/src/gnuk/chopstx$ git tag -v git describe
object e12a7e0bb3f004c7bca41cfdb24c8b66daf3db89
type commit
tag release/1.21
tagger NIIBE Yutaka <gniibe@fsij.org> 1650593697 +0900
Chopstx: Version 1.21
gpg: Signature made Fri Apr 22 04:14:57 2022 CEST
gpg: using EDDSA key 249CB3771750745D5CDD323CE267B052364F028D
gpg: Good signature from "NIIBE Yutaka <gniibe@fsij.org>" [unknown]
gpg: aka "NIIBE Yutaka <gniibe@debian.org>" [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: 249C B377 1750 745D 5CDD 323C E267 B052 364F 028D
jas@kaka:~/src/gnuk/chopstx$ cd ../src
jas@kaka:~/src/gnuk/src$ kdf_do=required ./configure --enable-factory-reset --vidpid=234b:0000 --target=FST_01SZ
Header file is: board-fst-01sz.h
Debug option disabled
Configured for bare system (no-DFU)
PIN pad option disabled
CERT.3 Data Object is NOT supported
Card insert/removal by HID device is NOT supported
Life cycle management is supported
Acknowledge button is supported
KDF DO is required before key import/generation
jas@kaka:~/src/gnuk/src$ make less
jas@kaka:~/src/gnuk/src$ cd ../regnual/
jas@kaka:~/src/gnuk/regnual$ make less
jas@kaka:~/src/gnuk/regnual$ cd ../../
jas@kaka:~/src$ sudo python3 neug/tool/neug_upgrade.py -f gnuk/regnual/regnual.bin gnuk/src/build/gnuk.bin
gnuk/regnual/regnual.bin: 4608
gnuk/src/build/gnuk.bin: 109568
CRC32: b93ca829
Device:
Configuration: 1
Interface: 1
20000e00:20005000
Downloading flash upgrade program...
start 20000e00
end 20002000
# 20002000: 32 : 4
Run flash upgrade program...
Wait 1 second...
Wait 1 second...
Device:
08001000:08020000
Downloading the program
start 08001000
end 0801ac00
jas@kaka:~/src$
The kernel log will contain the following, and the card is ready to use as an OpenPGP card. You may unplug it and re-insert it as you wish.
usb 3-3: reset full-speed USB device number 41 using xhci_hcd
usb 3-3: device firmware changed
usb 3-3: USB disconnect, device number 41
usb 3-3: new full-speed USB device number 42 using xhci_hcd
usb 3-3: New USB device found, idVendor=234b, idProduct=0000, bcdDevice= 2.00
usb 3-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 3-3: Product: Gnuk Token
usb 3-3: Manufacturer: Free Software Initiative of Japan
usb 3-3: SerialNumber: FSIJ-1.2.20-42315277
Setting up the card is the next step, and there are many tutorials around for this, eventually I settled with the following sequence. Let s start with setting the admin PIN. First make sure that pcscd nor scdaemon is running, which is good hygien since those processes cache some information and with a stale connection this easily leads to confusion. Cache invalidation sigh.
jas@kaka:~$ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye
jas@kaka:~$ ps auxww grep -e pcsc -e scd
jas 30221 0.0 0.0 3468 1692 pts/3 R+ 11:49 0:00 grep --color=auto -e pcsc -e scd
jas@kaka:~$ gpg --card-edit
Reader ...........: 234B:0000:FSIJ-1.2.20-42315277:0
Application ID ...: D276000124010200FFFE423152770000
Application type .: OpenPGP
Version ..........: 2.0
Manufacturer .....: unmanaged S/N range
Serial number ....: 42315277
Name of cardholder: [not set]
Language prefs ...: [not set]
Salutation .......:
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
KDF setting ......: off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]
gpg/card> admin
Admin commands are allowed
gpg/card> kdf-setup
gpg/card> passwd
gpg: OpenPGP card no. D276000124010200FFFE423152770000 detected
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit
Your selection? 3
PIN changed.
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit
Your selection?
Now it would be natural to setup the PIN and reset code. However the Gnuk software is configured to not allow this until the keys are imported. You would get the following somewhat cryptical error messages if you try. This took me a while to understand, since this is device-specific, and some other OpenPGP implementations allows you to configure a PIN and reset code before key import.
Your selection? 4
Error setting the Reset Code: Card error
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit
Your selection? 1
Error changing the PIN: Conditions of use not satisfied
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit
Your selection? q
Continue to configure the card and make it ready for key import. Some settings deserve comments. The lang field may be used to setup the language, but I have rarely seen it use, and I set it to sv (Swedish) mostly to be able to experiment if any software adhears to it. The URL is important to point to somewhere where your public key is stored, the fetch command of gpg --card-edit downloads it and sets up GnuPG with it when you are on a clean new laptop. The forcesig command changes the default so that a PIN code is not required for every digital signature operation, remember that I averaged 10 signatures per day for the past 2-3 years? Think of the wasted energy typing those PIN codes every time! Changing the cryptographic key type is required when I import 25519-based keys.
gpg/card> name
Cardholder's surname: Josefsson
Cardholder's given name: Simon
gpg/card> lang
Language preferences: sv
gpg/card> sex
Salutation (M = Mr., F = Ms., or space): m
gpg/card> login
Login data (account name): jas
gpg/card> url
URL to retrieve public key: https://josefsson.org/key-20190320.txt
gpg/card> forcesig
gpg/card> key-attr
Changing card key attribute for: Signature key
Please select what kind of key you want:
(1) RSA
(2) ECC
Your selection? 2
Please select which elliptic curve you want:
(1) Curve 25519
(4) NIST P-384
Your selection? 1
The card will now be re-configured to generate a key of type: ed25519
Note: There is no guarantee that the card supports the requested size.
If the key generation does not succeed, please check the
documentation of your card to see what sizes are allowed.
Changing card key attribute for: Encryption key
Please select what kind of key you want:
(1) RSA
(2) ECC
Your selection? 2
Please select which elliptic curve you want:
(1) Curve 25519
(4) NIST P-384
Your selection? 1
The card will now be re-configured to generate a key of type: cv25519
Changing card key attribute for: Authentication key
Please select what kind of key you want:
(1) RSA
(2) ECC
Your selection? 2
Please select which elliptic curve you want:
(1) Curve 25519
(4) NIST P-384
Your selection? 1
The card will now be re-configured to generate a key of type: ed25519
gpg/card>
Reader ...........: 234B:0000:FSIJ-1.2.20-42315277:0
Application ID ...: D276000124010200FFFE423152770000
Application type .: OpenPGP
Version ..........: 2.0
Manufacturer .....: unmanaged S/N range
Serial number ....: 42315277
Name of cardholder: Simon Josefsson
Language prefs ...: sv
Salutation .......: Mr.
URL of public key : https://josefsson.org/key-20190320.txt
Login data .......: jas
Signature PIN ....: not forced
Key attributes ...: ed25519 cv25519 ed25519
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
KDF setting ......: on
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]
gpg/card>
The device is now ready for key import! Bring out your offline laptop and boot it and use the keytocard command on the subkeys to import them. This assumes you saved a copy of the GnuPG home directory after generating the master and subkeys before, which I did in my own previous tutorial when I generated the keys. This may be a bit unusual, and there are simpler ways to do this (e.g., import a copy of the secret keys into a fresh GnuPG home directory).
$ cp -a gnupghome-backup-mastersubkeys gnupghome-import-fst01sz-42315277-2022-12-24
$ ps auxww grep -e pcsc -e scd
$ gpg --homedir $PWD/gnupghome-import-fst01sz-42315277-2022-12-24 --edit-key B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE
...
Secret key is available.
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
sec ed25519/D73CF638C53C06BE
created: 2019-03-20 expired: 2019-10-22 usage: SC
trust: ultimate validity: expired
ssb cv25519/02923D7EE76EBD60
created: 2019-03-20 expired: 2019-10-22 usage: E
ssb ed25519/80260EE8A9B92B2B
created: 2019-03-20 expired: 2019-10-22 usage: A
ssb ed25519/51722B08FE4745A2
created: 2019-03-20 expired: 2019-10-22 usage: S
[ expired] (1). Simon Josefsson <simon@josefsson.org>
gpg> key 1
sec ed25519/D73CF638C53C06BE
created: 2019-03-20 expired: 2019-10-22 usage: SC
trust: ultimate validity: expired
ssb* cv25519/02923D7EE76EBD60
created: 2019-03-20 expired: 2019-10-22 usage: E
ssb ed25519/80260EE8A9B92B2B
created: 2019-03-20 expired: 2019-10-22 usage: A
ssb ed25519/51722B08FE4745A2
created: 2019-03-20 expired: 2019-10-22 usage: S
[ expired] (1). Simon Josefsson <simon@josefsson.org>
gpg> keytocard
Please select where to store the key:
(2) Encryption key
Your selection? 2
sec ed25519/D73CF638C53C06BE
created: 2019-03-20 expired: 2019-10-22 usage: SC
trust: ultimate validity: expired
ssb* cv25519/02923D7EE76EBD60
created: 2019-03-20 expired: 2019-10-22 usage: E
ssb ed25519/80260EE8A9B92B2B
created: 2019-03-20 expired: 2019-10-22 usage: A
ssb ed25519/51722B08FE4745A2
created: 2019-03-20 expired: 2019-10-22 usage: S
[ expired] (1). Simon Josefsson <simon@josefsson.org>
gpg> key 1
sec ed25519/D73CF638C53C06BE
created: 2019-03-20 expired: 2019-10-22 usage: SC
trust: ultimate validity: expired
ssb cv25519/02923D7EE76EBD60
created: 2019-03-20 expired: 2019-10-22 usage: E
ssb ed25519/80260EE8A9B92B2B
created: 2019-03-20 expired: 2019-10-22 usage: A
ssb ed25519/51722B08FE4745A2
created: 2019-03-20 expired: 2019-10-22 usage: S
[ expired] (1). Simon Josefsson <simon@josefsson.org>
gpg> key 2
sec ed25519/D73CF638C53C06BE
created: 2019-03-20 expired: 2019-10-22 usage: SC
trust: ultimate validity: expired
ssb cv25519/02923D7EE76EBD60
created: 2019-03-20 expired: 2019-10-22 usage: E
ssb* ed25519/80260EE8A9B92B2B
created: 2019-03-20 expired: 2019-10-22 usage: A
ssb ed25519/51722B08FE4745A2
created: 2019-03-20 expired: 2019-10-22 usage: S
[ expired] (1). Simon Josefsson <simon@josefsson.org>
gpg> keytocard
Please select where to store the key:
(3) Authentication key
Your selection? 3
sec ed25519/D73CF638C53C06BE
created: 2019-03-20 expired: 2019-10-22 usage: SC
trust: ultimate validity: expired
ssb cv25519/02923D7EE76EBD60
created: 2019-03-20 expired: 2019-10-22 usage: E
ssb* ed25519/80260EE8A9B92B2B
created: 2019-03-20 expired: 2019-10-22 usage: A
ssb ed25519/51722B08FE4745A2
created: 2019-03-20 expired: 2019-10-22 usage: S
[ expired] (1). Simon Josefsson <simon@josefsson.org>
gpg> key 2
sec ed25519/D73CF638C53C06BE
created: 2019-03-20 expired: 2019-10-22 usage: SC
trust: ultimate validity: expired
ssb cv25519/02923D7EE76EBD60
created: 2019-03-20 expired: 2019-10-22 usage: E
ssb ed25519/80260EE8A9B92B2B
created: 2019-03-20 expired: 2019-10-22 usage: A
ssb ed25519/51722B08FE4745A2
created: 2019-03-20 expired: 2019-10-22 usage: S
[ expired] (1). Simon Josefsson <simon@josefsson.org>
gpg> key 3
sec ed25519/D73CF638C53C06BE
created: 2019-03-20 expired: 2019-10-22 usage: SC
trust: ultimate validity: expired
ssb cv25519/02923D7EE76EBD60
created: 2019-03-20 expired: 2019-10-22 usage: E
ssb ed25519/80260EE8A9B92B2B
created: 2019-03-20 expired: 2019-10-22 usage: A
ssb* ed25519/51722B08FE4745A2
created: 2019-03-20 expired: 2019-10-22 usage: S
[ expired] (1). Simon Josefsson <simon@josefsson.org>
gpg> keytocard
Please select where to store the key:
(1) Signature key
(3) Authentication key
Your selection? 1
sec ed25519/D73CF638C53C06BE
created: 2019-03-20 expired: 2019-10-22 usage: SC
trust: ultimate validity: expired
ssb cv25519/02923D7EE76EBD60
created: 2019-03-20 expired: 2019-10-22 usage: E
ssb ed25519/80260EE8A9B92B2B
created: 2019-03-20 expired: 2019-10-22 usage: A
ssb* ed25519/51722B08FE4745A2
created: 2019-03-20 expired: 2019-10-22 usage: S
[ expired] (1). Simon Josefsson <simon@josefsson.org>
gpg> quit
Save changes? (y/N) y
$
Now insert it into your daily laptop and have GnuPG and learn about the new private keys and forget about any earlier locally available card bindings this usually manifests itself by GnuPG asking you to insert a OpenPGP card with another serial number. Earlier I did rm -rf ~/.gnupg/private-keys-v1.d/ but the scd serialno followed by learn --force is nicer. I also sets up trust setting for my own key.
jas@kaka:~$ gpg-connect-agent "scd serialno" "learn --force" /bye
...
jas@kaka:~$ echo "B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE:6:" gpg --import-ownertrust
jas@kaka:~$ gpg --card-status
Reader ...........: 234B:0000:FSIJ-1.2.20-42315277:0
Application ID ...: D276000124010200FFFE423152770000
Application type .: OpenPGP
Version ..........: 2.0
Manufacturer .....: unmanaged S/N range
Serial number ....: 42315277
Name of cardholder: Simon Josefsson
Language prefs ...: sv
Salutation .......: Mr.
URL of public key : https://josefsson.org/key-20190320.txt
Login data .......: jas
Signature PIN ....: not forced
Key attributes ...: ed25519 cv25519 ed25519
Max. PIN lengths .: 127 127 127
PIN retry counter : 5 5 5
Signature counter : 3
KDF setting ......: on
Signature key ....: A3CC 9C87 0B9D 310A BAD4 CF2F 5172 2B08 FE47 45A2
created ....: 2019-03-20 23:40:49
Encryption key....: A9EC 8F4D 7F1E 50ED 3DEF 49A9 0292 3D7E E76E BD60
created ....: 2019-03-20 23:40:26
Authentication key: CA7E 3716 4342 DF31 33DF 3497 8026 0EE8 A9B9 2B2B
created ....: 2019-03-20 23:40:37
General key info..: sub ed25519/51722B08FE4745A2 2019-03-20 Simon Josefsson <simon@josefsson.org>
sec# ed25519/D73CF638C53C06BE created: 2019-03-20 expires: 2023-09-19
ssb> ed25519/80260EE8A9B92B2B created: 2019-03-20 expires: 2023-09-19
card-no: FFFE 42315277
ssb> ed25519/51722B08FE4745A2 created: 2019-03-20 expires: 2023-09-19
card-no: FFFE 42315277
ssb> cv25519/02923D7EE76EBD60 created: 2019-03-20 expires: 2023-09-19
card-no: FFFE 42315277
jas@kaka:~$
Verify that you can digitally sign and authenticate using the key and you are done!
jas@kaka:~$ echo foo gpg -a --sign gpg --verify
gpg: Signature made Sat Dec 24 13:49:59 2022 CET
gpg: using EDDSA key A3CC9C870B9D310ABAD4CF2F51722B08FE4745A2
gpg: Good signature from "Simon Josefsson <simon@josefsson.org>" [ultimate]
jas@kaka:~$ ssh-add -L
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILzCFcHHrKzVSPDDarZPYqn89H5TPaxwcORgRg+4DagE cardno:FFFE42315277
jas@kaka:~$
So time to relax and celebrate christmas? Hold on not so fast! Astute readers will have noticed that the output said PIN retry counter: 5 5 5 . That s not the default PIN retry counter for Gnuk! How did that happen? Indeed, good catch and great question, my dear reader. I wanted to include how you can modify the Gnuk source code, re-build it and re-flash the Gnuk as well. This method is different than flashing Gnuk onto a device that is running NeuG so the commands I used to flash the firmware in the start of this blog post no longer works in a device running Gnuk. Fortunately modern Gnuk supports updating firmware by specifying the Admin PIN code only, and provides a simple script to achieve this as well. The PIN retry counter setting is hard coded in the openpgp-do.c file, and we run a a perl command to modify the file, rebuild Gnuk and upgrade the FST-01SZ. This of course wipes all your settings, so you will have the opportunity to practice all the commands earlier in this post once again!
jas@kaka:~/src/gnuk/src$ perl -pi -e 's/PASSWORD_ERRORS_MAX 3/PASSWORD_ERRORS_MAX 5/' openpgp-do.c
jas@kaka:~/src/gnuk/src$ make less
jas@kaka:~/src/gnuk/src$ cd ../tool/
jas@kaka:~/src/gnuk/tool$ ./upgrade_by_passwd.py
Admin password:
Device:
Configuration: 1
Interface: 0
../regnual/regnual.bin: 4608
../src/build/gnuk.bin: 110592
CRC32: b93ca829
Device:
Configuration: 1
Interface: 0
20002a00:20005000
Downloading flash upgrade program...
start 20002a00
end 20003c00
Run flash upgrade program...
Waiting for device to appear:
Wait 1 second...
Wait 1 second...
Device:
08001000:08020000
Downloading the program
start 08001000
end 0801b000
Protecting device
Finish flashing
Resetting device
Update procedure finished
jas@kaka:~/src/gnuk/tool$
Now finally, I wish you all a Merry Christmas and Happy Hacking!
One of my main musical 'discoveries' in 2022 was British electronic band
Underworld.
I m super late to the party. Underworld s commercial high point was the mid
nineties. And I was certainly aware of them then: the use of
Born Slippy .NUXX in 1996 s Trainspotting soundtrack was ubiquitous, but it
didn t grab me.
In more recent years my colleague and friend Andrew Dinn (with whom I enjoyed
many pre-pandemic conversations about music) enthusiastically advocated for
Underworld (and furnished me with some rarities). This started to get them
under my skin.
It took a bit longer for me to truly get them, though, and the final straw was
revisiting their BBC 6 Music Festival performance from
2016
(with Rez and it's companion piece "Cowgirl" standing out)
So where to start? There s something compelling about their whole catalogue.
This is a group with which you can go deep, if you wish.
The only album which hasn t grabbed me is 100 days off and it s probably only
a matter of time before it does (Andrew advocates the Extended Ansum Edition
bootleg here). Here are four career-spanning personal highlights:
With the end of the year approaching fast, I thought putting my year in
retrospective via music would be a fun thing to do.
Albums
In 2022, I added 51 new albums to my collection nearly one a week! I listed
them below in the order in which I acquired them.
I purchased most of these albums when I could and borrowed the rest at
libraries. If you want to browse though, I added links to the album covers
pointing either to websites where you can buy them or to Discogs when digital
copies weren't available1.
Browsing through the albums, I can see my tastes really shifted a lot in the
last few years. I used to listen to a lot of Hip-Hop, but the recent trends in
this genre2 really turn me off. In fact, it seems I didn't add a single
Hip-Hop album to my collection this year...
Metal also continues to dominate the list. Many thanks to Angry Metal
Guy for being the best metal reviewing website out there.
Concerts
2022 was also a big change for me, as I started going to much more concerts than
I previously did. metalfinder has been working great and I'm really happy
with it.
Here are the concerts I went to in 2022:
April 26th: Arch Enemy, Unto Others, Behemoth, Napalm Death
September 16th: NOFX
November 4th: Aeternam
November 7th: Jordi Savall & Hesp rion XXI
November 13th: VOLA
November 19th: Vulgaires Machins, Anti-Flag
November 26th: Soen
December 12h: Oddisee
December 16th: Jail, B ton Arm , Reckless Upstarts, Union Thugs, La Gachette
I'm looking forward continuing to go to a lot of concerts in 2023!
Some of the albums especially the O ! ones are pretty
underground. For most of those, I actually have physical copies I bought
and ripped.
Mostly mumble rap, beats than are less and less sample-based,
extreme commercialisation and lyrics that are less and less political and
engaged.
Shutdown is a history of the world macroeconomic response to
COVID-19, covering 2020 and the very beginning of 2021.
But wait, you might be saying. It's only the end of 2022 right now, and
this book was published in September of 2021. That's not history, that's
journalism. And yes, I think that's a valid critique. Shutdown is
doing something rather odd, and I'm not certain it was a good idea, but I
do think it has a (somewhat narrow) audience.
Descriptions first. After an awkward introduction (more on that later),
Tooze launches into an essentially chronological history in four parts:
the initial viral spread and early political and public health response,
the economic hard stop and macroeconomic response, the summer fallout and
political complications, and the more-organized aftershocks of the fall.
The early chapters are closer to a history, with a clear timeline and the
tracery of cause and effect. The closer the narrative comes to the time
Tooze was writing it, the more that clarity drops away. The last few
chapters feel like a collection of simultaneous events that may or may not
be related or have long-term significance.
Everyone reading this lived through those events, and if you're at all
like me, consumed far more news coverage of them than was healthy. The
obvious question, then, is why read a book that rehashes all of that? For
me, there are two answers: Tooze pays attention to more of the world than
makes it into the local headlines and tries to synthesize a larger
picture, and the focus of this book is the macroeconomic facilities used
in the response. I remember the fights over school closures in the US. I
didn't know about the impact of unprecedented Federal Reserve action on
the bond market for emerging market government debt.
If you're the sort of person who reads The Economist religiously
(which I am not), you may not learn anything new here. If you're not, and
you have a general interest in international finance, there were probably
some wrinkles you missed. Even if you stay up-to-date on the more
technical news, Shutdown provides an intermediate consolidation and
restructuring. It's not ready to be a history in the traditional sense,
but it's a first pass at putting events in order and tracing the
implications for the global financial system.
Read in that sense, Shutdown felt like a continuation of Tooze's
Crashed, following the same themes of a
hegemonic but unstable dollar system and a Federal Reserve that has
increasingly taken on the role of backstop to the entire world (and how
the only tools it has available tend to increase wealth inequality). If
you've not read Crashed, read it first. I think it's the stronger
and more thorough book (not the least because it had more time and data to
construct a coherent history), and it's the best introduction to the
international macroeconomic risks that Tooze traces in Shutdown.
This book was, for me, an update of the Tooze's thinking in Crashed
for the COVID era.
Tooze is very good at clearly describing macroeconomic shocks. I recently
read Lev Menand's The Fed Unbound, which
is in part about the same intervention during the COVID shock that Tooze
describes here, and yet it wasn't until I read Shutdown that I
grasped that the Treasury purchases by the Fed had arguably crossed the
political red line of monetizing government debt, even though the Fed
probably had no choice and few people noticed in the middle of the crisis.
This is where Tooze's background as a historian is helpful. Most people
writing on this topic are either economists, who seem to take inferences
like that for granted and dive into the technical debate, or journalists,
who rarely understand the nuance and often jump to facile conclusions.
Tooze is a historian with an extensive economics background; he can
explain the mechanics while still focusing on the limitations of politics,
which is the sort of analysis that I want to read.
The problem with this book as a history is that it necessarily raises more
questions than it answers. In the conclusion, Tooze writes:
A severe tightening in U.S. monetary policy or even a full-fledged
taper tantrum would put global resilience to a stern test. So too
would a violent escalation of geopolitical tension in one of the major
regions of the world economy.
Both of those events have subsequently happened, which throws any
tentative conclusions Tooze can offer into question.
For another example, when Tooze wrote Shutdown, China's zero COVID
policy was widely celebrated inside China and had enabled a fast economic
recovery while the rest of the world was still in serious difficulty.
Before Omicron, it was conceivable (if extremely risky) that China could
continue to avoid a major COVID surge. In December of 2022, it's obvious
they only managed to delay, and while delay meant vaccination and the
price in deaths may well be smaller than was paid for the route taken by
most of the rest of the world, the trade-offs are now even harder to
analyze.
There are, of course, other examples, the most obvious of which is the
rise of global inflation simultaneous with a strengthening dollar. A
history written from a distance of several decades would have included
that aftermath. A snap history with a distance of only a few months
cannot.
The other problem with this book is that it's not as polished. Viking did
an amazing job turning publication around in roughly six months,
dramatically faster than publishing normally works, but there are parts
that could have used more editing. The introduction, in particular, reads
more like a blog post than an edited book, and while I'm a happy reader of
Tooze's Chartbook, the recap of
COVID's impact was a bit trite and Tooze's abstract musings on polycrisis
could have used tightening and clarity. The meat of the book is better,
but there is a messy stream-of-consciousness feel that is inherent in a
book written to this tight of a timeline.
I think the audience of this book is, narrowly, people who have read
Crashed and want to follow that line of reasoning into the COVID
era. Crashed is one of the better books on macroeconomic history
that I've read, and I did indeed want to follow that train of thought, so
I am part of that audience. This is not the sort of book that I would
widely recommend, however. If you want to read it, you probably know that
already; if you are new to Tooze's analysis, Crashed is the place
to start.
Rating: 7 out of 10
Tess of the Road is the first book of a YA fantasy duology set in
the same universe as Seraphina and
Shadow Scale.
It's hard to decide what to say about reading order (and I now appreciate
the ambiguous answers I got). Tess of the Road is a sequel to
Seraphina and Shadow Scale in the sense that there are
numerous references to the previous duology, but it has a different
protagonist and different concerns. You don't need to read the other
duology first, but Tess of the Road will significantly spoil the
resolution of the romance plot in Seraphina, and it will be obvious
that you've skipped over background material. That said, Shadow
Scale is not a very good book, and this is a much better book.
I guess the summary is this: if you're going to read the first duology,
read it first, but don't feel obligated to do so.
Tess was always a curious, adventurous, and some would say unmanageable
girl, nothing like her twin. Jeanne is modest, obedient, virtuous, and
practically perfect in every way. Tess is not; after a teenage love
affair resulting in an out-of-wedlock child and a boy who disappeared
rather than marry her, their mother sees no alternative but to lie about
which of the twins is older. If Jeanne can get a good match among the
nobility, the family finances may be salvaged. Tess's only remaining use
is to help her sister find a match, and then she can be shuffled off to a
convent.
Tess throws herself into court politics and does exactly what she's
supposed to. She engineers not only a match, but someone Jeanne sincerely
likes. Tess has never lacked competence. But this changes nothing about
her mother's view of her, and Tess is depressed, worn, and desperately
miserable in Jeanne's moment of triumph. Jeanne wants Tess to stay and
become the governess of her eventual children, retaining their twin bond
of the two of them against the world. Their older sister Seraphina, more
perceptively, tries to help her join an explorer's expedition. Tess, in a
drunken spiral of misery, insults everyone and runs away, with only a new
pair of boots and a pack of food.
This is going to be one of those reviews where the things I didn't like
are exactly the things other readers liked. I see why people loved this
book, and I wish I had loved it too. Instead, I liked parts of it a great
deal and found other parts frustrating or a bit too off-putting. Mostly
this is a preference problem rather than a book problem.
My most objective complaint is the pacing, which was also my primary
complaint about Shadow Scale. It was not hard to see where Hartman
was going with the story, I like that story, I was on board with going
there, but getting there took for-EV-er. This is a 536 page book that I
would have edited to less than 300 pages. It takes nearly a hundred pages
to get Tess on the road, and while some of that setup is necessary, I did
not want to wallow in Tess's misery and appalling home life for quite that
long.
A closely related problem is that Hartman continues to love flashbacks.
Even after Tess has made her escape, we get the entire history of her
awful teenage years slowly dribbled out over most of the book. Sometimes
this is revelatory; mostly it's depressing. I had guessed the outlines of
what had happened early in the book (it's not hard), and that was more
than enough motivation for me, but Hartman was determined to make the
reader watch every crisis and awful moment in detail. This is exactly
what some readers want, and sometimes it's even what I want, but not here.
I found the middle of the book, where the story is mostly flashbacks and
flailing, to be an emotional slog.
Part of the problem is that Tess has an abusive mother and goes through
the standard abuse victim process of being sure that she's the one who's
wrong and that her mother is justified in her criticism. This is
certainly realistic, and it eventually lead to some satisfying catharsis
as Tess lets go of her negative self-image. But Tess's mother is a
narcissistic religious fanatic with a persecution complex and not a single
redeeming quality whatsoever, and I loathed reading about her, let
alone reading Tess tiptoeing around making excuses for her. The point of
this in the story is for Tess to rebuild her self-image, and I get it, and
I'm sure this will work for some readers, but I wanted Tess's mother (and
the rest of her family except her sisters) to be eaten by dragons. I do
not like the emotional experience of hating a character in a book this
much.
Where Tess of the Road is on firmer ground is when Tess has an
opportunity to show her best qualities, such as befriending a quigutl in
childhood and, in the sort of impulsive decision that shows her at her
best, learning their language. (For those who haven't read the previous
books, quigutls are a dog-sized subspecies of dragon that everyone usually
treats like intelligent animals, although they're clearly more than that.)
Her childhood quigutl friend Pathka becomes her companion on the road,
which both gives her wanderings some direction and adds some useful
character interaction.
Pathka comes with a plot that is another one of those elements that I
think will work for some readers but didn't work for me. He's in search
of a Great Serpent, a part of quigutl mythology that neither humans or
dragons pay attention to. That becomes the major plot of the novel apart
from Tess's emotional growth. Pathka also has a fraught relationship with
his own family, which I think was supposed to parallel Tess's
relationships but never clicked for me. I liked Tess's side of this
relationship, but Pathka is weirdly incomprehensible and apparently fickle
in ways that I found unsatisfying. I think Hartman was going for an alien
tone that didn't quite work for me.
This is a book that gets considerably better as it goes along, and the
last third of the book was great. I didn't like being dragged through the
setup, but I loved the character Tess became. Once she reaches the road
crew, this was a book full of things that I love reading about. The
contrast between her at the start of the book and the end is satisfying
and rewarding. Tess's relationship with her twin Jeanne deserves special
mention; their interaction late in the book is note-perfect and much
better than I had expected.
Unfortunately, Tess of the Road doesn't have a real resolution.
It's only the first half of Tess's story, which comes back to that pacing
problem. Ah well.
I enjoyed this but I didn't love it. The destination was mostly worth the
journey, but I thought the journey was much too long and I had to spend
too much time in the company of people I hated far more intensely than was
comfortable. I also thought the middle of the book sagged, a problem I
have now had with two out of three of Hartman's books. But I can see why
other readers with slightly different preferences loved it. I'm probably
invested enough to read the sequel, although I'm a bit grumbly that the
sequel is necessary.
Followed by In the Serpent's Wake.
Rating: 7 out of 10
Foreword
Freexian has been using Tryton for a few years
to handle its invoicing and accounting. We have thus also been using
the Debian packages maintained by Mathias
Behrle and
we have been funding some of his work because maintaining an ERP with more
than 50 source packages was too much for him to handle alone on his free
time.
When Mathias discovered our Project
Funding
initiative, it was quite natural for him to consider applying to be able
to bring some much needed improvements to Tryton s Debian packaging.
He s running his own consulting company
(MBSolutions) so it s easy for him to invoice
Freexian to get the money for the funded projects.
What follows is Mathias Behrle s description of the projects that he
submitted and of the work that he achieved.
If you want to contact him, you can reach out to
mathiasb@m9s.biz or
mbehrle@debian.org. You can also follow him
on Mastodon.
Report
In January 2022 I applied for two projects in the Freexian Project Funding
Initiative.
The starting point of this project was Debian Bug
#998319: tryton-server should provide
a ready-to-use production-grade server config.
To address this problem instead of only providing configuration
snippets the idea was to provide a full featured guided setup of a
Tryton production environment, thus eliminating the risks of trial and
error for the system administrator.
The goal of this project was to complete the available Tryton modules
in Debian main with the latest set available from tryton.org and to
automate the task of creating new Debian packages from Tryton modules
as much as possible.
Accomplishments
As the result of Task
1,
several new packages emerged:
tryton-server-postgresql provides the guided setup of a PostgreSQL
database backend.
tryton-server-uwsgi provides the installation and configuration of a
robust WSGI server on top of tryton-server.
tryton-server-nginx provides the configuration of a scalable web
frontend to the uwsgi server, including the optional setup of secure
access by Letsencrypt certificates.
tryton-server-all-in-one puts it all together to provide a fully
functional Tryton production environment, including a database filled
with basic static data. With the installation of this package a robust
and secure production grade setup is possible from scratch, all
configuration leg work is done in the background.
The work was thoroughly reviewed by Neil Williams. Thanks go to him for his
detailed feedback providing very valuable information from the view of a
fresh Tryton user getting in first contact with the software. A cordial
thank you as well goes to the translation teams providing initial reviews
and translations for the configuration questions.
The efforts of Task 1 were completed with Task
2:
A Tryton specific version of
PyPi2deb was
created to help in the preparation of new Debian packages for new Tryton
modules.
All missing Tryton modules for the current series were packaged for Debian.
On top of those two planned projects, I completed an additional task: the
packaging of the Tryton Web
Client.
The Web Client is a quite important feature to access a Tryton server with
the browser and even a crucial requirement for some companies.
Unfortunately the packaging of the Web Client for Debian was problematic
from the beginning. tryton-sao requires exact versions of JavaScript
libraries that are almost never guaranteed to be available in the
different targeted Debian releases. Therefore a package with vendored
libraries has been created and will hopefully soon hit the Debian main
archive. The package is already available from the Tryton
Backport Mirror for the usually
supported Debian releases.
Summary
I am very pleased that the Tryton suite in Debian has gained full coverage
of Tryton modules and a user-friendly installation. The completion of the
project represents a huge step forward in the state-of-the-art deployment
of a production grade Tryton environment. Without the monetary support of
Freexian s project funding the realization of this project wouldn t have
been possible in this way and to this extent.
While my first impression of Guix 1.4rc2 on NV41PZ was only days ago, the final Guix 1.4 release has happened. I thought I should give it a second try, although being at my summer house with no wired ethernet I realized this may be overly optimistic. However I am happy to say that a guided graphical installation on my new laptop went smooth without any problem. Practicing OS installations has a tendency to make problems disappear.
My WiFi issues last time was probably due to a user interface mistake on my part: you have to press a button to search for wireless networks before seeing them. I m not sure why I missed this the first time, but maybe the reason was that I didn t really expect WiFi to work on this laptop with one Intel-based WiFi card without firmware and a USB-based WiFi dongle. I haven t went back to the rc2 image, but I strongly believe it wasn t a problem with that image but my user mistake. Perhaps some more visual clues could be given that Guix found a usable WiFi interface, as this isn t completely obvious now.
My main pet problem with the installation is the language menu. It contains a bazillion languages, and I want to find Swedish in it. However the list is half-sorted so it looks like it is alphabetized but paging through the list I didn t find svenska , but did notice that the sorting restarts after a while. Eventually I find my language of chose, but a better search interface would be better. Typing s to find it jumps around in the list. This may be a user interface misunderstanding on my part: I may be missing whatever great logic I m sure there is to find my language in that menu.
I did a simple installation, enabling GNOME, Cups and OpenSSH. Given the experience with sharing /home with my Trisquel installation last time, I chose to not mount it this time, fixing this later on if I want to share files between OSes. Watching the installation proceed with downloading packages over this slow WiFi was meditative, and I couldn t help but wonder what logic there was to the many steps where it says it is going to download X MB of software, downloads a set of packages, and then starts another iteration saying it is going to download Y MB and then downloads another set of packages. Maybe there is a package dependency tree being worked out while I watch.
After logging into GNOME I had to provide the WiFi password another time, it seems it wasn t saved during installation, or I was too impatient to wait for WiFi to come up automatically. Using the GNOME WiFi selection menu worked fine. The webcam issue is still present, the image is distorted and it doesn t happen in Trisquel. Other than that, everythings appear to work, but it has to be put through more testing.
Upgrading Guix after installation is still suffering from the same issue I noticed with the rc2 images, this time I managed to save the error message in case someone wants to provide an official fix or workaround. The initial guix pull command also takes forever, even on this speedy laptop, but after the initial run it is faster. Here are the error messages (pardon the Swedish):
jas@kaka ~$ sudo -i
...
root@kaka ~# guix pull
...
root@kaka ~# guix system reconfigure /etc/config.scm
guix system: fel: aborting reconfiguration because commit 8e2f32cee982d42a79e53fc1e9aa7b8ff0514714 of channel 'guix' is not a descendant of 989a3916dc8967bcb7275f10452f89bc6c3389cc
tips: Use --allow-downgrades' to force this downgrade.
root@kaka ~#
I ll avoid using allow-downgrades this time to see if there is a better solution available.
Update: Problem resolved: my muscle memory typed sudo -i before writing the commands above. If I stick to the suggestedguix pull (as user) followed by sudo guix system reconfigure /etc/config.scm everything works. I ll leave this in case someone else runs into this problem.
I m using the Evolution mail/calendar/contacts application, and it was not installed via GNOME so I had to manually install it using guix package -i evolution . Following the guided setup worked remarkable well (it auto-detects all my email settings after giving it my email address), although at the end I get a surprising error message:
Puzzling error message from Evolution
If I didn t know a bit about how Evolution works internally, I would have been stuck here the solution is to install the evolution data server package. This should probably be a dependency from the main package? Fix it by guix package -i evolution-data-server . It works directly, no need to even restart Evolution or go through the configuration dialog again. After this, I m happily using email against my Dovecot server and contacts/calendars against my Nextcloud server via GNOME s builtin Nextcloud connector which was straight-forward to setup.
Artifact Space is a military (mostly) science fiction novel, the
first of an expected trilogy. Christian Cameron is a prolific author of
historical fiction under that name, thrillers under the name Gordon Kent,
and historical fantasy under the name Miles Cameron. This is his first
science fiction novel.
Marca Nbaro is descended from one of the great spacefaring mercantile
families, but it's not doing her much good. She is a ward of the
Orphanage, the boarding school for orphaned children of the DHC, generous
in theory and a hellhole in practice. Her dream to serve on one of the
Greatships, the enormous interstellar vessels that form the backbone of
the human trading network, has been blocked by the school authorities, a
consequence of the low-grade war she's been fighting with them throughout
her teenage years. But Marca is not a person to take no for an answer.
Pawning her family crest gets her just enough money to hire a hacker to
doctor her school records, adding the graduation she was denied and
getting her aboard the Greatship Athens as a new Midshipper.
I don't read a lot of military science fiction, but there is one type of
story that I love that military SF is uniquely well-suited to tell. It's
not the combat or the tactics or the often-trite politics. It's the
experience of the military as a system, a collective human endeavor.
One ideal of the military is that people come to it from all sorts of
backgrounds, races, and social classes, and the military incorporates them
all into a system built for a purpose. It doesn't matter who you are or
what you did before: if you follow the rules, do your job, and become part
of a collaboration larger than yourself, you have a place and people to
watch your back whether or not they know you or like you. Obviously, like
any ideal, many militaries don't live up to this, and there are many
stories about those failures. But the story of that ideal, told well, is
a genre I like a great deal and is hard to find elsewhere.
This sort of military story shares some features with found family, and
it's not a coincidence that I also like found family stories. But found
family still assumes that these people love you, or at least like you.
For some protagonists, that's a tricky barrier both to cross and to
believe one has crossed. The (admittedly idealized) military doesn't
assume anyone likes you. It doesn't expect that you or anyone around you
have the right feelings. It just expects you to do your job and work with
other people who are doing their job. The requirements are more concrete,
and thus in a way easier to believe in.
Artifact Space is one of those military science fiction stories. I
was entirely unsurprised to see that the author is a former US Navy career
officer.
The Greatships here are, technically, more of a merchant marine than a
full-blown military. (The author noted in an interview that he based
them on the merchant ships of Venice.) The weapons are used primarily for
defense; the purpose of the Greatships is trade, and every crew member has
a storage allotment in the immense cargo area that they're encouraged to
use. The setting is in the far future, after a partial collapse and
reconstruction of human society, in which humans have spread through
interstellar space, settled habitable planets, and built immense orbital
cities. The Athens is trading between multiple human settlements,
but its true destination is far into the deep black: Tradepoint, where it
can trade with the mysterious alien Starfish for xenoglas, a material that
humans have tried and failed to reproduce and on which much of human
construction now depends.
This is, to warn, one of those stories where the scrappy underdog of noble
birth makes friends with everyone and is far more competent than anyone
expects. The story shape is not going to surprise you, and you have to
have considerable tolerance for it to enjoy this book. Marca is
ridiculously, absurdly central to the plot for a new Middie. Sometimes
this makes sense given her history; other times, she is in the middle of
improbable accidents that felt forced by the author. Cameron doesn't
entirely break normal career progression, but Marca is very special in a
way that you only get to be as the protagonist of a novel.
That said, Cameron does some things with that story shape that I liked.
Marca's hard-won survival skills are not weirdly well-suited for
her new life aboard ship. To the contrary, she has to unlearn a lot of
bad habits and let go of a lot of anxiety. I particularly liked her
relationship with her more-privileged cabin mate, which at first seemed to
only be a contrast between Thea's privilege and Marca's background, but
turned into both of them learning from each other. There's a great mix of
supporting characters, with a wide variety of interactions with Marca and
a solid sense that all of the characters have their own lives and their
own concerns that don't revolve around her.
There is, of course, a plot to go with this. I haven't talked about it
much because I think the summaries of this book are a bit of a spoiler,
but there are several layers of political intrigue, threats to the ship,
an interesting AI, and a good hook in the alien xenoglas trade. Cameron
does a deft job balancing the plot with Marca's training and her
slow-developing sense of place in the ship (and fear about discovery of
her background and hacking). The pacing is excellent, showing all the
skill I'd expect from someone with a thriller background and over forty
prior novels under his belt. Cameron portrays the tedious work of
learning a role on a ship without boring the reader, which is a tricky
balancing act.
I also like the setting: a richly multicultural future that felt like it
included people from all of Earth, not just the white western parts. That
includes a normalized androgyne third gender, which is the sort of thing
you rarely see in military SF. Faster-than-light travel involves typical
physics hand-waving, but the shape of the hand-waving is one I've not seen
before and is a great excuse for copying the well-known property of
oceangoing navies that longer ships can go faster.
(One tech grumble, though: while Cameron does eventually say that this is
a known tactic and Marca didn't come up with anything novel, deploying
spread sensors for greater resolution is sufficiently obvious it should be
standard procedure, and shouldn't have warranted the character reactions
it got.)
I thoroughly enjoyed this. Artifact Space is the best military SF
that I've read in quite a while, at least back to John G. Hemry's
JAG in space novels and probably better than
those. It's going to strike some readers, with justification, as cliched,
but the cliches are handled so well that I had only minor grumbling at a
few absurd coincidences. Marca is a great character who is easy to care
about. The plot was tense and satisfying, and the feeling of military
structure, tradition, jargon, and ship pride was handled well. I had a
very hard time putting this down and was sad when it ended.
If you're in the mood for that class of "learning how to be part of a
collaborative structure" style of military SF, recommended.
Artifact Space reaches a somewhat satisfying conclusion, but leaves
major plot elements unresolved. Followed by Deep Black, which
doesn't have a release date at the time of this writing.
Rating: 9 out of 10
tl;dr:
Ok-wrapping as needed in today s Rust is a significant distraction, because there are multiple ways to do it. They are all slightly awkward in different ways, so are least-bad in different situations. You must choose a way for every fallible function, and sometimes change a function from one pattern to another.
Rust really needs #[throws] as a first-class language feature. Code using #[throws] is simpler and clearer.
Please try out withoutboats s fehler. I think you will like it.
Contents
A recent personal experience in coding style
Ever since I read withoutboats s 2020 article about fehler, I have been using it in most of my personal projects.
For Reasons I recently had a go at eliminating the dependency on fehler from Hippotat. So, I made a branch, deleted the dependency and imports, and started on the whack-a-mole with the compiler errors.
After about a half hour of this, I was starting to feel queasy.
After an hour I had decided that basically everything I was doing was making the code worse. And, bizarrely, I kept having to make individual decisons about what idiom to use in each place. I couldn t face it any more.
After sleeping on the question I decided that Hippotat would be in Debian withfehler, or not at all. Happily the Debian Rust Team generously helped me out, so the answer is that fehler is now in Debian, so it s fine.
For me this experience, of trying to convert Rust-with-#[throws] to Rust-without-#[throws] brought the Ok wrapping problem into sharp focus.
What is Ok wrapping? Intro to Rust error handling
(You can skip this section if you re already a seasoned Rust programer.)
In Rust, fallibility is represented by functions that return Result<SuccessValue, Error>: this is a generic type, representing either whatever SuccessValue is (in the Ok variant of the data-bearing enum) or some Error (in the Err variant). For example, std::fs::read_to_string, which takes a filename and returns the contents of the named file, returns Result<String, std::io::Error>.
This is a nice and typesafe formulation of, and generalisation of, the traditional C practice, where a function indicates in its return value whether it succeeded, and errors are indicated with an error code.
Result is part of the standard library and there are convenient facilities for checking for errors, extracting successful results, and so on. In particular, Rust has the postfix ? operator, which, when applied to a Result, does one of two things: if the Result was Ok, it yields the inner successful value; if the Result was Err, it returns early from the current function, returning an Err in turn to the caller.
This means you can write things like this:
let input_data = std::fs::read_to_string(input_file)?;
and the error handling is pretty automatic. You get a compiler warning, or a type error, if you forget the ?, so you can t accidentally ignore errors.
But, there is a downside. When you are returning a successful outcome from your function, you must convert it into a Result. After all, your fallible function has return type Result<SuccessValue, Error>, which is a different type to SuccessValue. So, for example, inside std::fs::read_to_string, we see this:
let mut string = String::new();
file.read_to_string(&mut string)?;
Ok(string)
string has type String; fs::read_to_string must return Result<String, ..>, so at the end of the function we must return Ok(string). This applies to return statements, too: if you want an early successful return from a fallible function, you must write return Ok(whatever).
This is particularly annoying for functions that don t actually return a nontrivial value. Normally, when you write a function that doesn t return a value you don t write the return type. The compiler interprets this as syntactic sugar for -> (), ie, that the function returns (), the empty tuple, used in Rust as a dummy value in these kind of situations. A block ( ... ) whose last statement ends in a ; has type (). So, when you fall off the end of a function, the return value is (), without you having to write it. So you simply leave out the stuff in your program about the return value, and your function doesn t have one (i.e. it returns ()).
But, a function which either fails with an error, or completes successfuly without returning anything, has return type Result<(), Error>. At the end of such a function, you must explicitly provide the success value. After all, if you just fall off the end of a block, it means the block has value (), which is not of type Result<(), Error>. So the fallible function must end with Ok(()), as we see in the example for std::fs::read_to_string.
A minor inconvenience, or a significant distraction?
I think the need for Ok-wrapping on all success paths from fallible functions is generally regarded as just a minor inconvenience. Certainly the experienced Rust programmer gets very used to it. However, while trying to remove fehler s #[throws] from Hippotat, I noticed something that is evident in codebases using vanilla Rust (without fehler) but which goes un-remarked.
There are multiple ways to write the Ok-wrapping, and the different ways are appropriate in different situations.
See the following examples, all taken from a real codebase. (And it s not just me: I do all of these in different places, - when I don t have fehler available - but all these examples are from code written by others.)
Idioms for Ok-wrapping - a bestiary
Wrap just a returned variable binding
If you have the return value in a variable, you can write Ok(reval) at the end of the function, instead of retval.
pub fn take_until(&mut self, term: u8) -> Result<&'a [u8]>
// several lines of code
Ok(result)
If the returned value is not already bound to variable, making a function fallible might mean choosing to bind it to a variable.
Wrap a nontrivial return expression
Even if it s not just a variable, you can wrap the expression which computes the returned value. This is often done if the returned value is a struct literal:
fn take_from(r: &mut Reader<'_>) -> Result<Self>
// several lines of code
Ok(AuthChallenge challenge, methods )
Introduce Ok(()) at the end
For functions returning Result<()>, you can write Ok(()).
This is usual, but not ubiquitous, since sometimes you can omit it.
Wrap the whole body
If you don t have the return value in a variable, you can wrap the whole body of the function in Ok(). Whether this is a good idea depends on how big and complex the body is.
fn from_str(s: &str) -> std::result::Result<Self, Self::Err>
Ok(match s
"Authority" => RelayFlags::AUTHORITY,
// many other branches
_ => RelayFlags::empty(),
)
Omit the wrap when calling fallible sub-functions
If your function wraps another function call of the same return and error type, you don t need to write the Ok at all. Instead, you can simply call the function and not apply ?.
You can do this even if your function selects between a number of different sub-functions to call:
But this doesn t work if the returned error type isn t the same, but needs the autoconversion implied by the ? operator.
Convert a fallible sub-function error with Ok( ... ?)
If the final thing a function does is chain to another fallible function, but with a different error type, the error must be converted somehow. This can be done with ?.
Convert a fallible sub-function error with .map_err
Or, rarely, people solve the same problem by converting explicitly with .map_err:
pub fn create_unbootstrapped(self) -> Result<TorClient<R>>
// several lines of code
TorClient::create_inner(
// several parameters
)
.map_err(ErrorDetail::into)
What is to be done, then?
The fehler library is in excellent taste and has the answer. With fehler:
Whether a function is fallible, and what it s error type is, is specified in one place. It is not entangled with the main return value type, nor with the success return paths.
So the success paths out of a function are not specially marked with error handling boilerplate. The end of function return value, and the expression after return, are automatically wrapped up in Ok. So the body of a fallible function is just like the body of an infallible one, except for places where error handling is actually involved.
Error returns occur through ? error chaining, and with a new explicit syntax for error return.
We usually talk about the error we are possibly returning, and avoid talking about Result unless we need to.
fehler provides:
An attribute macro #[throws(ErrorType)] to make a function fallible in this way.
A macro throws!(error) for explicitly failing.
This is precisely correct. It is very ergonomic.
Consequences include:
One does not need to decide where to put the Ok-wrapping, since it s automatic rather than explicitly written out.
Specifically, what idiom to adopt in the body (for example write!(...)?; vs write!(...) in a formatter) does not depend on whether the error needs converting, how complex the body is, and whether the final expression in the function is itself fallible.
Making an infallible function fallible involves only adding #[throws] to its definition, and ? to its call sites. One does not need to edit the body, or the return type.
Changing the error returned by a function to a suitably compatible different error type does not involve changing the function body.
There is no need for a local Result alias shadowing std::result::Result, which means that when one needs to speak of Result explciitly, the code is clearer.
Limitations of fehler
But, fehler is a Rust procedural macro, so it cannot get everything right. Sadly there are some wrinkles.
You can t write #[throws] on a closure.
Sometimes you can get quite poor error messages if you have a sufficiently broken function body.
Code inside a macro call isn t properly visible to fehler so sometimes return statements inside macro calls are untreated. This will lead to a type error, so isn t a correctness hazard, but it can be nuisance if you like other syntax extensions eg if_chain.
#[must_use] #[throws(Error)] fn obtain() -> Thing; ought to mean that Thing must be used, not the Result<Thing, Error>.
But, Rust-with-#[throws] is so much nicer a language than Rust-with-mandatory-Ok-wrapping, that these are minor inconveniences.
Please can we have #[throws] in the Rust language
This ought to be part of the language, not a macro library. In the compiler, it would be possible to get the all the corner cases right. It would make the feature available to everyone, and it would quickly become idiomatic Rust throughout the community.
It is evident from reading writings from the time, particularly those from withoutboats, that there were significant objections to automatic Ok-wrapping. It seems to have become quite political, and some folks burned out on the topic.
Perhaps, now, a couple of years later, we can revisit this area and solve this problem in the language itself ?
Explicitness
An argument I have seen made against automatic Ok-wrapping, and, in general, against any kind of useful language affordance, is that it makes things less explicit.
But this argument is fundamentally wrong for Ok-wrapping. Explicitness is not an unalloyed good. We humans have only limited attention. We need to focus that attention where it is actually needed. So explicitness is good in situtions where what is going on is unusual; or would otherwise be hard to read; or is tricky or error-prone. Generally: explicitness is good for things where we need to direct humans attention.
But Ok-wrapping is ubiquitous in fallible Rust code. The compiler mechanisms and type systems almost completely defend against mistakes. All but the most novice programmer knows what s going on, and the very novice programmer doesn t need to. Rust s error handling arrangments are designed specifically so that we can avoid worrying about fallibility unless necessary except for the Ok-wrapping. Explicitness about Ok-wrapping directs our attention away from whatever other things the code is doing: it is a distraction.
So, explicitness about Ok-wrapping is a bad thing.
Appendix - examples showning code with Ok wrapping is worse than code using #[throws]
Observe these diffs, from my abandoned attempt to remove the fehler dependency from Hippotat.
I have a type alias AE for the usual error type (AE stands for anyhow::Error). In the non-#[throws] code, I end up with a type alias AR<T> for Result<T, AE>, which I think is more opaque but at least that avoids typing out -> Result< , AE> a thousand times. Some people like to have a local Result alias, but that means that the standard Result has to be referred to as StdResult or std::result::Result.
With fehler and #[throws]
Vanilla Rust, Result<>, mandatory Ok-wrapping
Return value clearer, error return less wordy:
impl Parseable for Secret
impl Parseable for Secret
#[throws(AE)]
fn parse(s: Option<&str>) -> Self
fn parse(s: Option<&str>) -> AR<Self>
let s = s.value()?;
let s = s.value()?;
if s.is_empty() throw!(anyhow!( secret value cannot be empty ))
if s.is_empty() return Err(anyhow!( secret value cannot be empty ))
I m currently reading the second book of the TriSolar Sci-Fi series by Cixin Liu, I ve only just started it so this post can t have spoilers for it and I will also only have minimal spoilers for the first book (nothing more than you will get from pop culture references to it).
In the second book there are people called Wall Facers who have broad powers to shape the course of the Human response to an alien invasion in 400+ years time. The idea is that as the aliens have an ability to see everything that can be seen on Earth any ideas that leave the brain of one person can be snooped on, so if some people act independently without communicating their plans they can take the aliens by surprise. While that is probably going to work out well in the books history in general seems to show that people who act independently without any useful feedback from others tend to perform poorly, every king and dictator seems to demonstrate this.
Efficient Work
I ve been thinking about what I would do if I had significant powers to guide the response to an alien threat in some hundreds of years. The first thing to do would be to get all people working as efficiently as possible. Without the imminent threat of alien invasion we can have debates about how much time to spend working vs leisure time. Should we make 24 hours per week the new normal work week? But if the threat of annihilation is looming then the discussion should be about how to get as many people as possible working as much as possible.
Currently 1/4 of the world population lack access to safe drinking water [1], there s a plan to achieve universal and equitable access to safe and affordable drinking water for all by 2030 . But 2030 isn t soon enough, another 8 years where 1/4 of children born won t reach their potential due to poor water is unacceptable. Currently 13% of the world population don t have access to electricity and 40% don t have access to clean fuels for cooking [2]. Lack of energy access reduces health and opportunities for education. Healthcare is another major obstacle to human development and therefore economic development. Even some allegedly first-world countries like the US lack universal affordable healthcare.
I think we could reasonably get safe water to 99% of the world population before 2025 if we tried hard (IE applied a small fraction of the resources of a single war to it). Getting electricity to 95% of the world population and clean cooking fuels to 90% of the world population are probably achievable goals for 2025 as well.
Healthcare is a slightly harder problem as we need to train more nurses and doctors. A registered nurse apparently needs 3 years of training after completing high school. We may have to improve high schools to get more students up to the standard of nursing degrees. If it takes 3 years to improve schools in year 9+ and then 3 years to get more high school graduates that would mean that it would take about 9 years to get an increase in nurses. Doing this would require increasing the capacity of universities and making university almost free (as it was for decades). So in about 2031 we could start sending a significant number of nurses from developed countries to help out developing countries.
Becoming a doctor apparently requires 8 years of study plus a minimum of 3 years residency . So if doctors were entirely trained in first world countries then we wouldn t be able to send many doctors to developing countries until 2039. If the residency was performed in other countries then it could be as early as 2036.
According to the WHO currently only half the world s population have adequate healthcare [3]. To get adequate healthcare to the world we need to more than double the number of doctors because currently we don t have enough in countries with decent healthcare systems such as Australia. It would probably take to at least 2060 to get enough doctors trained. The end goal of course would be to have every country able to train enough of it s citizens to provide all medical services, but countries that have serious widespread healthcare problems that reduce the number of people who can pursue higher education will have difficulty in that until some of the healthcare problems are alleviated.
Education
Obviously education is important to all achievements. Currently education seems very poorly run, it is possible to create a school system that teaches children effectively without the bullying that is common in Australia and without the sort of pressure that South Korea is infamous for. One of the main issues to resolve with the school system is the idea that everyone should learn at the same speed, that goal can only be achieved by making the majority of the students learn slowly. Students should be able to freely skip ahead as their skill permits and finish school at any age. Also high school isn t for everyone, the tech schools that teach trades need to be brought back.
Deceiving Aliens
A plot point in the TriSolar series is that the aliens can see each other s thoughts, the local communication (their equivalent to talking) is based on reading each other s thoughts without the possibility of deception. While deceptive written communication is potentially possible for them they haven t developed skills in that area.
As a first step towards exploiting this humans could focus more on linguistic development that increases language complexity, such as the way the English language adopts words from other languages and gives them slightly different meanings for example the difference between driver and chauffeur and the difference between dog and hound is not obvious to many Europeans who otherwise speak English fluently.
When involved in conversation it s possible to convey meaning without directly stating things, this is used extensively by people who are interested in security. My observations of this are based on conversations with people who do government work, but I imagine that criminal organisations also do similar things for similar reasons.
An increased focus on poetry in schools might be helpful in developing skills for conveying ideas to people who think in human ways where the message is unclear to non-humans who have no experience of deception. I wonder whether the ability to understand human poetry would make aliens less hostile to humans, if they can think like us then they would be less likely to want to exterminate us.
Poker is a game that depends on the ability to deceive others, I ve never been any good at it. I wonder if making it part of the school curriculum would help improve the overall human ability to deceive aliens. I don t think that such schools would become dens of sociopathy as depicted in Kakegurui, but it might have some negative results.
Spreading education to a larger portion of the world s population requires more use of electronic education. Anything learned via text can be more easily assimilated by aliens than things that are learned directly from other people. For high school and the basics of a university degree this is fine. But for more advanced education it seems that having a large face to face component might help keep the value away from the aliens.
More Ideas?
What do you think I missed on this list? I wasn t trying to list every possibility, just the more important ones. Also for any goals other than increasing inequality for it s own sake we should improve health and education for the world.
Utkarsh Gupta
did 41.0h (out of 32.5h assigned and 25.0h from previous period), thus carrying over 16.5h to the next month.
Evolution of the situation
In November, we released 43 DLAs, fixing 183 CVEs.
We currently have 63 packages in dla-needed.txt that are waiting for updates, which is 19 fewer than the previous month.
We re excited to announce that two Debian Developers Tobias Frost
and Guilhem Moulin, have completed the on-boarding process
and will begin contributing to LTS as of December 2022. Welcome aboard!
Thanks to our sponsors
Sponsors that joined recently are in bold.
On the shortlist of things to try on my new laptop has been Guix. I have been using Guix on my rsnapshot-based backup server since 2018, and experimented using it on a second laptop but never on my primary daily work machine. The main difference with Guix for me, compared to Debian (or Trisquel), is that Guix follows a rolling release model, even though they prepare stable versioned installation images once in a while. It seems the trend for operating system software releases is to either following a Long-Term-Support approach or adopt a rolling approach. Historically I have found that the rolling release approach, such as following Debian testing, has lead to unreliable systems, since little focus was given to system integration stability. This probably changed in the last 10 years or so, and today add-on systems like Homebrew on macOS gives me access to modern releases of free software easily. While I am likely to stay with LTS releases of GNU/Linux on many systems, the experience with rolling Guix (with unattended-upgrades from a cron job to pull in new code continously) on my backup servers has been smooth: no need for re-installation or debugging of installations for over four years!
I tried the Guix 1.4 rc2 installation image on top of my previous Trisquel 11 installation; following the guided Guix installation menus was simple. I installed using wired network, since the WiFi dongle I had did not automatically become available. I put the Guix system on a separate partition, that I left empty when I installed Trisquel, and mounted the same /home that I used for Trisquel. Everything booted fine, and while I had some issues doing guix pull followed by guix system reconfigure /etc/config.scm I eventually got it working by using --allow-downgrade once. I believe this was a symptom of using a release candidate installation image. Guix did not auto-detect Trisquel or set up a Grub boot menu for it, and I have been unable to come up with the right Guix bootloader magic to add a Trisquel boot item again. Fortunately, the EFI boot choser allows me to boot Trisquel again.
Guix 1.4 uses Linux-libre 6.0 which is newer than Trisquel 11 s Linux-libre 5.15. The WiFi dongle worked automatically once the system was installed. I will continue to tweak the default system configuration that was generated, it seems a standard GNOME installation does not include Evolution on Guix. Everything else I have tested works fine, including closing the lid and suspend and then resume, however the builtin webcam has a distorted image which does not happen on Trisquel. All in all, it seems the resulting system would be usable enough for me. I will be switching between Trisquel and Guix, but expect to spend most of time for daily work within Trisquel because it gives me the stable Debian-like environment that I ve been used to for ~20 years. Sharing the same /home between Trisquel and Guix may have been a mistake: GNOME handles this badly, and the dock will only contain the lowest-common-denominator of available applications, with the rest removed permanently.
Holger Levsen: Welcome, David, thanks for taking the time to talk with us today. First, could you briefly tell me about yourself?
David: Sure! I m David A. Wheeler and
I work for the Linux Foundation as the Director of Open Source Supply Chain Security.
That just means that my job is to help open source software projects
improve their security, including its development, build, distribution,
and incorporation in larger works, all the way out to its eventual use by end-users.
In my copious free time I also teach at George Mason University (GMU); in particular,
I teach a graduate course on how to design and implement secure software.
My background is technical. I have a Bachelor s in Electronics Engineering,
a Master s in Computer Science and a PhD in Information Technology.
My PhD dissertation is connected to reproducible builds.
My PhD dissertation was on countering the Trusting Trust attack, an attack
that subverts fundamental build system tools such as compilers.
The attack was discovered by Karger & Schell in the 1970s, and later
demonstrated & popularized by Ken Thompson.
In my dissertation on trusting trust I showed that a process
called Diverse Double-Compiling (DDC) could detect trusting trust attacks.
That process is a specialized kind of reproducible build specifically designed
to detect trusting trust style attacks. In addition, countering the trusting trust
attack primarily becomes more important only when reproducible builds become
more common. Reproducible builds enable detection of
build-time subversions.
Most attackers wouldn t bother with a trusting trust attack if they could just
directly use a build-time subversion of the software they actually want to subvert.
Holger: Thanks for taking the time to introduce yourself to us. What do you think are the biggest challenges today in computing?
There are many big challenges in computing today. For example:
Lack of resilience & capacity in chip fabrication. Fabs are extraordinarily expensive,
and at the high end continue to have technological advancement.
As a result, supply is failing to meet demand, and geopolitical issues raise further concerns.
We ve seen cars, gaming consoles and many other devices
unable to be delivered due to chip shortages. More fabs are
being built, and some politicians are raising concerns, but it s unclear
that current efforts will be enough.
Lack of enough developers able to develop the software that people & organizations need.
Computers are far faster, and open source software has made software reuse
incredibly easy. However, organizations still struggle to automate
many tasks. The bottleneck is the lack of enough talented developers able to convert
ideas into working software. Low-code and no-code approaches help in specialized areas,
just like all previous automate the programmer efforts of the last 60 years, but
there s no reason to believe they will help enough.
Large scale of software. Small systems are easier to develop & maintain, but today s
systems increasingly get bigger to meet users needs & are much harder to manage.
Even small embedded systems are often supported by huge back-end systems.
Ending tail of Moore s law & rise of smartphones. Historically people would just wait a few years for their
software to speed up, but Moore s law is petering out, and smartphones are necessarily
limited by power & size limits. As a result, software developers
can t wait for the hardware to save their slow systems; they must redesign.
Switching to faster languages, or using multiple processors, is much more difficult than
waiting for performance problems to disappear.
Continuous change in interfaces. Developers continuously find reasons to change
component interfaces: perhaps they re too inflexible, too hard to use, and so on.
But now that developers are reusing hundreds, thousands, or tens of thousands of components,
managing the continuous change of the reused components is challenging.
Package managers make updating easy but don t automatically handle interface changes.
I think this is mostly a self-inflicted problem most components could support old interfaces
(like the Linux kernel does) but because it s often not acknowledged as a problem, it s often not addressed.
Security & privacy. Decades ago there were fewer computers and most computers weren t connected to a network.
Today things are different. Criminals have found many ways to attack computer systems to
make money, and nation-states have found many ways to attack computer systems for their own reasons.
Attackers now have very strong motivations to perform attacks.
Yet many developers aren t told how to develop software that resists attacks, nor
how to protect their supply chains. Operations try to monitor and recover from
attacks, but their job is difficult due to inadequately secure software that doesn t
support those monitoring & recovery efforts well either. The results are terrible security.
Holger: Do you think reproducible builds are an important part in secure computing today already?
David: Yes, but first let s put things in context.
Today, when attackers exploit software vulnerabilities, they re primarily
exploiting unintentional vulnerabilities that were created by the software
developers. There are a lot of efforts to counter this:
Train & education developers in how to develop secure software.
The OpenSSF provides a free course on how to do that (full disclosure: I m the author).
Take that course or something like it!
Add tools to your CI pipeline to detect potential vulnerabilities. Yes, they have false
positives and false negatives, so you have to also use your brain but that just means you
need to be smart about using tools, instead of not using them.
Get projects & organizations to update the components they use,
since often the vulnerabilities are well-known publicly
(e.g., Equifax in 2017). Add some tools to your development process to warn you about
components with known vulnerabilities! GitHub & GitLab both provide tools to do this,
and there are many other tools.
When starting new projects, try to use memory-safe languages. On average 70% of the
vulnerabilities in Chrome and in Microsoft are from memory safety problems; using a memory-safe
language eliminates most of them.
We re just starting to get better at this, which is good. However, attackers always
try to attack the easiest target. As our deployed software has started to be hardened
against attack, attackers have dramatically increased their attacks
on the software supply chain (Sonatype found in 2022 that there s been a 742% increase year-over-year).
The software supply chain hasn t historically gotten much attention, making it the easy target.
There are simple supply chain attacks with simple solutions:
In almost every year the top attack has been typosquatting. In typo squatting,
an attacker creates packages with almost the right name. This is an easy attack to
counter developers just need to double-check the name of a package before adding it.
But we aren t warning developers enough about it!
For more information, see papers such as the Backstabber s Knife Collection.
Last year the top software supply chain attack was dependency confusion convincing
projects to use the wrong repo for a given package. There are simple solutions to this, such as
specifying the package source and/or requiring a cryptographic hash to match.
Some attacks involve takeovers of developer accounts. In almost all cases, these are
caused by stolen passwords. Using a multi-factor authentication (MFA) token eliminates
stolen password attacks, which is why several
repositories are starting to require MFA tokens in some cases.
Unfortunately, attackers know there are other lines of attack.
One of the most dangerous is subverted build systems, as demonstrated by
the subversion of SolarWinds Orion system. In a subverted build system,
developers can review the software source code all day and see no problem,
because there is no problem there. Instead, the process to convert source code
into the code people run, called the build system , is subverted by an attacker.
One solution for countering subverted build systems is to make the build systems harder
to attack. That s a good thing to do, but you can never be confident that it was good enough .
How can you be sure it s not subverted, if there s no way to know?
A stronger defense against subverted build systems is the idea of verified reproducible builds.
A build is reproducible if given the same source code, build environment and build instructions,
any party can recreate bit-by-bit identical copies of all specified artifacts.
A build is verified if multiple different parties verify that they get the same result for that situation.
When you have a verified reproducible build, either all the parties colluded
(and you could always double-check it yourself), or the build process isn t subverted.
There is one last turtle: What if the build system tools or machines are subverted themselves?
This is not a common attack today, but it s important to know if we can address them
when the time comes. The good news is that we can address this.
For some situations reproducible builds can also counter such attacks.
If there s a loop (that is, a compiler is used to generate itself), that s called the trusting trust attack,
and that is more challenging. Thankfully, the trusting trust attack has been known about for
decades and there are known solutions. The diverse double-compiling (DDC) process that
I explained in my PhD dissertation, as well as the bootstrappable builds process, can
both counter trusting trust attacks in the software space. So there is no reason to lose hope:
there is a bottom turtle , as it were.
Holger: Thankfully, this has all slowly started to change and supply chain issues are now widely discussed, as evident by efforts like
Securing the Software Supply Chain: Recommended Practices Guide for Developers
which you shared on our mailing list. In there, Reproducible Builds are mentioned as recommended advanced practice, which is both pretty cool (we ve come a long way!), but to me it also sounds like this will take another decade until it s become standard normal procedure. Do you agree on that timeline?
David: I don t think there will be any particular timeframe. Different projects and
ecosystems will move at different speeds. I wouldn t be surprised if it
took a decade or so for them to become relatively common there are
good reasons for that.
Today the most common kinds of attacks based on software
vulnerabilities still involve unintentional vulnerabilities in operational systems.
Attackers are starting to apply supply chain attacks, but the top such attacks
today are typosquatting (creating packages with similar names) and
dependency confusion) (convincing projects to download packages from the wrong
repositories).
Reproducible builds don t counter those kinds of attacks, they
counter subverted builds. It s important to eventually have verified
reproducible builds, but understandably other issues are currently getting
prioritized first.
That said, reproducible builds are important long term.
Many people are working on countering unintentional vulnerabilities
and the most common kinds of supply chain attacks.
As these other threats are countered, attackers will increasingly target
build systems. Attackers always go for the weakest link.
We will eventually need verified reproducible builds in many situations, and
it ll take a while to get build systems able to widely perform reproducible builds,
so we need to start that work now. That s true for anything where you know
you ll need it but it will take a long time to get ready you need to start now.
Holger: What are your suggestions to accelerate adoption?
David: Reproducible builds need to be:
Easy (ideally automatic). Tools need to be modified so that reproducible builds
are the default or at least easier to do.
Transparent to projects & potential users. Many projects have no idea that their results aren t
reproducible, and many potential users of the project don t know either.
That information needs to be obvious. I ve proposed that the OpenSSF
Dashboard SIG try to reproduce builds, for at least some packages, to make it
more obvious to everyone when a project isn t reproducible. I don t know if that
will happen in that particular case, but the point is to help people learn that information
as soon as possible.
Deployed.
Experiments are great, but experiments showing that a project could be reproducible
are inadequate. We need the projects that people use to be reproducible.
I think there s a snowball effect. Once many projects packages are reproducible,
it will be easier to convince other projects to make their packages reproducible.
I also think there should be some prioritization. If a package is in wide use
(e.g., part of minimum set of packages for a widely-used Linux distribution or
framework), its reproducibility should be a special focus. If a package is vital for
supporting some societally important critical infrastructure (e.g., running dams),
it should also be considered important. You can then work on the
ones that are less important over time.
Holger: How is the Best Practices Badge going? How many projects are participating and how many are missing?
David: It s going very well. You can see some automatically-generated statistics, showing we have over 5,000 projects, adding more than 1/day on average.
We have more than 900 projects that have earned at least the passing badge level.
Holger: How many of the projects participating in the Best Practices badge engaging with reproducible builds?
David: As of this writing there are 168 projects that report meeting the reproducible builds criterion.
That s a relatively small percentage of projects. However, note that this criterion (labelled build_reproducible)
is only required for the gold badge. It s not required for the passing or silver level badge.
Currently we ve been strategically focused on getting projects to at least earn a passing badge,
and less on earning silver or gold badges.
We would love for all projects to get earn a silver or gold badge, of course, but
our theory is that projects that can t even earn a passing badge present the most risk to their users.
That said, there are some projects we especially want to see implementing higher badge levels.
Those include projects that are very widely used, so that
vulnerabilities in them can impact many systems.
Examples of such projects include the Linux kernel and curl.
In addition, some projects are used within
systems where it s important to society that they not have serious security vulnerabilities.
Examples include projects used by
chemical manufacturers, financial systems and weapons.
We definitely encourage any of those kinds of projects to earn higher badge levels.
Holger: Many thanks for this interview, David, and for all of your work at the Linux Foundation and elsewhere!
For more information about the Reproducible Builds project, please see our website at
reproducible-builds.org. If you are interested in
ensuring the ongoing security of the software that underpins our civilisation
and wish to sponsor the Reproducible Builds project, please reach out to the
project by emailing
contact@reproducible-builds.org.
Couple of weeks back I installed PostmarketOS on my idle phone Leeco Le 1s , which was paper weight for
some time now.
It all started with a roadtrip to Pondicherry (I will soon write about
this trip). As I was sitting on the front seat where Praveen s Librem
5 kept charing on the car dashboard. And we had a small discussion
about
PostmarketOS and how much new ports are available now.
My idle phone came to my mind. After reaching home I started
setting up porting pmOS to this device. Going through pmOS website, to
my surprise there is already a port for this device.
The OEM unlock is quite easy even though a little hiccup at begin (I
suspect it is solely of my cable). The Xiaomi users knows the pain of
unlocking bootloader.
With the pmOS community preferred practice of using pmbootstrap, I
built image for my device, flashed it. And phone boot stopped with
pmOS logo. I thought I went to bootloop. I tried sxmo, xfce4, everything same
nothing happening after boot logo splash.
The pmOS troubleshooting wiki is quite good. They have documented
most issues. Though screen is stuck I can still ssh to the phone.
From wiki I came to know its a screen refresh problem. I installed
msm-fb-refresher package and
ran it as a daemon.
Voila, I have a mate desktop.
Mate desktop is not at all touch friendly even though I tried to
scaled up to read and tap things on the screen. Wiki suggest xfce4 is
little more touch friendly. I started moving to xfce. Then again same
problem, stuck at boot loop.
This time it was with lightdm, I turned off CanGraphical issue warning and now I have
xfce desktop. pmos xfce seems great comparing
with mate.
Nothing works as of now from a Mobile phone point of view. The phone
maintainer says the battery is working, but I couldn t get it working.
Its always in battery mode and 50% status.
I thought the hardware buttons will never work. But with xev, I can
see the hardware key event triggering.
Contact is a standalone first-contact science fiction novel. Carl
Sagan (1934 1996) was best known as a non-fiction writer, astronomer, and
narrator of the PBS non-fiction program Cosmos. This is his first
and only novel.
Ellie Arroway is the director of Project Argus, a radio telescope array in
the New Mexico desert whose primary mission is SETI: the search for
extra-terrestrial intelligence by scanning the skies for unexpected radio
signals. Its assignment to SETI is controversial; there are radio
astronomy projects waiting, and although 25% of the telescope time is
assigned to non-SETI projects, some astronomers think the SETI mission
should be scrapped and Argus fully diverted to more useful research. That
changes overnight when Argus picks up a signal from Vega, binary pulses
representing the sequence of prime numbers.
The signal of course doesn't stop when the Earth rotates, so Ellie and her
team quickly notify every radio observatory they can get hold of to
follow the signal as it passes out of their line of sight. Before long,
nearly every country with a radio telescope is involved, and Russian help
is particularly vital since they have ship-mounted equipment. The US
military and intelligence establishment isn't happy about this and make a
few attempts to shove the genie back into the bottle and keep any further
discoveries secret, without a lot of success. (Sagan did not anticipate
the end of the Cold War, and yet ironically relations with the Russians in
his version of the 1990s are warmer by far than they are today. Not that
this makes the military types any happier.) For better or worse, making
sense of the alien signal becomes a global project.
You may be familiar with this book through its 1997 movie adaptation
starring Jodie Foster. What I didn't know before reading this book is
that it started life as a movie treatment, co-written with Ann Druyan, in
1979. When the movie stalled, Sagan expanded it into a novel. (Given the
thanks to Druyan in the author's note, it may not be far wrong to name her
as a co-author.) If you've seen the movie, you will have a good idea of
what will happen, but the book gives the project a more realistic
international scope. Ellie has colleagues carefully selected from all
over the world, including for the climactic moment of the story.
The biggest problem with Contact as a novel is that Sagan is a
non-fiction writer who didn't really know how to write a novel. The long,
detailed descriptions of the science and the astronomical equipment fit a
certain type of SF story, but the descriptions of the characters, even
Ellie, are equally detailed and yet use the same style. The book starts
with an account of Ellie's childhood and path into science written like a
biography or a magazine profile, not like a novel in which she's the
protagonist. The same is true of the other characters: we get
characterization of a sort, but the tone ranges from Wikipedia article to
long-form essay and never quite feels like a story.
Ellie is the most interesting character in the book, partly because the
way Sagan writes her is both distant but oddly compelling. Sagan (or
perhaps Druyan?) tries hard to show what life is like for a woman born in
the middle of the 20th century who is interested in science and I think
mostly succeeds, although Ellie's reactions to sexism felt weirdly
emotionless. The descriptions of her relationships are even odder and the
parts where this book felt the least like a novel, but Sagan does sell
some of that tone as reflective of Ellie's personality. She's a
scientist, the work is the center of her life, and everything else, even
when important, is secondary. It doesn't entirely make the writing style
work, but it helps.
Sagan does attempt to give Ellie a personal development arc related to her
childhood and her relationships with her father and step-father. I
thought the conclusion to that was neither believable nor anywhere near as
important as Sagan thought it was, which was off-putting. Better were her
ongoing arguments with evangelical Christians, one of whom is a
close-minded ass and the other of which is a far more interesting
character. They felt wedged into this book, and I'm dubious a realistic
version of Ellie would have been the person to have those debates, but
it's a subject Sagan clearly has deep personal interest in and that shows
in how they're written.
The other problem with Contact as a novel is that Sagan does not
take science fiction seriously as a genre, instead treating it as a way to
explore a thought experiment. To a science fiction reader, or at least to
this science fiction reader, the interesting bits of this story involve
the aliens. Those are not the bits Sagan is interested in. His attention
is on how this sort of contact, and project, would affect humanity and
human politics. We do get some more traditional science fiction near the
end of the book, but Sagan then immediately backs away from it, minimizes
that part of the story, and focuses exclusively on the emotional and
philosophical implications for humans of his thought experiment. Since I
found his philosophical musings about agnosticism and wonder and discovery
less interesting than the actual science fiction bits, I found this
somewhat annoying. The ending felt a bit more like a cheap trick than a
satisfying conclusion.
Interestingly, this entire novel is set in an alternate universe, for
reasons entirely unexplained (at least that I noticed) in the book. It's
set in the late 1990s but was written in 1985, so of course this is an
alternate future, but the 1985 of this world still isn't ours. Yuri
Gagarin was the first man to set foot on the moon, and the space program
and the Cold War developed in subtly different ways. I'm not sure why
Sagan made that choice, but it felt to me like he was separating his
thought experiment farther from our world to give the ending more
plausible deniability.
There are, at the time of the novel, permanent orbital colonies for
(mostly) rich people, because living in space turns out to greatly extend
human lifespans. That gives Sagan an opportunity to wax poetic about the
life-altering effects of seeing Earth from space, which in his alternate
timeline rapidly sped up nuclear disarmament and made the rich more
protective of the planet. This is an old bit of space boosterism that
isn't as common these days, mostly because it's become abundantly clear
that human psychology doesn't work this way. Sadly, rich sociopaths
remain sociopaths even when you send them into space. I was a bit torn
between finding Sagan's predictions charmingly hopeful and annoyingly
daft.
I don't think this novel is very successful as a novel. It's much longer
than it needs to be and long parts of it drag. But it's still oddly
readable; even knowing the rough shape of the ending in advance, I found
it hard to put down once the plot properly kicks into gear about
two-thirds of the way through. There's a lot in here that I'd argue with
Sagan about, but he's thoughtful and makes a serious attempt to work out
the political and scientific ramifications of such a discovery in detail.
Despite the dry tone, he does a surprisingly good job capturing the
anticipation and excitement of a very expensive and risky scientific
experiment.
I'm not sure I would recommend this book to anyone, but I'm also the
person who found Gregory Benford's Timescape to be boring and tedious, despite its rave reviews as a
science fiction novel about the practice of science. If that sort of book
is more your jam, you may like Contact better than I did.
Rating: 6 out of 10
First up: what I'm covering here is probably not relevant for most people. That's ok! Different situations have different threat models, and if what I'm talking about here doesn't feel like you have to worry about it, that's great! Your life is easier as a result. But I have worked in situations where we had to care about some of the scenarios I'm going to describe here, and the technologies I'm going to talk about here solve a bunch of these problems.
So. You run a typical VM in the cloud. Who has access to that VM? Well, firstly, anyone who has the ability to log into the host machine with administrative capabilities. With enough effort, perhaps also anyone who has physical access to the host machine. But the hypervisor also has the ability to inspect what's running inside a VM, so anyone with the ability to install a backdoor into the hypervisor could theoretically target you. And who's to say the cloud platform launched the correct image in the first place? The control plane could have introduced a backdoor into your image and run that instead. Or the javascript running in the web UI that you used to configure the instance could have selected a different image without telling you. Anyone with the ability to get a (cleverly obfuscated) backdoor introduced into quite a lot of code could achieve that. Obviously you'd hope that everyone working for a cloud provider is honest, and you'd also hope that their security policies are good and that all code is well reviewed before being committed. But when you have several thousand people working on various components of a cloud platform, there's always the potential for something to slip up.
Let's imagine a large enterprise with a whole bunch of laptops used by developers. If someone has the ability to push a new package to one of those laptops, they're in a good position to obtain credentials belonging to the user of that laptop. That means anyone with that ability effectively has the ability to obtain arbitrary other privileges - they just need to target someone with the privilege they want. You can largely mitigate this by ensuring that the group of people able to do this is as small as possible, and put technical barriers in place to prevent them from pushing new packages unilaterally.
Now imagine this in the cloud scenario. Anyone able to interfere with the control plane (either directly or by getting code accepted that alters its behaviour) is in a position to obtain credentials belonging to anyone running in that cloud. That's probably a much larger set of people than have the ability to push stuff to laptops, but they have much the same level of power. You'll obviously have a whole bunch of processes and policies and oversights to make it difficult for a compromised user to do such a thing, but if you're a high enough profile target it's a plausible scenario.
How can we avoid this? The easiest way is to take the people able to interfere with the control plane out of the loop. The hypervisor knows what it booted, and if there's a mechanism for the VM to pass that information to a user in a trusted way, you'll be able to detect the control plane handing over the wrong image. This can be achieved using trusted boot. The hypervisor-provided firmware performs a "measurement" (basically a cryptographic hash of some data) of what it's booting, storing that information in a virtualised TPM. This TPM can later provide a signed copy of the measurements on demand. A remote system can look at these measurements and determine whether the system is trustworthy - if a modified image had been provided, the measurements would be different. As long as the hypervisor is trustworthy, it doesn't matter whether or not the control plane is - you can detect whether you were given the correct OS image, and you can build your trust on top of that.
(Of course, this depends on you being able to verify the key used to sign those measurements. On real hardware the TPM has a certificate that chains back to the manufacturer and uniquely identifies the TPM. On cloud platforms you typically have to retrieve the public key via the metadata channel, which means you're trusting the control plane to give you information about the hypervisor in order to verify what the control plane gave to the hypervisor. This is suboptimal, even though realistically the number of moving parts in that part of the control plane is much smaller than the number involved in provisioning the instance in the first place, so an attacker managing to compromise both is less realistic. Still, AWS doesn't even give you that, which does make it all rather more complicated)
Ok, so we can (largely) decouple our trust in the VM from having to trust the control plane. But we're still relying on the hypervisor to provide those attestations. What if the hypervisor isn't trustworthy? This sounds somewhat ridiculous (if you can't run a trusted app on top of an untrusted OS, how can you run a trusted OS on top of an untrusted hypervisor?), but AMD actually have a solution for that. SEV ("Secure Encrypted Virtualisation") is a technology where (handwavily) an encryption key is generated when a new VM is created, and the memory belonging to that VM is encrypted with that key. The hypervisor has no access to that encryption key, and any access to memory initiated by the hypervisor will only see the encrypted content. This means that nobody with the ability to tamper with the hypervisor can see what's going on inside the OS (and also means that nobody with physical access can either, so that's another threat dealt with).
But how do we know that the hypervisor set this up, and how do we know that the correct image was booted? SEV has support for a "Launch attestation", a CPU generated signed statement that it booted the current VM with SEV enabled. But it goes further than that! The attestation includes a measurement of what was booted, which means we don't need to trust the hypervisor at all - the CPU itself will tell us what image we were given. Perfect.
Except, well. There's a few problems. AWS just doesn't have any VMs that implement SEV yet (there are bare metal instances that do, but obviously you're building your own infrastructure to make that work). Google only seem to provide the launch measurement via the logging service - and they only include the parsed out data, not the original measurement. So, we still have to trust (a subset of) the control plane. Azure provides it via a separate attestation service, but again it doesn't seem to provide the raw attestation and so you're still trusting the attestation service. For the newest generation of SEV, SEV-SNP, this is less of a big deal because the guest can provide its own attestation. But Google doesn't offer SEV-SNP hardware yet, and the driver you need for this only shipped in Linux 5.19 and Azure's SEV Ubuntu images only offer up to 5.15 at the moment, so making use of that means you're putting your own image together at the moment.
And there's one other kind of major problem. A normal VM image provides a bootloader and a kernel and a filesystem. That bootloader needs to run on something. That "something" is typically hypervisor-provided "firmware" - for instance, OVMF. This probably has some level of cloud vendor patching, and they probably don't ship the source for it. You're just having to trust that the firmware is trustworthy, and we're talking about trying to avoid placing trust in the cloud provider. Azure has a private beta allowing users to upload images that include their own firmware, meaning that all the code you trust (outside the CPU itself) can be provided by the user, and once that's GA it ought to be possible to boot Azure VMs without having to trust any Microsoft-provided code.
Well, mostly. As AMD admit, SEV isn't guaranteed to be resistant to certain microarchitectural attacks. This is still much more restrictive than the status quo where the hypervisor could just read arbitrary content out of the VM whenever it wanted to, but it's still not ideal. Which, to be fair, is where we are with CPUs in general.
(Thanks to Leonard Cohnen who gave me a bunch of excellent pointers on this stuff while I was digging through it yesterday)
Ever since the demise of Google Reader I have been looking for a suitable replacement RSS reader. In the past I used to use Liferea but that was when I used a single desktop machine; these days I want to be able to read on my phone and multiple machines. I moved to Feedly and it s been mostly ok, but I m hitting the limit of feeds available in the free tier, and $72/year is a bit more than I can justify to myself. Especially when I have machines already available to me where I could self host something.
The problem, of course, is what to host. It seems the best options are all written in PHP, so I had to get over my adverse knee-jerk reaction to that. I ended up on FreshRSS but if it hadn t worked out I d have tried TinyTinyRSS. Of course I m hosting on Debian, and the machine I chose to use was already running nginx and PostgreSQL. So I needed to install PHP:
I put my FreshRSS install in /srv/freshrss so I grabbed the 1.20.2 release from GitHub (actually 1.20.1 at the time, but I ve upgraded to the latest since) and untared it in there. I gave www-data access to the data directory (sudo chown -R www-data /srv/freshrss/data) (yes, yes, I could have created a new user specifically for FreshRSS, but I ve chosen not to for now). There s no actual need to configure things up on the filesystem, you can do the initial setup from the web interface. Which is where the trouble came. I ve been an Apache user since 1998 and as a result it s what I know and what I go to. nginx is new to me. And I wanted my FreshRSS instance to live in a subdirectory of an existing TLS-enabled host, rather than have it s own hostname. Now, at least FreshRSS copes with this (unlike far too many other projects), you just have to configure your webserver correctly. Which took me more experimentation than I d like, but I ve ended up with the following snippet:
Other than the addition of the freshrss prefix this ends up differing slightly from the FreshRSS webserver configuration example. I ended up having to make the path info on the fastcgi_split_path_info optional, and my try_files in the bare directory location directive needed $is_args$args added or I just ended up in a redirect loop because the session parameters didn t get passed through. I m sure there s a better way to do it, but I did a bunch of searching and this is how I ended up making it work.
Before firing up the web configuration I created a suitable database:
$ sudo -Hu postgres psql
psql (13.8 (Debian 13.8-0+deb11u1))
Type "help" for help.
postgres=# create database freshrss;
CREATE DATABASE
postgres=# create user freshrss with encrypted password 'hunter2';
CREATE ROLE
postgres=# grant all privileges on database freshrss to freshrss;
GRANT
postgres=# \q
I ran through the local configuration, creating myself a user and adding some feeds, then created a cronjob to fetch updates hourly and keep a log:
Experiences so far? Reasonably happy. The interface seems snappy enough, and works well both on mobile and desktop. I m only running a single user instance at present, but am considering opening it up to some other folk and will see how that scales. And it clearly indicated a number of my feeds that were broken, so I ve cleaned some up that are still around and deleted the missing ones. Now I just need to figure out what else I should be subscribed to that I ve been putting off due to the Feedly limit!
I've been ridiculously burned out for a while now but I'm taking the month off to recover and that's giving me an opportunity to catch up on a lot of stuff. This has included me actually writing some code to work with the Pluton in my Thinkpad Z13. I've learned some more stuff in the process, but based on everything I know I'd still say that in its current form Pluton isn't a threat to free software.
So, first up: by default on the Z13, Pluton is disabled. It's not obviously exposed to the OS at all, which also means there's no obvious mechanism for Microsoft to push out a firmware update to it via Windows Update. The Windows drivers that bind to Pluton don't load in this configuration. It's theoretically possible that there's some hidden mechanism to re-enable it at runtime, but that code doesn't seem to be in Windows at the moment. I'm reasonably confident that "Disabled" is pretty genuinely disabled.
Second, when enabled, Pluton exposes two separate devices. The first of these has an MSFT0101 identifier in ACPI, which is the ID used for a TPM 2 device. The Pluton TPM implementation doesn't work out of the box with existing TPM 2 drivers, though, because it uses a custom start method. TPM 2 devices commonly use something called a "Command Response Buffer" architecture, where a command is written into a buffer, the TPM is told to do a thing, and the response to the command ends up in another buffer. The mechanism to tell the TPM to do a thing varies, and an ACPI table exposed to the OS defines which of those various things should be used for a given TPM. Pluton systems have a mechanism that isn't defined in the existing version of the spec (1.3 rev 8 at the time of writing), so I had to spend a while staring hard at the Windows drivers to figure out how to implement it. The good news is that I now have a patch that successfully gets the existing Linux TPM driver code work correctly with the Pluton implementation.
The second device has an MSFT0200 identifier, and is entirely not a TPM. The Windows driver appears to be a relatively thin layer that simply takes commands from userland and passes them on to the chip - I haven't found any userland applications that make use of this, so it's tough to figure out what functionality is actually available. But what does seem pretty clear from the code I've looked at is that it's a component that only responds when it's asked - if the OS never sends it any commands, it's not able to do anything.
One key point from this recently published Microsoft doc is that the whole "Microsoft can update Pluton firmware" thing does just seem to be the ability for the OS to push new code to the chip at runtime. That means Microsoft can't arbitrarily push new firmware to the chip - the OS needs to be involved. This is unsurprising, but it's nice to see some stronger confirmation of that.
Anyway. tl;dr - Pluton can (now) be used as a regular TPM. Pluton also exposes some additional functionality which is not yet clear, but there's no obvious mechanism for it to compromise user privacy or restrict what users can run on a Free operating system. The Pluton firmware update mechanism appears to be OS mediated, so users who control their OS can simply choose not to opt in to that.
I had bought a Thinkpad E470 laptop back in 2018 which was lying unused for
quite some time. Recently when I wanted to use it, I found that the keyboard is
not working, especially some keys and after some time the laptop will hang in
Lenovo boot screen. I came back to Bangalore almost after 2 years from my
hometown (WFH due to Covid) and thought it was the right time to get my laptop
back to normal working state. After getting the keyboard replaced I noticed that
1TB HDD is no longer fast enough for my taste!. I've to admit I never thought I
would start disliking HDD so quickly thanks to modern SSD based work laptops. So
as a second upgrade I got the HDD removed from my laptop and got a 240G SSD.
Yeah I know its reduction from my original size but I intend to continue using
my old HDD via USB SATA enclosure as an external HDD which can house the extra
data which I need to save.
So now that I've a SSD I need to install Debian Unstable again on it and this is
where I tried something new. My colleague (name redacted on request) suggested
to me use GRML live CD and install Debian via debootstrap. And after giving a
thought I decided to try this out. Some reason for going ahead with this are
listed below
Debian Installer does not support a proper BTRFS based root file system. It
just allows btrfs as root but no subvolume support. Also I'm not sure about
the luks support with btrfs as root.
I also wanted to give a try to systemd-boot as my laptop is UEFI capable and
I've slowly started disliking Grub.
I really hate installing task-kde-desktop (Yeah you read it right, I've switched
to be a KDE user for quite some time) which will pull tons of unwanted stuff
and bloat. Well it's not just task-kde-desktop but any other task-desktop
package does similar and I don't want to have too much of unused stuff and
services running.
Disk Preparation
As a first step I went to GRML website and downloaded current pre-release. Frankly, I'm using GRML for first
time and I was not sure what to expect. When I booted it up I was bit taken a
back to see its console based and I did not have a wired lan just a plain
wireless dongle (Jiofi device) and was wondering what it will take to connect.
But surprisingly curses based UI was pretty much straight forward to allow me to
connect to Wifi AP. Another thing was the rescue CD had non-free firmware as the
laptop was using ath10k device and needed non-free blobs to operate.
Once I got shell prompt in rescue CD first thing I did was to reconfigure
console-setup to increase font size which was very very small on default boot.
Once that is done I did the following to create a 1G (FAT32) partition for EFI.
parted -a optimal -s /dev/sda mklabel gpt
parted -a optimal -s /dev/sda mkpart primary vfat 0% 1G
parted -a optimal -s /dev/sda set1 esp on
mkfs.vfat -n boot_disk -F 32 /dev/sda1
So here is what I did: created a 1G vfat type partition and set the esp flag on
it. This will be mounted to /boot/efi for systemd-boot. Next I created a single
partition on the rest of the available free disk which will be used as the root
file system.
Next I encrypted the root parition using LUKS and then created the BTRFS file
system on top of it.
Next is to create subvolumes in BTRFS. I followed suggestion by colleague and
created a top-level @ as subvolume below which created @/home@/var/log@/opt .
Also enabled compression with zstd and level of 1 to avoid battery drain.
Finally marked the @ as default subvolume to avoid adding it to fstab entry.
mount -o compress=zstd:1 /dev/mapper/ENC /mnt
btrfs subvol create /mnt/@
cd /mnt/@
btrfs subvol create ./home
btrfs subvol create ./opt
mkdir -p var
btrfs subvol create ./var/log
btrfs suvol set-default /mnt/@
Bootstrapping Debian
Now that root disk is prepared next step was to bootstrap the root file system.
I used debootstrap for this job. One thing I missed here from installer was
ability to preseed. I tried looking around to figure out if we can preseed
debootstrap but did not find much. If you know the procedure do point it to me.
cd /mnt/
debootstrap --include=dbus,locales,tzdata unstable @/ http://deb.debian.org/debian
Well this just gets a bare minimal installation of Debian I need to install rest
of the things post this step manually by chroot into target folder @/.
I like the grml-chroot command for chroot purpose, it does most of the job of
mounting all required directory like /dev/ /proc /sys etc. But before entering
chroot I need to mount the ESP partition we created to /boot/efi so that I
can finalize the installation of kernel and systemd-boot.
umount /mnt
mount -o compress=zstd:1 /dev/mapper/ENC /mnt
mkdir -p /mnt/boot/efi
mount /dev/sda1 /mnt/boot/efi
grml-chroot /mnt /bin/bash
I remounted the root subvolume @ directly to /mnt now, remember I made @ as
default subvolume before. I also mounted ESP partition with FAT32 file system to
/boot/efi. Finally I used grml-chroot to get into chroot of newly bootstrapped
file system.
Now I will install the kernel and minimal KDE desktop installation and configure
locales and time zone data for the new system. I wanted to use dracut instead of
default initramfs-tools for initrd. I also need to install cryptsetup and
btrfs-progs so I can decrypt and really boot into my new system.
I've not written actual UUID above this is just for the purpose of showing the
content of /etc/crypttab. Once these entries are added we need to recreate
initrd. I just reconfigured the installed kernel package for retriggerring the
recreation of initrd using dracut.
..
Reconfiguration was locales is done by editing /etc/locales.gen to uncomment
en_US.UTF-8 and writing /etc/timezone with Asia/Kolkata. I used
DEBIAN_FRONTEND=noninteractive to avoid another prompt asking for locale and
timezone information.
Added my user using adduser command and also set the root password as well.
Added my user to sudo group so I can use sudo to elevate privileges.
Setting up systemd-boot
So now basic usable system is ready last part is enabling the systemd-boot
configuration as I'm not gonna use grub. I did following to install
systemd-boot. Frankly I'm not expert of this it was colleague's suggestion.
Before installing the systemd-boot I had to setup kernel command line. This can
be done by writing command line to /etc/kernel/cmdline with following contents.
systemd.gpt_auto=no quiet root=LABEL=root_disk
I'm disabling systemd-gpt-generator to avoid race condition between crypttab
entry and auto generated entry by systemd. I faced this mainly because of my
stupidity of not adding entry root=LABEL=root_disk
Finally exit from the chroot and reboot into the freshly installed system.
systemd-boot already ships a hook file zz-systemd-boot under /etc/kernel
so its pretty much usable without any manual intervention. Previously after
kernel installation we had to manually update kernel image in efi partitions
using bootctl
Conclussion
Though installing from live image is not new and debian-installer also does the
same only difference is more control over installation and doing things which is
installer is not letting you do (or should I say is not part of default
installation?). If properly automated using scripts we can leverage this to do
custom installation in large scale environments. I know there is FAI but I've
not explored it and felt there is too much to setup for a simple installations
with specific requirements.
So finally I've a system with Debian which differs from default Debian
installation :-). I should thank my colleague for rekindling nerd inside me who
had stopped experimenting quite a long time back.
The Unbroken is the first book of a projected fantasy trilogy. It
is C.L. Clark's first novel.
Lieutenant Touraine is one of the Sands, the derogatory name for the
Balladairan Colonial Brigade. She, like the others of her squad, are
conscript soldiers, kidnapped by the Balladairan Empire from their
colonies as children and beaten into "civilized" behavior by Balladairan
training. They fought in the Balladairan war against the Taargens. Now,
they've been reassigned to El-Wast, capital city of Qaz l, the foremost of
the southern colonies. The place where Touraine was born, from which she
was taken at the age of five.
Balladaire is not France and Qaz l is not Algeria, but the parallels are
obvious and strongly implied by the map and the climates.
Touraine and her squad are part of the forces accompanying Princess Luca,
the crown princess of the Balladairan Empire, who has been sent to take
charge of Qaz l and quell a rebellion. Luca's parents died in the
Withering, the latest round of a recurrent plague that haunts Balladaire.
She is the rightful heir, but her uncle rules as regent and is reluctant
to give her the throne. Qaz l is where she is to prove herself. If she
can bring the colony in line, she can prove that she's ready to rule: her
birthright and her destiny.
The Qaz li are uninterested in being part of Luca's grand plan of personal
accomplishment. She steps off her ship into an assassination attempt,
foiled by Touraine's sharp eyes and quick reactions, which brings the Sand
to the princess's attention. Touraine's reward is to be assigned the
execution of the captured rebels, one of whom recognizes her and names her
mother before he dies. This sets up the core of the plot: Qaz li
rebellion against an oppressive colonial empire, Luca's attempt to use the
colony as a political stepping stone, and Touraine caught in between.
One of the reasons why I am happy to see increased diversity in SFF
authors is that the way we tell stories is shaped by our cultural
upbringing. I was taught to tell stories about colonialism and rebellion
in a specific ideological shape. It's hard to describe briefly, but the
core idea is that being under the rule of someone else is unnatural as
well as being an injustice. It's a deviation from the way the world
should work, something unexpected that is inherently unstable. Once
people unite to overthrow their oppressors, eventual success is
inevitable; it's not only right or moral, it's the natural path of
history. This is what you get when you try to peel the supremacy part
away from white supremacy but leave the unshakable self-confidence and
bedrock assumption that the universe cares what we think.
We were also taught that rebellion is primarily ideological. One may be
motivated by personal injustice, but the correct use of that injustice is
to subsume it into concepts such as freedom and democracy. Those concepts
are more "real" in some foundational sense, more central to the right
functioning of the world, than individual circumstance. When the
now-dominant group tells stories of long-ago revolution, there is no
personal experience of oppression and survival in which to ground the
story; instead, it's linked to anticipatory fear in the reader, to the
idea that one's privileges could be taken away by a foreign oppressor and
that the counter to this threat is ideological unity.
Obviously, not every white fantasy author uses this story shape, but the
tendency runs deep because we're taught it young. You can see it
everywhere in fantasy, from Lord of the Rings to
Tigana. The Unbroken uses a much
different story shape, and I don't think it's a coincidence that the
author is Black.
Touraine is not sympathetic to the Qaz li. These are not her people and
this is not her life. She went through hell in Balladairan schools, but
she won a place, however tenuous. Her personal role model is General
Cantic, the Balladairan Blood General who was also one of her instructors.
Cantic is hard as nails, unforgiving, unbending, and probably a war
criminal, but also the embodiment of a military ethic. She is tough but
fair with the conscript soldiers. She doesn't put a stop to their
harassment by the regular Balladairan troops, but neither does she let it
go too far. Cantic has power, she knows how to keep it, and there is a
place for Touraine in Cantic's world.
And, critically, that place is not just hers: it's one she shares with her
squad. Touraine's primary loyalty is not to Balladaire or to Qaz l. It's
to the Sands. Her soldiers are neither one thing nor the other, and they
disagree vehemently among themselves about what Qaz l and their other
colonial homes should be to them, but they learned together, fought
together, and died together. That theme is woven throughout The
Unbroken: personal bonds, third and fourth loyalties, and practical
ethics of survival that complicate and contradict simple dichotomies of
oppressor and oppressed.
Touraine is repeatedly offered ideological motives that the protagonist in
the typical story shape would adopt. And she repeatedly rejects them for
personal bonds: trying to keep her people safe, in a world that is not
looking out for them.
The consequence is that this book tears Touraine apart. She tries to walk
a precarious path between Luca, the Qaz li, Cantic, and the Sands, and she
falls off that path a lot. Each time I thought I knew where this book was
going, there's another reversal, often brutal. I tend to be a
happily-ever-after reader who wants the protagonist to get everything they
need, so this isn't my normal fare. The amount of hell that Touraine goes
through made for difficult reading, worse because much of it is due to her
own mistakes or betrayals. But Clark makes those decisions believable
given the impossible position Touraine is in and the lack of role models
she has for making other choices. She's set up to fail, and the price of
small victories is to have no one understand the decisions that she makes,
or to believe her motives.
Luca is the other viewpoint character of the book (and yes, this is also a
love affair, which complicates both of their loyalties). She is the
heroine of a more typical genre fantasy novel: the outsider princess with
a physical disability and a razor-sharp mind, ambitious but fair (at least
in her own mind), with a trusted bodyguard advisor who also knew her
father and a sincere desire to be kinder and more even-handed in her
governance of the colony. All of this is real; Luca is a protagonist, and
the reader is not being set up to dislike her. But compared to Touraine's
grappling with identity, loyalty, and ethics, Luca is never in any real
danger, and her concerns start to feel too calculated and superficial.
It's hard to be seriously invested in whether Luca proves herself or gets
her throne when people are being slaughtered and abused.
This, I think, is the best part of this book. Clark tells a traditional
ideological fantasy of learning to be a good ruler, but she puts it
alongside a much deeper and more complex story of multi-faceted
oppression. She has the two protagonists fall in love with each other and
challenges them to understand each other, and Luca does not come off well
in this comparison. Touraine is frustrated, impulsive, physical, and
sometimes has catastrophically poor judgment. Luca is analytical and
calculating, and in most ways understands the political dynamics far
better than Touraine. We know how this story usually goes: Luca sees
Touraine's brilliance and lifts her out of the ranks into a role of
importance and influence, which Touraine should reward with loyalty. But
Touraine's world is more real, more grounded, and more authentic, and both
Touraine and the reader know what Luca could offer is contingent and comes
with a higher price than Luca understands.
(Incidentally, the cover of The Unbroken, designed by Lauren
Panepinto with art by Tommy Arnold, is astonishingly good at capturing
both Touraine's character and the overall feeling of the book. Here's a
larger version.)
The writing is good but uneven. Clark loves reversals, and they did keep
me reading, but I think there were too many of them. By the end of the
book, the escalation of betrayals and setbacks was more exhausting than
exciting, and I'd stopped trusting anything good would last. (Admittedly,
this is an accurate reflection of how Touraine felt.) Touraine's inner
monologue also gets a bit repetitive when she's thrashing in the jaws of
an emotional trap. I think some of this is first-novel problems of
over-explaining emotional states and character reasoning, but these
problems combine to make the book feel a bit over-long.
I'm also not in love with the ending. It's perhaps the one place in the
book where I am more cynical about the politics than Clark is, although
she does lay the groundwork for it.
But this book is also full of places small and large where it goes a
different direction than most fantasy and is better for it. I think my
favorite small moment is Touraine's quiet refusal to defend herself
against certain insinuations. This is such a beautiful bit of
characterization; she knows she won't be believed anyway, and refuses to
demean herself by trying.
I'm not sure I can recommend this book unconditionally, since I think you
have to be in the mood for it, but it's one of the most thoughtful and
nuanced looks at colonialism and rebellion I can remember seeing in
fantasy. I found it frustrating in places, but I'm also still thinking
about it. If you're looking for a political fantasy with teeth, you could
do a lot worse, although expect to come out the other side a bit battered
and bruised.
Followed by The Faithless, and I have no idea where Clark is going
to go with the second book. I suppose I'll have to read and find out.
Content note: In addition to a lot of violence, gore, and death, including
significant character death, there's also a major plague. If you're not
feeling up to reading about panic caused by contageous illness, proceed
with caution.
Rating: 7 out of 10