I stumbed across a program called Shiori. It’s a single-binary Go program which you can use as a self-hosted “Ersatz” for Pocket.

Shiori main

I can add articles via the Web interface, but I can also use the CLI for that. Searching and exporting is also possible.

When I click on an article, I’m shown the copy shiori downloaded when the URL was added.

Reading an article

One thing I didn’t like is that a ./shiori add URL assumes the background of my terminal is dark and it uses very light colors to show me what actually happened, but I can also add bookmarks via shiori’s Web interface.

$ TERM=dumb ./shiori add https://en.wikipedia.org/wiki/MQTT
11. MQTT - Wikipedia (10-14 minutes)
    > https://en.wikipedia.org/wiki/MQTT
    + MQTT[2] (Message Queuing Telemetry Transport) is an ISO standard (ISO/IEC
PRF 20922)[3] publish-subscribe-based messaging protocol. It works on top of
the TCP/IP protocol. It is designed for connections with remote locations where
a "small code footprint" is required or the network bandwidth is limited. The
publish-subscribe messaging pattern requires a message broker.

$ TERM=dumb ./shiori search goo
12. Google
    > http://google.com
    + Komponiere deine eigenen von Bach inspirierten Melodien – mit dem ersten
Google Doodle mit k�nstlicher Intelligenz. #GoogleDoodle! 🎼 #BachDoodle 

Documentation is sufficient, and CLI operation seems complete.

My favorite feature is, I think, shiori export bookmarks.html which produces a HTML file in Netscape Bookmark format. :-)

applications :: 22 Mar 2019 :: e-mail

Today’s Web is full of magical sites with clever user interfaces in which developers invent all manner of “useful” features such as not being able to paste passwords. A lot of sites are beautiful, really, with heavy graphics, lovely colors, and a baseline of several dozen (or is it hundred?) megabytes I load onto a tiny screen over a wobbly connection when mobile. And lest I forget, let me rave about the incredibly “useful” cookie pop-ups, GDPR warnings, and whathave-you-disclaimers which guarantee a really “wonderful” browsing experience. </rant>

It’s not all bad, obviously, and there are very many well-designed and lightweight sites, but there was a time when “surfing” looked like this:

screenshot of my Gopher site

Are you old enough to remember Gopher? It was lean, it contained mostly plain text, and it was fast. It wasn’t colorful at all, unless you got Lynx to do color or used NCSA Mosaic which was quite slow because computers then were slow.

Install a copy of lynx if you don’t yet have it, and give it a try; most modern Web browsers don’t have support for Gopher, although there is the odd FireFox, I think, plugin which might work for you.

lynx gopher://serf.jpmens.net

Interestingly, Gopher is still a bit alive: popular sites such as HackerNews have a Gopher site; you’ll find a link to it and others above. Even the hugely popular Redis key-value store by Salvatore Sanfilippo (antirez) has now had Gopher support added to it and comes with a special authoring tool.

See also:

Tell me about your Gopher site, and I’ll add it to my directory.

protocols :: 03 Mar 2019 :: e-mail

In 2012 I wrote a short piece on retrieving SSH public keys from a DNS-based FUSE pseudo file system, and I’ve been meaning to address that since about a year later, because SSH then got a configurable program to provide public keys for users. Peter reminded me to mention this, hence this post.

The program specified as AuthorizedKeysCommand in the SSH server configuration must belong to root and it should produce zero or more lines of authorized_keys output on standard output; think “cat ~/.ssh/authorized_keys”.

So I can use the AuthorizedKeysCommand to obtain a user’s public keys from almost any source, such as an LDAP directory, some special database, from a particular directory just like AuthorizedKeysFile, or by almost any other means.

The server configuration (sshd.conf) will contain:

AuthorizedKeysCommand /etc/skeys/keylist %u
AuthorizedKeysCommandUser uucp

We can test whether that works by using a trivial prototype shell script (which will probably remain in production until the cows come home …) as the appropriate command.


