RSSAmplifier

Blog

/dev/schnouki

Recent content on /dev/schnouki

schnouki.netRSS feed ↗73 posts

Latest posts

Using a Blue Yeti microphone on Linux with Pipewire in 2025

TL;DR: there’s nothing to do, it just works out of the box. As I work for an amazing fully remote company , I attend a few remote meetings every week, using Google Meet. So, having a good audio and video setup is pretty important, as it helps a lot with communications. Until recently, my setup was basically “a nice webcam and a cheap headset”. After a coworker pointed out that my…

Tip: F13-F24 keys with ZSA keyboards on Linux

I recently took the plunge and got myself a ZSA Voyager , a beautiful split ergonomic keyboard. So far I’m really happy with it – even though my fingers are still getting used to the split layout 😅 One of its coolest features is the incredibly smooth configuration and customization experience using Oryx , ZSA’s configuration tool. Unlike VIA, which requires Chromium-based…

Manually removing tabs from the Firefox session manager

So… something weird happened. I clicked a link, and it crashed Firefox. And my whole Sway session. Back to my TUI login manager… Login again, open Firefox: same crash, back to the login manager again. Now this is getting annoying. One easy way to fix that would be to remove the session manager data from my Firefox profile. But I don’t want to lose my other 114 tabs just because of that one!…

Using content negotiation to serve WebP images in Caddy 2

A while ago, I upgraded Caddy on my VPS from Caddy 1 to Caddy 2 . One thing that broke during that time (and that I embarrassingly didn’t notice until today) is the content negotiation for images. The idea of content negotiation is simple. Imagine you have a regular JPEG or PNG image on your website. If you also have a WebP version of that same image, and if the visitor’s browser can…

Advent of Code 2020, day 10

Today is day 10 already! And it’s a pretty interesting one. We’re dealing with sequences of numbers, and differences between those numbers. Each number needs to have a difference of 1, 2, or 3 with the previous one. Parsing this list of numbers is trivial. For this problem, it helps to add 0 to that list (as it’s always the initial number to consider). And since we must consider…

Advent of Code 2020, days 7, 8 and 9

I’m a bit late, so here are days 7 to 9. As now usual, all my solutions are available on https://git.sr.ht/~schnouki/advent-of-code . Day 7: Handy Haversacks Bags inside bags inside bags… Do we have recursive bags now? 😯 Anyway. The first step is to parse those descriptions into something more usable. I’ve decided to do it without regexps, and storing data in simple dicts: def…

Advent of Code 2020, days 5 and 6

This weekend was days 5 and 6. As always, all my solutions are available on https://git.sr.ht/~schnouki/advent-of-code . Day 5: binary boarding Today we are dealing with boarding passes, and parsing strings into seat numbers. The description is pretty straightfoward: for each part of the boarding pass we have a lower and upper bound, and each new characters divides the search space in 2. Classic…

Advent of Code 2020, day 4

It’s day 4 … As before, all my solutions are available on https://git.sr.ht/~schnouki/advent-of-code . Today we’re dealing with passport validation. Spoiler alert: as often with data validation issues, it’s pretty boring… Okay, let’s parse those passports. Split input when there are 2 newlines, split each block on whitespace, parse key:value entries. Boring!…

Advent of Code 2020, day 3

It’s day 3 already! As before, all my solutions are available on https://git.sr.ht/~schnouki/advent-of-code . Today we’ll talk about toboggan trajectories! 1 In typical AoC fashion, our input is a map in ASCII art. What’s important to us is its size and the position of the trees… So we’ll parse this input and store just that: the width and height of the map, and the…

Advent of Code 2020, day 2

Let’s go for Day 2! As before, all my solutions are available in a Git repository: https://git.sr.ht/~schnouki/advent-of-code . Today’s puzzle is about password policies. Our input is made of line with a simple structure: we can parse them with a simple regular expression, and store the result in a dataclass . (We could also use a namedtuple or even a tuple, but using a class we can…

Advent of Code 2020, day 1

It’s that time of the year again: the Advent of Code 2020 has started! For those who don’t know, Advent of Code is an Advent calendar of programming puzzles. Simple at first, not-so-simple after one week or two usually. This year I’ve decided to try to write a small recap every day. Or, well, whenever I solve those puzzles, which may be a few days late, or even way later if…

New theme, new content

