Love thy neighbor as thyself
‘Love thy neighbor as thyself’, words which astoundingly occur already in the Old Testament.
One can love one’s neighbor less than one loves oneself; one is then the egoist, the racketeer, the capitalist, the bourgeois. and although one may accumulate money and power one does not of necessity have a joyful heart, and the best and most attractive pleasures of the soul are blocked.
Or one can love one’s neighbor more than oneself—then one is a poor devil, full of inferiority complexes, with a longing to love everything and still full of hate and torment towards oneself, living in a hell of which one lays the fire every day anew.
But the equilibrium of love, the capacity to love without being indebted to anyone, is the love of oneself which is not taken away from any other, this love of one’s neighbor which does no harm to the self.
I always have a hard time finding this quote on the Internet. Let's fix that.
Work around Google evil .ics feeds
I've happily been using
After doing that, I noticed that the fan in my laptop was on more often than usual, and I noticed that akonadi-server and postgres were running very often, and doing quite a lot of processing.
I investigated and realised that Google seems to be doing everything they can to make their ical feeds hard to sync against efficiently. This is the list of what I have observed Gmail doing to an unchanged ical feed:
Date:headers in HTTP replies are always now
If-Modified-Since:is not supported
DTSTAMPof each element is always now
VTIMEZONEentries appear in random order
CNentries randomly change between full name and plus.google.com user ID
ATTENDEEentries randomly change between having a CN or not having it
TRIGGERentries change spontaneously
CREATEDentries change spontaneously
This causes akonadi to download and reprocess the entire ical feed at every single poll, and I can't blame akonadi for doing it. In fact, Google is saying that there is a feed with several years worth of daily appointments that all keep being changed all the time.
As a work-around, I have configured the akonadi source to point at a local file
on disk, and I have written a script
to update the file only if the
.ics feed has actually changed.
Have a look at the script:
I consider it far from trivial, since it needs to do a partial parsing of the
.ics feed to throw away all the nondeterminism that Google pollutes it with.
$ cat ~/.config/systemd/user/update-ical-feeds.timer [Unit] Description=Updates ical feeds every hour # Only run when on AC power ConditionACPower=yes [Timer] # Run every hour OnActiveSec=1h # Run a minute after boot OnBootSec=1m Unit=update-ical-feeds.service $ cat ~/.config/systemd/user/update-ical-feeds.service [Unit] Description=Update ICal feeds [Service] # Use oneshot to prevent two updates being run in case the previous one # runs for more time than the timer interval Type=oneshot ExecStart=/home/enrico/tmp/calendars/update $ systemctl --user start update-ical-feeds.timer $ systemctl --user list-timers NEXT LEFT LAST PASSED UNIT ACTIVATES Wed 2015-03-25 22:19:54 CET 59min left Wed 2015-03-25 21:19:54 CET 2s ago update-ical-feeds.timer update-ical-feeds.service 1 timers listed. Pass --all to see loaded but inactive timers, too.
To reload the configuration after editing:
systemctl --user daemon-reload.
I wonder if
ConditionACPower needs to be in the
.timer or in the
.service, since there is a
[Unit] section is in both. Update: I have
been told it can be in the
I also wonder if there is a way to have the timer trigger only when online.
There is a
network-online.target and I do not know if it is applicable. I
also do not know how to ask systemd if all the preconditions are currently met
for a .service/.timer to run.
Finally, I especially wonder if it is worth hoping that Google will ever make
.ics feeds play nicely with calendar clients.
Screen-dependent window geometry
I have an external monitor for my laptop in my work desk at home, and when I work I keep a few windows like IRC on my laptop screen, and everything else on the external monitor. Then maybe I transfer on the sofa to watch a movie or in the kitchen to cook, and I unplug from the external monitor to bring the laptop with me. Then maybe I go back to the external monitor to resume working.
The result of this (with openbox) is that when I disconnect the external monitor all the windows on my external monitor get moved to the right edge of the laptop monitor, and when I reconnect the external monitor I need to rearrange them all again.
I would like to implement something that does the following:
- it keeps a dictionary mapping screen geometry to window geometries
- every time a window geometry and virtual desktop number changes, it gets recorded in the hash for the current screen geometry
- every time the screen geometry changes, for each window, if there was a saved window geometry + wirtual desktop number for it for the new screen geometry, it gets restored.
- Is anything like this already implemented? Where?
- If not, what would be a convenient way to implement it myself, ideally in a wmctrl-like way that does not depend on a specific WM?
Note: I am not interested in switching to a different WM unless it is openbox with this feature implemented in it.
Reuse passwords in /etc/crypttab
Today's scenario was a laptop with an SSD and a spinning disk, and the goal was to deploy a Debian system on it so that as many things as possible are encrypted.
My preferred option for it is to setup one big LUKS partition in each disk, and put a LVM2 Physical Volume inside each partition. At boot, the two LUKS partition are opened, their contents are assembled into a Volume Group, and I can have everything I want inside.
This has advantages:
- if any of the disks breaks, the other can still be unlocked, and it should still be possible to access the LVs inside it
- once boot has happened, any layout of LVs can be used with no further worries about encryption
- I can use pvmove to move partitions at will between SSD and spinning disks, which means I can at anytime renegotiate the tradeoffs between speed and disk space.
However, by default this causes cryptsetup to ask for the password once for each LUKS partition, even if the passwords are the same.
Searching for ways to mitigate this gave me unsatisfactory results, like:
- decrypt the first disk, and use a file inside it as the keyfile to decrypt the second one. But in this case if the first disk breaks, I also lose the data in the second disk.
- reuse the LUKS session key for the first disk in the second one. Same problem as before.
- put a detached LUKS header in /boot and use it for both disks, then make regular backups of /boot. It is an interesting option that I have not tried.
The solution that I found was something that did not show up in any of my search results, so I'm documenting it here:
# <target name> <source device> <key file> <options> ssd /dev/sda2 main luks,initramfs,discard,keyscript=decrypt_keyctl spin /dev/sdb1 main luks,initramfs,keyscript=decrypt_keyctl
This caches each password for 60 seconds, so that it can be reused to unlock
other devices that use it. The documentation can be found at the beginning of
/lib/cryptsetup/scripts/decrypt_keyctl, beware of the leopard™.
main is an arbitrary tag used to specify which devices use the same password.
This is also useful to work easily with multiple LUKS-on-LV setups:
# <target name> <source device> <key file> <options> home /dev/mapper/myvg-chome main luks,discard,keyscript=decrypt_keyctl backup /dev/mapper/myvg-cbackup main luks,discard,keyscript=decrypt_keyctl swap /dev/mapper/myvg-cswap main swap,discard,keyscript=decrypt_keyctl
Free as in Facebook
Yesterday we were in an airport. We tried to connect to the airport "free" wifi. It had a captive portal that asked for a lot of personal information before one could maybe get on the internet, and we gave up. Bologna Airport, no matter what they do to pretend that they like you, it's always clear that they don't.
I looked at the captive portal screen and I said: «ah yes, "free" wifi. Free as in Facebook».
We figured that we had an expression that will want to be reused.
Another day in the life of a poor developer
try: # After Python 3.3 from collections.abc import Iterable except ImportError: # This has changed in Python 3.3 (why, oh why?), reinforcing the idea that # the best Python version ever is still 2.7, simply because upstream has # promised that they won't touch it (and break it) for at least 5 more # years. from collections import Iterable import shlex if hasattr(shlex, "quote"): # New in version 3.3. shell_quote = shlex.quote else: # Available since python 1.6 but deprecated since version 2.7: Prior to Python # 2.7, this function was not publicly documented. It is finally exposed # publicly in Python 3.3 as the quote function in the shlex module. # # Except everyone was using it, because it was the only way provided by the # python standard library to make a string safe for shell use # # See http://stackoverflow.com/questions/35817/how-to-escape-os-system-calls-in-python import pipes shell_quote = pipes.quote import shutil if hasattr(shutil, "which"): # New in version 3.3. shell_which = shutil.which else: # Available since python 1.6: # http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python from distutils.spawn import find_executable shell_which = find_executable
Akonadi client example
After many failed attemps I have managed to build a C++ akonadi client. It has felt like one of the most frustrating programming experiences of my whole life, so I'm sharing the results hoping to spare others from all the suffering.
First thing first, akonadi client libraries are not in
libakonadi-dev but in
kdepimlibs5-dev, even if
kdepimlibs5-dev does not show in
Then, kdepimlibs is built with Qt4. If your application uses Qt5 (mine was) you need to port it back to Qt4 if you want to talk to Akonadi.
Then, kdepimlibs does not seem to support qmake and does not ship pkg-config
.pc files, and if you want to use kdepimlibs your build system needs to be
cmake. I ported by code from qmake to cmake, and now qtcreator wants me to
run cmake by hand every time I change the
CMakeLists.txt file, and it stopped
allowing to add, rename or delete sources.
Finally, most of the code / build system snippets found on the internet seem flawed in a way or another, because the build toolchain of Qt/KDE applications has undergone several redesignins during time, and the network is littered with examples from different eras. The way to obtain template code to start a Qt/KDE project is to use kapptemplate. I have found no getting started tutorial on the internet that said "do not just copy the snippets from here, run kapptemplate instead so you get them up to date".
kapptemplate supports building an "Akonadi Resource" and an "Akonadi Serializer", but it does not support generating template code for an akonadi client. That left me with the feeling that I was dealing with some software that wants to be developed but does not want to be used.
Anyway, now an example of how to interrogate Akonadi exists as is on the internet. I hope that all the tears of blood that I cried this morning have not been cried in vain.