[ $# -ne 1 ] && { echo "Usage: $0 userid" >&2; exit 1; }

case "$1" in 
	# this is just a joke; don't take this seriously, and if you
	# do, make sure you have some sort of cache in case your
	# internet goes kaputt
        curl -sf https://api.github.com/users/jjolie/keys |
	jq -r '.[].key'
        [ -f $keyfile ] && cat $keyfile

I install this program in its own directory, and ensure the files belong to root and are neither writeable by group or others. I’ll bump sshd’s logging up to DEBUG and if I try and login as user jjolie, I see:

sshd[21454]: debug1: temporarily_use_uid: 10/10 (e=0/0)
sshd[21454]: debug1: matching key found: file /etc/skeys/keylist %u, line 1 ECDSA SHA256:+fb1q4teO3....0Pio
sshd[21454]: debug1: restore_uid: 0/0
sshd[21454]: debug1: do_pam_account: called
sshd[21454]: Accepted publickey for jjolie from port 60346 ssh2: ECDSA SHA256:+fb1q4teO3....0Pio
sshd[21454]: debug1: monitor_child_preauth: jjolie has been authenticated by privileged process

When user jjolie logs in, our program gets her public keys via the Github API, and otherwise we see if we have a .pub file for the user in /var/lib/keys/.

Using, say, an LDAP or other directory, we can ensure users’ keys are centrally managed, and in particular, it will be easier, when a user leaves, to ensure she’s no longer permitted to login to our servers.

See also:

ssh :: 02 Mar 2019 :: e-mail

Now that half the world knows, I might as well tell you that I used balenaEtcher to flash an image onto a USB memory key.


I launched the app on a Mac on which I still have Little Snitch installed, a program which alerts me of outgoing connections attempted by programs on my Mac. I can then, on a per/program and per/connection basis, decide whether I wish to allow that connection and, if so, for just once or forever.

This is the list of connections initiated I was requested to approve from the already installed app:

etcher.io on TCP port 80 (http)
balena.io on TCP port 80 (http)
s3-1-w.amazonaws.com on TCP port 443 (https)
fullstory.com on TCP port 443 (https)
d1l6p2sc9645hc.cloudfront.net on TCP port 443 (https)
a.impactradius-go.com on TCP port 443 (https)
www.google.com on TCP port 443 (http
accounts-cctld.l.google.com on TCP port 443 (https)
cse.google.com on TCP port 443 (https)
rs.fullstory.com on TCP port 443 (https)
api.mixpanel.com on TCP port 443 (https)
sentry.io on TCP port 443 (https)
stats.l.doubleclick.net on TCP port 443 (https)
data2.gosquared.com on TCP port 443 (https)
data.gosquared.com on TCP port 443 (https)
assets.balena.io on TCP port 443 (https)
code.jquery.com on TCP port 443 (https)

That was the list of connections I was requested to approve. To copy an image onto a USB memeory key. I don’t even.

Update: prompted by Tony, I checked; it appears to be an Electron app.

$ strings balenaEtcher
privacy :: 23 Feb 2019 :: e-mail

I was asked to moderate a discussion about all aspects of DNS privacy at FOSDEM, and I gladly went for that. I’d not been at FOSDEM yet, but I had read about its size, and it really is huge.

Seconds after arriving at FOSDEM’s ‘K’ building on the Sunday morning, Fabian intercepted me and treated me to a much-needed cup of coffee after the four-hour drive. My primary target at the conference was the DNS Devroom to which I got at around 10:30, only to find the dreaded “FULL” sign posted on the door, but I had a “VIP” ticket, and Peter let me in.

Moderating the DNS Privacy panel was huge fun. I got to see Stéphane and Bert (and Peter and Pieter and others) again, and I had the honour of meeting Daniel Stenberg. The (slightly truncated) video of the half-hour panel clearly shows what we talked about, and if you watch it I think you’ll recognize that I really did enjoy moderating it.

I didn’t get to see very many talks at FOSDEM, but I did chat to lots of people: Nicole and Lars, Howard and Michael, Fabian, whom I’ve already mentioned, Toshaan, Pieter, Pieter, and Peter, and several others. I spent lunch and the better part of the afternoon with Christoph and later drove him to the station, and from there I drove the short hop to Ghent.

Config Management Camp was a first for me as well, and I went because I’ve been postponing it for years, and I promised to go this year. Toshaan and Kris do a marvelous job in organizing it.

Cfgmgmtcamp (that’s how it’s spelled – I think vowels are expensive in Belgium) is a tenth of FOSDEM’s size, and much easier for me to handle. The conference is also free of charge, and the organizers serve lovely complimentary pains au chocolat and croissants for breakfast (coffee was very american and took ages to brew). The talks I saw were good, and the speakers well versed.

I spent one day only at FOSDEM, and that’s ok; I don’t imagine I would go again unless I were already in the vicinity; it’s just too large and too full for me. Selecting what talk to see at which time is a full-time job, and the probability of the room being ‘FULL’ is very high. (Somebody told me she came an hour early to the DNS devroom so as to have a chance of getting in.)

I will try to go back to Config Management Camp though: it’s a good size but if it gets any larger it too will be hard to handle. For me.

conferences :: 09 Feb 2019 :: e-mail

Other recent entries