I was getting tired of Minimo , the theme used on this blog. So I created a new one from scratch. I like it a lot, but I’m obviously biased 😉 Some things I used: Marx , a classless CSS reset. Nice and minimal. SCSS, rendered with Hugo Pipes . Only readable source code in the Git repository! Iosevka fonts: Iosevka Sparkle for normal text (duospace, like iA Writer Duo ), and the normal…

Hackers: Heroes of the Computer Revolution

In this book, Steven Levy tells the history of modern computing. From the first MIT hackers who started working on model railroads before discovering early TX-0 and PDP-1 mainframes to video game creators working at Sierra; from Peter Samson, John “Captain Crunch” Draper, and Woz, to Richard Stallmann Steve Jobs and Bill Gates… decades the history of early computers and their…

Aya Nakamura vs Kaamelott

Pour se changer un peu les idées en cette période de confinement… C’est très con mais ça me fait rire !

Comment je suis devenue anarchiste

Isabelle Attard, ex-députée au parcours atypique, retrace dans ce livre les grandes lignes de son parcours politique. Elle raconte comment son expérience à l’Assemblée Nationale a changé son regard sur le pouvoir tel qu’il est exercé dans nos « démocraties » : de nombreuses désillusions qui l’ont conduite à une déconstruction puis reconstruction, au cours de laquelle elle…

How to run a Win10 dev VM on VirtualBox 5

I have a NAS (HP ProLiant Gen10 microserver) running OpenMediaVault 4 with the VirtualBox “plugin” . Meaning it runs VirtualBox 5.2, while the latest version is 6.1. Recently I needed to run something on a Windows machine. So I quickly grabbed a Win10 dev VM , imported the OVA appliance in the VirtualBox web UI, and… it failed. Hard. Error in (line 120) — Invalid value…

Fées, weed et guillotines

Une jeune femme déboule en trombe chez un détective privé et lui demande de retrouver une fille, avec pour seul indice des tableaux de son sourire. Étrange, mais faisable. Sauf que cette jeune femme semble venue d’une autre époque, avoir un certain mépris pour les humains, craindre le fer, et ne pas vraiment s’intéresser aux troubles causés par ses règlements de compte… Un bon…

Happy new year 2020!

Happy new year! 🎉 This year I’ll try to make this blog a bit more active again. But as I’m not sure I’ll manage to write many interesting articles, I’ll try to add some other content instead. Starting with reviews of the books I read along the year. It will be either in French or in English, and there’s no guarantee it will be of any interest to anyone 😅

How to use a Keychron K2/K4 USB keyboard on Linux

I recently bought a Keychron K2 mechanical keyboard and it’s been great so far. Most things work out of the box on my Linux laptop with a few notable exceptions: function keys! no insert key! The issue with function keys: when set to Windows mode, the special keys (“volume up”, “brightness control”, etc.) send Windows-specific key combinations instead of standard…

Introducing watch_tabnine

I’m a big fan of TabNine , a super nice code editor-agnostic code completion tool. I use it from Emacs using company-tabnine and it’s amazing how well it works (especially since I joined the beta for the new cloud-based service that uses deep learning techniques to provide better completion candidates). However there’s one annoying thing with TabNine. From time to time it starts…

Python, debugging, print, and context managers

I’ve been recently working on some big changes to a big module in a big Python application. For this precise module, there are 1019 unit tests, most of them auto-generated from a few (big) data files. The tests are run using pytest , and usually take about 7 seconds to run on my laptop. My changes caused a single test to fail. One out of 1019. Yay? Well, time to debug that: let’s add…

Automatically archive the modules of the currently running kernel on upgrade on Arch Linux

I don’t reboot my laptop very often. My current uptime is 11 days; that’s quite low, I’m pretty sure the previous one was at least a month. Yet I often upgrade my system with pacman -Syu (or more precisely yay -Syu ). As a consequence, I’m often running a kernel that is older that the one that is currently installed: ~ % uname -sr Linux 4.20.13-arch1-1-ARCH ~ % pacman -Qi…

STIBIDIK

STIBIDIK is an online marketplace that specializes in vintage fashion from the best second-hand boutiques. I’ve been working at STIBIDIK as co-founder and CTO from 2016 to late 2018.

Findspire

Findspire is a artistic content discovery platform. Its main service is a music and video streaming service, quite similar to Spotify or Deezer. I worked at Findspire as lead software engineer from 2013 to 2016.

Open Source software

I’ve contributed to Open Source / Free Software projects for more than a decade. I’ve also started a few projects; most of that is available on my GitHub page .

Buddycloud

The Buddycloud project aims to build a rich user and group messaging ecosystem that can easily be embedded in any app, and relies on an open protocol (based on XMPP ) and open-source software. I contributed to the Buddycloud project from 2012 to 2013 as a volunteer.

GetSimple CMS with Caddy

I just switched my web server from lighttpd to Caddy ! No need to write a script to update my Let’s Encrypt certificates, HTTP/2, etc.: pretty nice. But of course I needed to rewrite my configuration. Most of it was straightforward. I had to delete some nice things , but in the end even that was OK (I wasn’t even using that anymore). My biggest issue was to get a test site that uses…

Highlighting Hugo shortcodes in Emacs

I’m working on some new content for this blog that uses a lot of shortcodes . The problem is that in Emacs, markdown-mode doesn’t know about shortcodes, so it doesn’t render them properly: Fortunately, a few lines of Emacs Lisp and it works beautifully: markdown-shortcode.el (defun schnouki/markdown-maybe-add-shortcode-keyword () "Enable fontifying Hugo shortcodes if in the…

Remove the last page of a PDF if empty

A small but common issue… My CV is written with \LaTeX 1 , and in France, CVs are expected to be 1 page long (unless you have a lot of experience). This can be quite challenging. When reducing the length of my CV to 1 page, I often end with a 2-page PDF with a completely blank second page. I then use stapler to remove this empty page. But doing this every time quickly gets annoying! So I need a…

gitlab-runner on a laptop without pain

I have several (private) projects hosted on gitlab.com that use Gitlab CI . Since these are private projects, I prefer to run their CI pipelines on private runners. So I set up gitlab-runner on my Kimsufi server. It works great! Except that… Except that my Kimsufi server is really slow. So tests that run in 2 to 3 minutes on my laptop sometimes take 20 to 30 minutes to run in CI. Which is not…

Backup TOTP secrets with Emacs

I use FreeOTP to generate time-based OTP tokens on my phone. It’s similar to Google Authenticator et al , except that it’s Free Software, it works really well, and it can display images in addition to an account name, which is nice . Plus it’s really easy to use: start setting-up the 2nd factor authentication on the service you want, when it shows a QR-code scan it with the app,…

Blog evolution

Time to change again 😃 Actually there are several changes this time: blog engine: switched from Pelican to Hugo , another static blog generator, also known as the new cool kid in town . Really fast, and so far I didn’t feel I needed several plugins as I did with Pelican. comments: removed Disqus in favor of a self-hosted instance of Isso . Because privacy! analytics: removed Piwik hosted…

Islas

Pour me déplacer à Nancy j’utilise principalement les trams ou les bus du réseau Stan . Pour mes trajets domicile-travail, j’ai le choix entre une ligne de bus, trajet court mais passages pas très fréquents, ou le tram, trajet un peu plus long mais passages plus fréquents. Avant de quitter le bureau, j’ai donc envie de savoir lequel prendre… Et donc je passe soit par le site web,…

Let's Encrypt and client certificates

A few days ago I switched to Let’s Encrypt certificates for this site (instead of StartSSL). Twitter user @utopiah recently asked me about using it as a CA to sign the client certificate instead of using a self-generated, self-signed one. @Schnouki well isn't it possible and better to use @letsencrypt as CA to sign the client p12 instead of using a self generated one?

Last commit in each git branch

At work we’re usually working on many git branches at the same time, and from time to time we rebase the “work-in-progress” branches on top of master . In the end it makes it quite complicated to know when a remote branch was last modified, by whom, and whether it has been merged or not. So we have to run git branch -a and then git log on each remote branch… Too tedious…

Introvert's heart

Found this recently. I agree wholeheartedly. And of course there’s also this one, which everyone should read at least once :)

Chromecast and network namespaces

This is a follow-up to the post about OpenVPN for a single application . I’ve finally found a way to access my Chromecast from a program running inside a network namespace! And it turns out it’s pretty easy to do. With the setup I described in my last post, the isolated app has full access to the local network through the vpn1 interface. The only thing needed for the Chromecast to work…

OpenVPN for a single application on Linux

It’s sometimes useful to run a single application through a VPN for privacy reasons . There are many ways to do it, and the most common one is apparently to run the application with a different user account and use some iptables magic to configure a specific routing table for this user. In my opinion this is way too troublesome and complicated, and much less comfortable to use. Luckily…

Présentation d'ElasticSearch à l'Apéro Web Nancy

Hier soir j’ai présenté ElasticSearch lors d’un Apéro Web Nancy . Le public était nombreux et très attentif, c’était impressionnant 😃 Comme promis, je viens de mettre en ligne le contenu de cette présentation dans un dépôt git . Ce dépôt contient les slides, le jeu de données (sous formes de fichiers JSON), le script permettant d’indexer ces données dans ElasticSearch, les…

TLSA records on OVH

DANE is a great way of improving security on the web by replacing SSL certificate authorities with DNS records signed by DNSSEC. Basically, the certificate (or its fingerprint) is contained in a TLSA record, with some paremeters that specify how clients should validate it. It is also extremely simple to generate TLSA records for your domain using online tools such as…

Sigur Rós — Heysátan

It’s been way too long since the last time I posted something about Sigur Rós. Saw them in Luxembourg a few months ago and it was amazing.

Flashing a stock Android image without wiping user data

Until today my Nexus 10 was running Android 4.4.2 (stock firmware from Google). I couldn’t install the OTA update to 4.4.4 because I had installed a custom recovery ( TWRP ) in order to root the device. So today I decided to reinstall the stock recovery and install the update… But the installation failed. The tablet was able to reboot, but it showed that is was still running Android…

Basic auth / SSL client certificate: dual-method authentication in lighttpd

On my server I’m running several webapps (such as Tiny Tiny RSS , CGP , and Shaarli ). They are all running on a private, separate subdomain. As I’m the only user, this subdomain is protected at the server-level with HTTP Basic authentication, and each app is configured to allow full access without requiring any other login. This works great, is really simple, and has the advantage of…

lighttpd and SSL client certificates

I recently configured my lighttpd server to enable authentication based on SSL client certificates on a private subdomain. Here’s a quick how-to. Configure OpenSSL: $ cp /etc/ssl/openssl.cnf ./ $ $EDITOR openssl.cnf # Edit "dir" $ mkdir certs $ echo "00" > serial $ echo "00" > crlnumber $ touch index.txt Create the CA : $ openssl genrsa -out ca.key 2048 # Generate a RSA-2048 private key $…

hubiC remote for git-annex

I still love git-annex . And one of the things I like is that it can use many storage backends and track the location of any data on all of these backends. And in the latest versions, it’s quite easy to add support for new backends. Which I did for hubiC , an inexpensive 1 cloud storage service by OVH. hubiC provides a nice API , which is actually the “usual” OpenStack SWIFT API…

ZSH completion for git-annex

I love git-annex . It works extremely well, its documentation is excellent, and Joey Hess, its main developper, is amazingly reactive when you tell him about a bug or ask him any question about this software. I’m currently using git-annex to manage almost 1 TB of data, spread over my laptop, my NAS, a few external hard drives, and my hubiC account. (Yes, git-annex is also designed to be able…

DNSSEC-trigger on Arch Linux without Network Manager

Many ISPs have pretty shitty DNS resolvers. Sometimes they act as fake DNS, sometimes they are just poorly configured. And it’s even worse on hotspots with captive portals. Part of the solution is to use DNSSEC … but it’s not that easy. Of course, Unbound can be installed in a matter of minutes, but it’s not necessary a good idea to always use a full resolver instead of the ISP…

Resource control with systemd

My dev environment requires CouchDB , ElasticSearch , Redis , a Django dev server, and a web browser. Usually I even need two browsers: Firefox and Chromium . And, of course, I run Emacs and a few instances or urxvt . This takes a lot of resources. And I obviously don’t want my laptop to lag because it’s swapping or because any service is hogging the CPU. Since the biggest offender are…

New blog engine… again

Another year (or two), another blog engine 😃 I’ve now switched to Pelican , a static blog engine written in Python. So far so good: it works well, is fast, and there’s a great community working on a lot of nice plugins and themes (including this one). Now let’s hope I’ll write a little more 😃

Optimizing JPEG pictures

I recently realized that during our vacation in London, my girlfriend and me took about 4 GB of pictures. Since I currently have 30 GB of storage space on rsync.net to do my backups, 4 GB is quite a lot. Fortunately, there are several solutions to reduce their size. The first one would be to resize them or to increase their compression ratio / decrease their quality. But I don’t want such a…