<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Home on OSSO B.V.</title>
    <link>/</link>
    <description>Recent content in Home on OSSO B.V.</description>
    <generator>Hugo -- gohugo.io</generator>
    <lastBuildDate>Wed, 20 Nov 2019 14:14:49 +0100</lastBuildDate><atom:link href="/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>linux / local root exploit / module vetting</title>
      <link>/blog/2026/linux-local-root-exploit-module-vetting/</link>
      <pubDate>Fri, 08 May 2026 00:00:00 +0000</pubDate>
      
      <guid>/blog/2026/linux-local-root-exploit-module-vetting/</guid>
      <description>Recently, we were greeted with the Copy Fail Linux kernel vulnerability. Mitigating this was a matter of denylisting a module. But, only eight days later, there was another exploit, also (ab)using AF_ALG and kernel module autoloading. I&#39;m betting this is not the last, now that the kernel is scrutinized using AI models that keep getting more advanced.
Luckily, we had our machine inventory up to date. So when CVE-2026-31431 (&amp;quot;Copy Fail&amp;quot;) came along, deploying a mitigation was a matter of:</description>
    </item>
      
    <item>
      <title>macos tahoe / ecn / slow downloads</title>
      <link>/blog/2026/macos-tahoe-ecn-slow-downloads/</link>
      <pubDate>Wed, 04 Feb 2026 00:00:00 +0000</pubDate>
      
      <guid>/blog/2026/macos-tahoe-ecn-slow-downloads/</guid>
      <description>Recently, a customer reported an intermittent but frustrating issue: since upgrading to macOS 26 (Tahoe), downloads from our servers were occasionally crawling. Not always, and not for everyone. The culprit turned out to be a combination of Explicit Congestion Notification (ECN), NIC offloading limitations, and the way classic congestion control algorithms react to &amp;quot;well-intentioned&amp;quot; signals.
The macOS Tahoe ECN lottery The first mystery was the intermittency. We noticed that some connections were fast, while others to the same server appeared throttled.</description>
    </item>
      
    <item>
      <title>recap 2025 - updates at OSSO</title>
      <link>/blog/2025/recap2025/</link>
      <pubDate>Fri, 19 Dec 2025 08:30:00 +0100</pubDate>
      
      <guid>/blog/2025/recap2025/</guid>
      <description>2025 &amp;ndash; Finding the Turbo Button  A year of momentum. After the &amp;ldquo;certification heavy&amp;rdquo; focus of 2024, 2025 felt like shifting into a higher gear. We&amp;rsquo;ve seen our infrastructure move to 100G, our hardware embrace a new generation of speed, and our team grow into a tighter, faster unit.
Looking back at the last twelve months, the theme hasn&amp;rsquo;t just been &amp;ldquo;maintenance&amp;rdquo; &amp;mdash; it&amp;rsquo;s been about refinement. We&amp;rsquo;ve been busy cleaning out the old (goodbye spinning rust and legacy loadbalancers) to make room for the new (hello EPYC processors and Nokia core routers).</description>
    </item>
      
    <item>
      <title>Kubernetes: the new Gateway API</title>
      <link>/blog/2025/k8s-gateway-api/</link>
      <pubDate>Tue, 16 Dec 2025 00:00:00 +0000</pubDate>
      
      <guid>/blog/2025/k8s-gateway-api/</guid>
      <description>Transitioning K8S towards the Gateway API We&amp;rsquo;ve heard the chatter about the retirement of the ingress-nginx ingress-controller. It seems to be a hot topic! We&amp;rsquo;ve had quite a few people ask:
 &amp;ldquo;Hey OSSO, have you seen this already?&amp;quot;
 Yes! We have!
Actually, we&amp;rsquo;re right on top of it. We plan to smoothly transition and adapt, and today we want to clarify OSSO&amp;rsquo;s approach going forward.
This post outlines the transition from the established Kubernetes Ingress resource to its successor Gateway API, detailing the reasons for the transition, our proposed migration path, and the key architectural concepts.</description>
    </item>
      
    <item>
      <title>ubuntu / gnome config / issues / 2025</title>
      <link>/blog/2025/ubuntu-gnome-config-issues-2025/</link>
      <pubDate>Tue, 02 Dec 2025 00:00:00 +0000</pubDate>
      
      <guid>/blog/2025/ubuntu-gnome-config-issues-2025/</guid>
      <description>I had flushed my desktop and was ready to start fresh. Still using Ubuntu for now. It does take a few hacks and tricks to get my system right.
Disable and purge snap For one, I&#39;m removing snap. The Ubuntu Snap takeover has cost me so many man hours. As mentioned in the linked post, removing it and going with the Linux Mint packages was a great decision. Not once have I regretted not having Snap installed.</description>
    </item>
      
    <item>
      <title>proxmox vm / no arp replies / mellanox nic</title>
      <link>/blog/2025/proxmox-vm-no-arp-replies-mellanox-nic/</link>
      <pubDate>Tue, 30 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>/blog/2025/proxmox-vm-no-arp-replies-mellanox-nic/</guid>
      <description>Recently, when upgrading a Proxmox host from 7.2 to 8.4, we ran into a strange issue. The hypervisor host had network connectivity, but the VM guests did not. The upgrade was continued to Proxmox 9.0, but that did not fix the problem.
The host was fine. We could ssh in, ping the gateway, do updates, whatever &amp;mdash; but the guests had trouble communicating. In particular: the guests appeared unable to find the gateway at layer 2.</description>
    </item>
      
    <item>
      <title>zabbix / wrong nvme temperature readings</title>
      <link>/blog/2025/zabbix-wrong-nvme-temperature-readings/</link>
      <pubDate>Thu, 18 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>/blog/2025/zabbix-wrong-nvme-temperature-readings/</guid>
      <description>After installing some new nodes Zabbix began reporting NVMe drive temperatures that were... alarming. Think &amp;quot;above 60 °C&amp;quot; alarming. But when I checked the same drives manually, the values were sane. So, either the drives were gaslighting me, or Zabbix was.
The search Decomposing what our monitoring scripts do was really just calling nvme-cli:
# nvme smart-log /dev/nvme0n1 | grep temper temperature : 33 °C (306 K) Nothing wrong there.</description>
    </item>
      
    <item>
      <title>Security</title>
      <link>/security/</link>
      <pubDate>Tue, 16 Sep 2025 13:40:31 +0200</pubDate>
      
      <guid>/security/</guid>
      <description>Information Security at OSSO At OSSO, information security is a core component of our operations, not an afterthought. We maintain a robust security posture to protect our infrastructure and customer data, and we believe in being transparent about our practices. This page outlines our formal certifications and our implementation of key industry standards.</description>
    </item>
      
    <item>
      <title>loopback through leaf / single nic iperf test</title>
      <link>/blog/2025/loopback-through-leaf-single-nic-iperf-test/</link>
      <pubDate>Sun, 06 Jul 2025 00:00:00 +0000</pubDate>
      
      <guid>/blog/2025/loopback-through-leaf-single-nic-iperf-test/</guid>
      <description>When bringing up new servers, especially with new or untested network interface cards (NICs) or cables, you might want to test their raw network throughput. While standard iperf tests between two different machines are common, sometimes you want to isolate the test to a single NIC, pushing traffic through it and back, effectively looping it at a nearby switch. This verifies the physical path, the SFP, and the NIC&#39;s transmit/receive capabilities without involving another server&#39;s NIC or network stack.</description>
    </item>
      
    <item>
      <title>invalid elf header magic / rook-ceph / k8s</title>
      <link>/blog/2025/invalid-elf-header-magic-rook-ceph-k8s/</link>
      <pubDate>Sat, 31 May 2025 00:00:00 +0000</pubDate>
      
      <guid>/blog/2025/invalid-elf-header-magic-rook-ceph-k8s/</guid>
      <description>Yesterday, we noticed some previously unseen messages in the logs: Invalid ELF header magic: != \x7fELF. Of course an ELF binary should start with a valid header. Who/what is trying to run something else?
These messages appeared on Kubernetes nodes that were recently installed and not yet fully in use for production workloads. Coincidentally, these particular nodes were running Ubuntu 24.04 (Noble Numbat), while the rest of this cluster was still on older versions.</description>
    </item>
      
    <item>
      <title>nginx / no realip in logs / bug</title>
      <link>/blog/2025/nginx-no-realip-in-logs-bug/</link>
      <pubDate>Fri, 30 May 2025 00:00:00 +0000</pubDate>
      
      <guid>/blog/2025/nginx-no-realip-in-logs-bug/</guid>
      <description>Recently we were doing a vulnerability scan on an external endpoint of a website. During this time, we noticed simultaneous suspicious activity coming from inside our internal network. What&#39;s the deal?
To make a long story short: we use a proxy (like HAProxy) in front of our webservers, and it speaks the Proxy Protocol to pass along the original client&#39;s IP address. That way, when a request hits our internal nginx server, the logs show the real client&#39;s IP, not the IP of the reverse proxy that actually made the connection.</description>
    </item>
      
    <item>
      <title>supermicro / ikvm / expired certificate</title>
      <link>/blog/2025/supermicro-ikvm-expired-certificate/</link>
      <pubDate>Thu, 29 May 2025 00:00:00 +0000</pubDate>
      
      <guid>/blog/2025/supermicro-ikvm-expired-certificate/</guid>
      <description>Supermicro computers generally work very well. At our company we&#39;ve been using them for ages. One thing that does keep giving us the occasional trouble however is the BMC. Today, we&#39;ll be looking at expired certificates of the iKVM interface.
Introduction First, some definitions, which we generally use interchangeably:
The Baseboard Management Controller (BMC) is the chipset core of the Intelligent Platform Management Interface (IPMI) implementation, which we mostly use to remotely attach a Keyboard, Video and Mouse (KVM, over IP).</description>
    </item>
      
    <item>
      <title>pveproxy / systemd journald / perl buffering</title>
      <link>/blog/2025/pveproxy-systemd-journald-perl-buffering/</link>
      <pubDate>Tue, 15 Apr 2025 00:00:00 +0000</pubDate>
      
      <guid>/blog/2025/pveproxy-systemd-journald-perl-buffering/</guid>
      <description>Because I was debugging &amp;mdash; what later turned out to be &amp;mdash; an application firewall that was messing with my connections to Proxmox pveproxy on port 8006, I wanted more debug logs. Telling pveproxy to give me more info gave me a bit of a hard time.
Connections from a remote peer would get disconnected, and it initially looked like pveproxy was to blame.
Step one: get more info from pveproxy.</description>
    </item>
      
    <item>
      <title>sed / regular expressions / optimizing</title>
      <link>/blog/2025/sed-regular-expressions-optimizing/</link>
      <pubDate>Mon, 17 Mar 2025 00:00:00 +0000</pubDate>
      
      <guid>/blog/2025/sed-regular-expressions-optimizing/</guid>
      <description>Last week, we were looking at using sed(1) to remove line feeds from CSV files. The regular expressions in that post could use some further inspection.
 I&#39;m sorry that this is a rather dry post. I wanted to get the numbers out there because the differences are significant. But without the example runs you&#39;re just left with numbers.
Feel free to skip right to the conclusions.
 To recap: we were working on multiline CSV files.</description>
    </item>
      
    <item>
      <title>sed / remove line feeds / csv</title>
      <link>/blog/2025/sed-remove-line-feeds-csv/</link>
      <pubDate>Sat, 15 Mar 2025 00:00:00 +0000</pubDate>
      
      <guid>/blog/2025/sed-remove-line-feeds-csv/</guid>
      <description>Can you use sed(1) to remove line feeds?
Yes you can. Even though sed, the stream editor, is line based, you can use it to remove line feeds from output.
In this post we&#39;ll be exploring how that is done and look into how a slight refactoring step can provide a big speed gain. The task at hand is removing line feeds from CSV file with multiline strings. Why? Because I want to use grep and awk on it, and multiline strings would complicate that a lot.</description>
    </item>
      
    <item>
      <title>recap 2024 - updates at OSSO</title>
      <link>/blog/2024/recap2024/</link>
      <pubDate>Fri, 20 Dec 2024 09:30:00 +0100</pubDate>
      
      <guid>/blog/2024/recap2024/</guid>
      <description>2024 &amp;ndash; a story in four acts  The end of the year. A good time to reflect on what happened the past twelve months. The ups, the downs. What did we achieve? And what can we look forward to?
Some of you have asked to be updated on what we&amp;rsquo;re working on at OSSO. We&amp;rsquo;ll gladly share the gist here in this recap, which is in English for once (after four Dutch editions in 2020, 2021, 2022 and 2023).</description>
    </item>
      
    <item>
      <title>mysql binlog replay / max_allowed_packet</title>
      <link>/blog/2024/mysql-binlog-replay-max-allowed-packet/</link>
      <pubDate>Fri, 03 May 2024 00:00:00 +0000</pubDate>
      
      <guid>/blog/2024/mysql-binlog-replay-max-allowed-packet/</guid>
      <description>Trying to replay MySQL binlogs? And running into max_allowed_packet errors? Fear not. Likely this is not corruption, but packets that really are that big.
In 2021 I wrote about mariabackup and selective table restore. That blog entry shows how one might restore a mariabackup-saved snapshot of a MariaDB (MySQL) database. Specifically, it focuses on recovering only one or two tables selectively and it details optional GPG decryption and decompression.
Here&#39;s a recap of the mandatory steps for full recovery and additionally how to replay binlogs to a specific point in time.</description>
    </item>
      
    <item>
      <title>mariadb check table / galera locking</title>
      <link>/blog/2024/mariadb-check-table-galera-locking/</link>
      <pubDate>Wed, 17 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>/blog/2024/mariadb-check-table-galera-locking/</guid>
      <description>After upgrading some database nodes from MariaDB 10.3 to 10.6 we encountered some issues with tables not being fully correct. We&#39;d like to CHECK (and maybe REPAIR) TABLE the entire database. But the database must not block queries on other nodes of the cluster.
The corruption we saw might have been a small corruption that had crept in during even earlier upgrades, we don&#39;t know. But we do know that we&#39;d like to get this sorted before the corruption gets worse after further upgrades.</description>
    </item>
      
    <item>
      <title>systemd-networkd-wait-online / stalling and failing</title>
      <link>/blog/2024/systemd-networkd-wait-online-stalling-and-failing/</link>
      <pubDate>Fri, 29 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>/blog/2024/systemd-networkd-wait-online-stalling-and-failing/</guid>
      <description>systemd-networkd-wait-online.service failing? Maybe it&#39;s IPv6.
Do you have a list of failed systemd units that looks like this?
# systemctl list-units --failed UNIT LOAD ACTIVE SUB DESCRIPTION ● systemd-networkd-wait-online.service loaded failed failed Wait for Network to be Configured Then that could be due to IPv6 networking not being set up properly.
Check the interfaces list:
# ip -br a lo UNKNOWN 127.0.0.1/8 ::1/128 ens18 UP 10.20.30.41/31 fe80::a124:092f:fa18:109e/64 ens19 UP 192.168.1.3/31 fe80::a124:092f:fa15:01d5/64 Proper IPv4 IPs, and only link-local IPs for IPv6?</description>
    </item>
      
    <item>
      <title>nmap ssl-enum-ciphers / haproxy / tls / no results</title>
      <link>/blog/2024/nmap-ssl-enum-ciphers-haproxy-tls-no-results/</link>
      <pubDate>Fri, 22 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>/blog/2024/nmap-ssl-enum-ciphers-haproxy-tls-no-results/</guid>
      <description>When doing an nmap ssl-enum-ciphers scan on a Haproxy machine, I got zero working ciphers. But connecting with TLS worked just fine. What is up?
While updating TLS ciphers to disable certain unsafe ciphers, we wanted to test the current offers. nmap with the ssl-enum-ciphers script should work fine for this, and it is reasonably fast:
$ nmap -Pn --script=ssl-enum-ciphers -p 443 google.com ... 443/tcp open https | ssl-enum-ciphers: | TLSv1.</description>
    </item>
      
    <item>
      <title>gpg-agent / ssh / ed25519 / agent refused</title>
      <link>/blog/2024/gpg-agent-ssh-ed25519-agent-refused/</link>
      <pubDate>Tue, 23 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>/blog/2024/gpg-agent-ssh-ed25519-agent-refused/</guid>
      <description>After putting in all the work to get ED25519 OpenPGP keys in my Yubikey smart card, I was slightly frustrated that the SSH support &amp;quot;sometimes&amp;quot; didn&#39;t work.
I thought I had tested that it worked, but today it didn&#39;t.
$ ssh my_server sign_and_send_pubkey: signing failed for ED25519 &amp;quot;cardno:000612345678&amp;quot; from agent: agent refused operation walter@my_server: Permission denied (publickey). That&#39;s odd.
Adding some debug to the gpg-agent &amp;mdash; debug 1024 in gpg-agent.conf &amp;mdash; got me this:</description>
    </item>
      
    <item>
      <title>recap 2023 - updates van OSSO</title>
      <link>/blog/2023/recap2023/</link>
      <pubDate>Fri, 22 Dec 2023 18:13:00 +0100</pubDate>
      
      <guid>/blog/2023/recap2023/</guid>
      <description>2023 &amp;ndash; betere omgevingen, betere security  Waar we vorig jaar druk bezig zijn geweest legacy op te ruimen, was dit jaar meer een jaar van de uitbreidingen: ArgoCD, NetworkPolicies, Cilium, Loki/Mimir&amp;hellip;
ContainerDay Security Met het gehele OSSO team zijn we afgelopen maart naar Hamburg geweest, naar ContainerDay Security 2023. Daar hebben we bijgepraat over de huidige stand van zaken op security gebied binnen Kubernetes.
Hier kwam het laatste zetje wat we nodig hadden om Cilium te gaan uitproberen voor Kubernetes networking.</description>
    </item>
      
    <item>
      <title>mplayer / screen saver / wayland</title>
      <link>/blog/2023/mplayer-screen-saver-wayland/</link>
      <pubDate>Sun, 15 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/mplayer-screen-saver-wayland/</guid>
      <description>I don&#39;t usually watch movies from my laptop, but when I do, I don&#39;t want the screen saver to kick in.
Occasionally, I notice that my old time movie player mplayer does not inhibit the screen saver or screen blanking. That means that 5 minutes into a movie, the screen turns black.
I don&#39;t think this used to be the case. Maybe it&#39;s because I&#39;m running the Wayland display server in GNOME now.</description>
    </item>
      
    <item>
      <title>bash / postfix health check / dev tcp</title>
      <link>/blog/2023/bash-postfix-health-check-dev-tcp/</link>
      <pubDate>Wed, 20 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/bash-postfix-health-check-dev-tcp/</guid>
      <description>Using /dev/tcp in bash for a health check? Here&#39;s an example.
I had a script that used netcat to connect to a Postfix email daemon to check its health status. To avoid pipelining errors I had it sleep between each write. The core looked somewhat like this:
messages=$(for x in \  &amp;#39;EHLO localhost&amp;#39; \  &amp;#39;MAIL FROM:&amp;lt;healthz@localhost&amp;gt;&amp;#39; \  &amp;#39;RCPT TO:&amp;lt;postmaster@example.com&amp;gt;&amp;#39; \  RSET \  QUIT do sleep 0.</description>
    </item>
      
    <item>
      <title>gpgv / can&#39;t allocate lock for</title>
      <link>/blog/2023/gpgv-can-t-allocate-lock-for/</link>
      <pubDate>Mon, 18 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/gpgv-can-t-allocate-lock-for/</guid>
      <description>gpgv prints out a warning that it cannot allocate a lock. This looks like something should be fixable, but it isn&#39;t.
Observed with gpg version 2.2.27-3ubuntu2.1:
$ gpgv &amp;lt;/dev/null gpgv: can&#39;t allocate lock for &#39;/home/walter/.gnupg/trustedkeys.gpg&#39; gpgv: verify signatures failed: Unknown system error The issue at hand here is the “gpgv: can&#39;t allocate lock for &#39;/home/walter/.gnupg/trustedkeys.gpg&#39;”. Can we fix something to suppress that?
TL;DR: no
Investigation Fire up the debugger gdb and break at keybox_lock.</description>
    </item>
      
    <item>
      <title>etckeeper / git / pack-objects died of signal 9</title>
      <link>/blog/2023/etckeeper-git-pack-objects-died-of-signal-9/</link>
      <pubDate>Fri, 15 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/etckeeper-git-pack-objects-died-of-signal-9/</guid>
      <description>Is your etckeeper dying on the git gc?
On several machines I have now seen git run out of memory when trying to do repo optimization and garbage collection. Usually this happened in /etc where we like to have etckeeper. It might look like this:
... warning: The last gc run reported the following. Please correct the root cause and remove .git/gc.log Automatic cleanup will not be performed until the file is removed.</description>
    </item>
      
    <item>
      <title>segfault in library / addr2line / objdump</title>
      <link>/blog/2023/segfault-in-library-addr2line-objdump/</link>
      <pubDate>Thu, 14 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/segfault-in-library-addr2line-objdump/</guid>
      <description>Yesterday, we spotted some SEGFAULTs on an Ubuntu/Focal server. We did not have core dumps, but the kernel message in dmesg was sufficient to find a culprit.
The observed messages were these:
nginx[854]: segfault at 6d702e746379 ip 00007ff40dc2f5a3 sp 00007fffd51c8420 error 4 in libperl.so.5.30.0[7ff40dbc7000+166000] Code: 48 89 43 10 48 83 c4 18 5b 5d 41 5c 41 5d 41 5e 41 5f c3 0f 1f 40 00 0f b6 7f 30 48 c1 e8 03 48 29 f8 48 89 c3 74 89 48 8b 02 &amp;lt;4c&amp;gt; 8b 68 10 4d 85 ed 0f 84 28 01 00 00 0f b6 40 30 49 c1 ed 03 49 nginx[951947]: segfault at 10 ip 00007fba4a1645a3 sp 00007ffe57b0f8a0 error 4 in libperl.</description>
    </item>
      
    <item>
      <title>qpress / qz1 extension</title>
      <link>/blog/2023/qpress-qz1-extension/</link>
      <pubDate>Tue, 12 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/qpress-qz1-extension/</guid>
      <description>This is a quick note to my future self. As we&#39;re using qpress less in favor of lz4 that has been available on Ubuntu Focal and above, we&#39;re inclined to forget what the .qz1 extension means.
Wondering what files with the .qz1 extension do?
This concerns single stream qpress compressed files.
Historically qpress uses the .qp extension, but that concerns multifile archives. The qpress binary can write compressed streams to stdout, but it will not decompress them to stdout.</description>
    </item>
      
    <item>
      <title>dirmngr / keyserver / disable-ipv6 / bionic</title>
      <link>/blog/2023/dirmngr-keyserver-disable-ipv6-bionic/</link>
      <pubDate>Fri, 01 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/dirmngr-keyserver-disable-ipv6-bionic/</guid>
      <description>This morning a build pipeline failed. dirmngr called by apt-key tried to use IPv6, even though it was disabled.
The build logs had this to say:
21.40 + apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 21.50 Warning: apt-key output should not be parsed (stdout is not a terminal) 21.57 Executing: /tmp/apt-key-gpghome.KzTTOZjgZP/gpg.1.sh --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 21.65 gpg: keyserver receive failed: Cannot assign requested address This was strange for a number of reasons:</description>
    </item>
      
    <item>
      <title>mariadb / gdb / debugging shutdown deadlock / part 2</title>
      <link>/blog/2023/mariadb-gdb-debugging-shutdown-deadlock-part-2/</link>
      <pubDate>Thu, 31 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/mariadb-gdb-debugging-shutdown-deadlock-part-2/</guid>
      <description>We were looking at a core dump of MariaDB instance that was in a deadlocked state. It was killed with SIGABRT. We now like to get MySQL thread info from it. Python support in gdb is here to help.
To recap: we were dissecting the core dump with gdb (gdb /usr/sbin/mariadbd core.208161), found out that it was waiting on one of the threads to stop before stopping completely. We now want to know what exactly it was waiting for.</description>
    </item>
      
    <item>
      <title>mariadb / gdb / debugging shutdown deadlock / part 1</title>
      <link>/blog/2023/mariadb-gdb-debugging-shutdown-deadlock-part-1/</link>
      <pubDate>Wed, 30 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/mariadb-gdb-debugging-shutdown-deadlock-part-1/</guid>
      <description>I was asked to look into a MariaDB deadlock during shutdown. We had a core dump (luckily). Now it&#39;s time to dissect it.
Ensure you can get core dumps For starters, you want a nice core dump whenever you hit an issue. We do. Here are some tips to ensure you do too.
You need to have a couple of parameters set correctly: the equivalent of the systemd LimitCORE=infinity and the assurance that the working directory is writable (maybe WorkingDirectory=/var/lib/mysql).</description>
    </item>
      
    <item>
      <title>laptop battery discharge / logging</title>
      <link>/blog/2023/laptop-battery-discharge-logging/</link>
      <pubDate>Sat, 08 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/laptop-battery-discharge-logging/</guid>
      <description>I recently got a new Framework Laptop. It is generally nice. Apart from the reflective screen, and the excessive battery consumption.
In suspend mode, it draws too much battery: more than a Watt. This is a known issue. The worst offenders are the expansion cards. For instance the USB-A cards consume about 350mW each, just by being plugged in.
To do some testing, I whipped up a script allowing easy access to battery usage logs: discharge-log</description>
    </item>
      
    <item>
      <title>viewing unencrypted traffic / ltrace / bpftrace</title>
      <link>/blog/2023/viewing-unencrypted-traffic-ltrace-bpftrace/</link>
      <pubDate>Mon, 03 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/viewing-unencrypted-traffic-ltrace-bpftrace/</guid>
      <description>Can we view TLS-encrypted traffic on the originating or terminating host, without having to decode the data from the wire?
This is a question that comes up every now and then when trying to debug a service by looking at how it communicates.
For the most insight, we should capture the encrypted traffic and use the (logged!) pre-master secret keys. See example details in make-master-secret-log discussing how to have HAProxy log them.</description>
    </item>
      
    <item>
      <title>removing auditd / disabling logging</title>
      <link>/blog/2023/removing-auditd-disabling-logging/</link>
      <pubDate>Fri, 30 Jun 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/removing-auditd-disabling-logging/</guid>
      <description>After installing auditd for testing purposes and removing it again, my kernel logs got flooded with messages. How do I disable them?
If you happened to have installed auditd, it is likely that the kernel audit subsystem was enabled. Even when there are no rules left (auditctl -l) you can still get more messages in your kernel logs than before.
For instance, after uninstalling auditd, I still get the following ones:</description>
    </item>
      
    <item>
      <title>netplan / docker0 / bind on 172.17.0.1</title>
      <link>/blog/2023/netplan-docker0-bind-on-172-17-0-1/</link>
      <pubDate>Thu, 15 Jun 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/netplan-docker0-bind-on-172-17-0-1/</guid>
      <description>If you want to bind your host-service to a the docker IP, exposing it to docker instances, means that that IP needs to exist first. If it doesn&#39;t, your log might look like this:
LOG: listening on IPv4 address &amp;quot;127.0.0.1&amp;quot;, port 5432 LOG: could not bind IPv4 address &amp;quot;172.17.0.1&amp;quot;: Cannot assign requested address WARNING: could not create listen socket for &amp;quot;172.17.0.1&amp;quot; LOG: listening on Unix socket &amp;quot;/var/run/postgresql/.s.PGSQL.5432&amp;quot;  As you probaby know, you cannot bind to an IP that is not configured on an interface anywhere &amp;mdash; barring the net.</description>
    </item>
      
    <item>
      <title>ansible / ipv6 addresses / without link local</title>
      <link>/blog/2023/ansible-ipv6-addresses-without-link-local/</link>
      <pubDate>Thu, 13 Apr 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/ansible-ipv6-addresses-without-link-local/</guid>
      <description>Trying to get the IPv6 addresses as ansible fact, but getting unwanted link_local scope addresses?
Maybe you&#39;re landing here because you did not see a solution at &amp;ldquo;all_ipv6_addresses includes link local addresses&amp;rdquo;. (I find it most odd that they locked the GitHub ticket, eliminating the possibility for anyone to reply with a fix.)
The ansible_all_ipv6_addresses | reject(&amp;quot;ansible.utils.in_network&amp;quot;, &amp;quot;fe80::/10&amp;quot;) construct works for me. For example:
local-address=127.0.0.1, ::1, {{ ( ansible_all_ipv4_addresses + ( ansible_all_ipv6_addresses|reject(&amp;quot;ansible.</description>
    </item>
      
    <item>
      <title>zabbix server / jammy upgrade / missing font</title>
      <link>/blog/2023/zabbix-server-jammy-upgrade-missing-font/</link>
      <pubDate>Fri, 31 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/zabbix-server-jammy-upgrade-missing-font/</guid>
      <description>The other day, we upgraded the host OS for our Zabbix Server from Ubuntu/Focal to Ubuntu/Jammy. This caused all text to go missing from the rendered graphs.
The php (uwsgi) logs had the following to say:
PHP Warning: imagettfbbox(): Could not find/open font in /usr/share/zabbix/include/graphs.inc.php on line 600 At least that&#39;s a pretty clear message.
Through a quick php live hack we learned that it tried to open /usr/share/zabbix/assets/fonts/graphfont.ttf. This file was a symlink to /etc/alternatives/zabbix-frontend-font and that was a symlink to /usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.</description>
    </item>
      
    <item>
      <title>postfix / no system resources / proxy protocol</title>
      <link>/blog/2023/postfix-no-system-resources-proxy-protocol/</link>
      <pubDate>Thu, 02 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/postfix-no-system-resources-proxy-protocol/</guid>
      <description>Connecting to Postfix and getting a &amp;quot;421 4.3.2 No system resources&amp;quot;? Maybe you forgot you&#39;re using the (HAProxy) Proxy Protocol...
If you&#39;re trying to connect to your Postfix mail daemon, and it looks like this:
$ nc localhost 25 ... wait for 5 seconds ... 421 4.3.2 No system resources Then I bet you&#39;re using HAProxy as reverse proxy to your mailserver and you have the following configured:
$ postconf | grep ^postscreen_upstream postscreen_upstream_proxy_protocol = haproxy postscreen_upstream_proxy_timeout = 5s To test a direct connection, you&#39;ll need to prefix your traffic with the proxy protocol v1 handshake.</description>
    </item>
      
    <item>
      <title>oneliner / finding fixed kernel bugs</title>
      <link>/blog/2023/oneliner-finding-fixed-kernel-bugs/</link>
      <pubDate>Fri, 17 Feb 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/oneliner-finding-fixed-kernel-bugs/</guid>
      <description>Recently we were bitten by an old kernel bug on Ubuntu that only rarely triggers. Finding out where the problem was is easier if you know where to look.
We had no kernel logs to go on. Only a hanging machine with no output. And a hunch that the running kernel version linux-image-5.4.0-122 was the likely culprit. Was there another way than meticulously reading all changelogs and changes to find out which bug we&#39;re dealing with?</description>
    </item>
      
    <item>
      <title>CephFS EINVAL specified for ceph.dir.subvolume</title>
      <link>/blog/2023/cephfs-einval-specified-for-ceph-dir-subvolume/</link>
      <pubDate>Mon, 06 Feb 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/cephfs-einval-specified-for-ceph-dir-subvolume/</guid>
      <description>What could be the case when creating a subvolume in CephFS throws an EINVAL VolumeException?
A client of ours recently got errors when creating a 24GiB subvolume:
ceph fs subvolume create cephfs-filesystem \ example1 --group_name=thegroup \ --size=25769803776  But, instead of silence and a new subvolume, they got this in their face: a big Python backtrace.
Error EINVAL: Traceback (most recent call last): File &amp;quot;ceph/mgr/volumes/fs/operations/versions/subvolume_base.py&amp;quot;, line 271, in discover self.fs.stat(self.base_path) File &amp;quot;cephfs.</description>
    </item>
      
    <item>
      <title>windows openvpn / unexpected default route</title>
      <link>/blog/2023/windows-openvpn-unexpected-default-route/</link>
      <pubDate>Fri, 27 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/windows-openvpn-unexpected-default-route/</guid>
      <description>The other day, I was looking into a VPN client issue. The user could connect, they would get their routes pushed, but they would then proceed to use the VPN for all traffic instead of just the routes we provided them.
We did not push a default route, because this VPN server exposed a small internal network only. Any regular internet surfing should be done directly. So, when I looked at a tcpdump I was baffled when I saw that DNS lookups were attempted through the OpenVPN tunnel:</description>
    </item>
      
    <item>
      <title>Kubernetes CRL support with the front-proxy-client and Haproxy</title>
      <link>/blog/2023/kubernetes-crl-support-with-the-front-proxy-client-and-haproxy/</link>
      <pubDate>Mon, 23 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/kubernetes-crl-support-with-the-front-proxy-client-and-haproxy/</guid>
      <description>“Why does kube-apiserver not take a CRL file?”  Kubernetes clusters at OSSO are usually setup using PKI infrastructure from which we create client certificates for users as well.
Unfortunately, users can sometimes be a little careless [citation needed] and sometimes they manage to share their keys with the world. PKI caters for lost certificates through the issuance of periodic (or ad-hoc) Certificate Revocation Lists (CRLs), in which the PKI admins can place certificates that have been compromised: if a certificate is listed in the CRL, it is revoked, and will not be accepted by the TLS agent.</description>
    </item>
      
    <item>
      <title>django 1.8 / python 3.10</title>
      <link>/blog/2023/django-1-8-python-3-10/</link>
      <pubDate>Tue, 17 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/django-1-8-python-3-10/</guid>
      <description>After upgrading a machine to Ubuntu/Jammy there was an old Django 1.8 project that refused to run with the newer Python 3.10.
... File &amp;quot;django/db/models/sql/query.py&amp;quot;, line 11, in &amp;lt;module&amp;gt; from collections import Iterator, Mapping, OrderedDict ImportError: cannot import name &#39;Iterator&#39; from &#39;collections&#39; (/usr/lib/python3.10/collections/__init__.py)  This was relatively straight forward to fix, by using the following patch. Some parts were stolen from a stackoverflow response by Elias Prado.
--- a/django/core/paginator.py 2023-01-11 14:09:04.</description>
    </item>
      
    <item>
      <title>sysctl / modules / load order / nf_conntrack</title>
      <link>/blog/2023/sysctl-modules-load-order-nf-conntrack/</link>
      <pubDate>Tue, 10 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>/blog/2023/sysctl-modules-load-order-nf-conntrack/</guid>
      <description>Recently we ran into an issue where connections were unexpectedly aborted. Connections from a NAT-ed client (a K8S pod) to a server would suddently get an old packet (according to the sequence number) in the middle of the data. This triggered the Linux NAT-box to issue a reset packet (RST). Setting the kernel flag to mitigate this behaviour required some knowledge of module load order during boot.
Spurious retransmits causing connection teardown To start off: we observed that traffic from a pod to a server got disconnected.</description>
    </item>
      
    <item>
      <title>recap 2022 - part 2 / stable diffusion</title>
      <link>/blog/2022/recap2022-part2/</link>
      <pubDate>Fri, 23 Dec 2022 10:30:00 +0100</pubDate>
      
      <guid>/blog/2022/recap2022-part2/</guid>
      <description>2022 &amp;ndash; genereren van plaatjes door de computer  Als je een beetje tech-nieuws hebt gevolgd, kan het je niet ontgaan zijn dat er allerhande sprongen in de kunstmatige intelligentie (AI) gebeurd zijn het afgelopen jaar.
Machine learning (ML) bestaat natuurlijk al langer. Maar in 2022 ging de bal voor computer generated images echt rollen. En niet alleen images. GPT-3 en ChatGPT laten zien dat computergegeneerde teksten ook al verbluffend goed kunnen zijn.</description>
    </item>
      
    <item>
      <title>recap 2022 - part 1</title>
      <link>/blog/2022/recap2022-part1/</link>
      <pubDate>Tue, 20 Dec 2022 10:13:00 +0100</pubDate>
      
      <guid>/blog/2022/recap2022-part1/</guid>
      <description>2022 &amp;ndash; afgesloten met gezelligheid  Bij OSSO hebben we het jaar afgesloten met een lekker kerstdiner. Sfeerlampjes aan 💡 Goed eten 🥩 Familie erbij 👪
Dat gezegd hebbende, beseffen we ons maar al te goed dat de Russische agressie in Oekraïne enorm leed veroorzaakt. We hopen dat de politiek genoeg wil kan tonen om David te blijven steunen in z&amp;rsquo;n strijd om de indringers weer buiten de landsgrenzen te zetten.</description>
    </item>
      
    <item>
      <title>avoiding 255 / 31-bit prefixes</title>
      <link>/blog/2022/avoiding-255-31-bit-prefixes/</link>
      <pubDate>Wed, 19 Oct 2022 00:00:00 +0000</pubDate>
      
      <guid>/blog/2022/avoiding-255-31-bit-prefixes/</guid>
      <description>At OSSO, we&#39;ve been using a spine-leaf architecture in the datacenter, using BGP and Layer 3 to the host. This means that we can have any IP address of ours just pop up anywhere in our network, simply by adding a prefix on a leaf switch. We sacrifice half of our IP space for this. But we gain simplicity by avoiding all Layer 2 tricks.
TL;DR: Avoid IP addresses ending in .</description>
    </item>
      
    <item>
      <title>supermicro / x9drw / quest for kvm</title>
      <link>/blog/2022/supermicro-x9drw-quest-for-kvm/</link>
      <pubDate>Fri, 09 Sep 2022 00:00:00 +0000</pubDate>
      
      <guid>/blog/2022/supermicro-x9drw-quest-for-kvm/</guid>
      <description>I&#39;m connected to an &amp;ldquo;ancient&amp;rdquo; Supermicro machine &amp;mdash; according to today&#39;s standards &amp;mdash; that saw the light somewhere around 2013. I&#39;m looking for a way to access the KVM module (Keyboard, Video, Mouse) so I can update it safely. You know, to be able to fix boot issues if they arise. Unfortunately, the firmware is rather old and I cannot get the iKVM application to run, like I&#39;m used to.</description>
    </item>
      
    <item>
      <title>chromium browser / without ubuntu snap / linux mint</title>
      <link>/blog/2022/chromium-browser-without-ubuntu-snap-linux-mint/</link>
      <pubDate>Wed, 31 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>/blog/2022/chromium-browser-without-ubuntu-snap-linux-mint/</guid>
      <description>In 2019, Clement &amp;quot;Clem&amp;quot; Lefebvre of Linux Mint, wrote these profetic words: &amp;ldquo;As long as snap is a solution to a problem, it&amp;rsquo;s great. Just like Flatpak, it can solve some of the real issues we have with frozen package bases. It can provide us with software we couldn&amp;rsquo;t otherwise run as packages. When it starts replacing packages for no good reason though, when it starts harming our interaction with upstream projects and software vendors and reducing our choice, it becomes a threat.</description>
    </item>
      
    <item>
      <title>falco helm upgrade / labelselector field immutable</title>
      <link>/blog/2022/falco-helm-upgrade-labelselector-field-immutable/</link>
      <pubDate>Tue, 30 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>/blog/2022/falco-helm-upgrade-labelselector-field-immutable/</guid>
      <description>Today I got this unusual error when upgrading the Falco helm chart from 1.19.4 to 2.0+.
Error: UPGRADE FAILED: cannot patch &amp;quot;falco&amp;quot; with kind DaemonSet: DaemonSet.apps &amp;quot;falco&amp;quot; is invalid: spec.selector: Invalid value: v1.LabelSelector{ MatchLabels:map[string]string{&amp;quot;app.kubernetes.io/instance&amp;quot;:&amp;quot;falco&amp;quot;, &amp;quot;app.kubernetes.io/name&amp;quot;:&amp;quot;falco&amp;quot;}, MatchExpressions:[]v1.LabelSelectorRequirement(nil) }: field is immutable  The explanation is here as given by Stackoverflow user misha2048:
 You cannot update selectors for [...] ReplicasSets, Deployments, DaemonSets [...] from my-app: ABC to my-app: XYZ and then simply [apply the changes].</description>
    </item>
      
    <item>
      <title>flipper zero multi-tool / developing</title>
      <link>/blog/2022/flipper-zero-multi-tool-developing/</link>
      <pubDate>Thu, 11 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>/blog/2022/flipper-zero-multi-tool-developing/</guid>
      <description>Here are some pointers on how to get started editing/developing plugins for the Flipper Zero multi-tool.
(When writing this, the stable version was at 0.63.3. Things are moving fast, so some of the next bits may be outdated when you read them.)
Starting Starting the Flipper Zero and adding an SD-card is documented in Flipper Zero first-start.
Now you can use all the nice pentest features already included. The SD-card is necessary to unlock some features.</description>
    </item>
      
    <item>
      <title>ubuntu jammy / ssh / rsa keys</title>
      <link>/blog/2022/ubuntu-jammy-ssh-rsa-keys/</link>
      <pubDate>Tue, 12 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>/blog/2022/ubuntu-jammy-ssh-rsa-keys/</guid>
      <description>With the new Ubuntu/Jammy we also get tighter security settings. Here are some aliases that will let you connect to older ssh servers.
For access to old Cisco routers, we already had the first two options in this alias; we now add two more:
# Alias on Ubuntu/Jammy with ssh 8.9p1-3+ to access old routers/switches: alias ssholdhw=&amp;#34;ssh \ -oKexAlgorithms=+diffie-hellman-group1-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1 \ -oCiphers=+aes128-cbc,aes192-cbc,aes256-cbc,3des-cbc \ -oHostkeyAlgorithms=+ssh-rsa \ -oPubkeyAcceptedKeyTypes=+ssh-rsa&amp;#34; That fixes so we can connect to old Cisco and old HP equipment.</description>
    </item>
      
    <item>
      <title>thunderbird / opening links / ubuntu</title>
      <link>/blog/2022/thunderbird-opening-links-ubuntu/</link>
      <pubDate>Sun, 08 May 2022 00:00:00 +0000</pubDate>
      
      <guid>/blog/2022/thunderbird-opening-links-ubuntu/</guid>
      <description>For some reason, opening links from Thunderbird stopped working. When clicking a URL, I expected Chromium to open the website, but nothing happened.
After visiting a few bug reports and the Thunderbird advanced configuration, I turned my attention to xdg-open:
$ xdg-open &#39;https://wjd.nu&#39; ERROR: not connected to the gnome-3-38-2004 content interface. Okay. So it wasn&#39;t a Thunderbird problem at all.
The culprit was that I had been doing some housekeeping in snap.</description>
    </item>
      
    <item>
      <title>dnssec validation / authoritative server</title>
      <link>/blog/2022/dnssec-validation-authoritative-server/</link>
      <pubDate>Thu, 24 Mar 2022 00:00:00 +0000</pubDate>
      
      <guid>/blog/2022/dnssec-validation-authoritative-server/</guid>
      <description>The delv(1) tool is the standard way to validate DNSSEC signatures. By default it will validate up to the DNS root zone, for which it knows and trusts the DNSKEY. If you want to validate only a part of a chain, you&#39;ll need to know a few things.
Regular DNSSEC validation Using delv is normally as simple as this:
$ delv -t A @1.1.1.1 dnssec.works. ; fully validated dnssec.works. 3600 IN A 5.</description>
    </item>
      
    <item>
      <title>nvme drive refusing efi boot</title>
      <link>/blog/2022/nvme-drive-refusing-efi-boot/</link>
      <pubDate>Thu, 10 Mar 2022 00:00:00 +0000</pubDate>
      
      <guid>/blog/2022/nvme-drive-refusing-efi-boot/</guid>
      <description>UEFI is the current boot standard. Instead of fighting it, we&#39;ve adopted it as the default for all hardware machines we install. We&#39;ve had some issues in the past, but they could all be attributed to a lack of knowledge by the operator, not by a problem with EFI itself. But, this time we couldn&#39;t figure out why the SuperMicro machine refused to boot from these newly installed EFI partitions: no bootable UEFI device found.</description>
    </item>
      
    <item>
      <title>fat16 filesystem layout</title>
      <link>/blog/2022/fat16-filesystem-layout/</link>
      <pubDate>Wed, 09 Mar 2022 00:00:00 +0000</pubDate>
      
      <guid>/blog/2022/fat16-filesystem-layout/</guid>
      <description>First there was FAT, then FAT12, FAT16 and finally FAT32. Inferior filesystems nowadays, but nevertheless both ubiquitous and mandatory for some uses. And sometimes you need to be aware of the differences.
A short breakdown of FAT16 follows &amp;mdash; we&#39;ll skip the older FAT as well as various uncommon settings, because those are not in active use.
Sector size The storage device defines (logical) sector sizes. This used to be 512 bytes per sector for a long time (we&#39;re skipping pre-hard disk tech), but this is now rapidly moving to 4096 bytes per sector on newer SSD and NVMe drives.</description>
    </item>
      
    <item>
      <title>reading matryoshka elf / dirtypipez</title>
      <link>/blog/2022/reading-matryoshka-elf-dirtypipez/</link>
      <pubDate>Tue, 08 Mar 2022 00:00:00 +0000</pubDate>
      
      <guid>/blog/2022/reading-matryoshka-elf-dirtypipez/</guid>
      <description>While looking at the clever dirtypipez.c exploit, I became curious how this elfcode was constructed.
On March 7 2022, Max Kellerman disclosed a vulnerability he found in Linux kernel 5.8 and above called The Dirty Pipe Vulnerability. Peter (blasty) at haxx.in quickly created a SUID binary exploit for it, called dirtypipez.c. This code contains a tiny ELF binary which writes another binary to /tmp/sh &amp;mdash; the ELF Matryoshka doll.
I was wondering how one parses this code &amp;mdash; to ensure it does what it says it does, and just because.</description>
    </item>
      
    <item>
      <title>rst tables with htmldjango / emoji two columns wide</title>
      <link>/blog/2022/rst-tables-with-htmldjango-emoji-two-columns-wide/</link>
      <pubDate>Mon, 28 Feb 2022 00:00:00 +0000</pubDate>
      
      <guid>/blog/2022/rst-tables-with-htmldjango-emoji-two-columns-wide/</guid>
      <description>For a project, we&#39;re using Django to generate a textual report. For readability, it is in monospace text. And we&#39;ve done it in reStructuredText (RST) so we can generate an HTML document from it as well.
A table in RST might look like this:
+-----------+-------+ | car brand | users | +===========+=======+ | Peugeot | 2 | +-----------+-------+ | Saab | 1 | +-----------+-------+ | Volvo | 4 | +-----------+-------+  Transforming this to HTML with a rst2html(1) generates a table similar to this:</description>
    </item>
      
    <item>
      <title>curious termios error / switching to asyncio serial</title>
      <link>/blog/2022/curious-termios-error-switching-to-asyncio-serial/</link>
      <pubDate>Sat, 22 Jan 2022 00:00:00 +0000</pubDate>
      
      <guid>/blog/2022/curious-termios-error-switching-to-asyncio-serial/</guid>
      <description>My Python code that interfaces with a serial port stopped working when refactoring the code to use asyncio. It started raising Invalid argument exceptions from tcsetattr(3). Why would asynchronous Python misbehave? Was there a bug in serial_asyncio?
TL;DR: When interfacing with an openpty(3) pseudoterminal &amp;mdash; which I used to emulate a real serial port &amp;mdash; setting parity and bytesize is not supported. But an error would only show up when tcsetattr(3) was called twice, which happened only in the asyncio case.</description>
    </item>
      
    <item>
      <title>recap 2021</title>
      <link>/blog/2021/recap2021/</link>
      <pubDate>Fri, 24 Dec 2021 18:10:00 +0100</pubDate>
      
      <guid>/blog/2021/recap2021/</guid>
      <description>2021 &amp;ndash; het jaar waarin alles ingehaald wordt.  Zo eindigde de recap van vorig jaar. Iets té optimistisch naar nu blijkt. De pandemie duurt voort en heeft zijn weerslag gehad op allerlei processen. Contact met onze klanten speelde nu noodgedwongen nog vaker digitaal af. Maar de OSSO-workflow kon grotendeels gehandhaafd blijven.
Hier volgen wat downs en (gelukkig vooral) ups van het afgelopen jaar.
 Challenges 😢Onze gewaardeerde collega Edgar besloot werk aan te nemen dat dichter bij huis was.</description>
    </item>
      
    <item>
      <title>systemd / zpool import / zfs mount / dependencies</title>
      <link>/blog/2021/systemd-zpool-import-zfs-mount-dependencies/</link>
      <pubDate>Fri, 19 Nov 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/systemd-zpool-import-zfs-mount-dependencies/</guid>
      <description>On getting regular ZFS mount points to work with systemd dependency ordering.
ZFS on Ubuntu is nice. And so is systemd. But getting them to play nice together sometimes requires a little extra effort.
A problem we were facing was that services would get started before their respective mount points had all been made available. For example, for some setups, we have a local-storage ZFS zpool that holds the /var/lib/docker directory.</description>
    </item>
      
    <item>
      <title>zpool import / no pools / stale zdb labels</title>
      <link>/blog/2021/zpool-import-no-pools-stale-zdb-labels/</link>
      <pubDate>Fri, 22 Oct 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/zpool-import-no-pools-stale-zdb-labels/</guid>
      <description>Today, when trying to import a newly created ZFS pool, we had to supply the -d DEV argument to find the pool.
# zpool import no pools available to import But I know it&#39;s there.
# zpool import local-storage cannot import &amp;#39;local-storage&amp;#39;: no such pool available And by specifying -d with a device search path, it can be found:
# zpool import local-storage -d /dev/disk/by-id Success!
# zpool list -oname NAME bpool local-storage rpool Manually specifying a search path is not real convenient.</description>
    </item>
      
    <item>
      <title>letsencrypt root / certificate validation on jessie</title>
      <link>/blog/2021/letsencrypt-root-certificate-validation-on-jessie/</link>
      <pubDate>Mon, 04 Oct 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/letsencrypt-root-certificate-validation-on-jessie/</guid>
      <description>On getting LetsEncrypt certificates to work on Debian/Jessie or Cumulus Linux 3 again.
Since last Thursday the 30th, the old LetsEncrypt certificate root stopped working at 14:01 UTC. This was a known and anticipated issue. All certificates had long been double signed by a new root that doubled as intermediate. Unfortunately, this does not mean that everything worked on older platforms with OpenSSL 1.0.1 or 1.0.2.
See this Debian/Jessie box &amp;mdash; we see similar behaviour on Cumulux Linux 3.</description>
    </item>
      
    <item>
      <title>umount -l / needs --make-slave</title>
      <link>/blog/2021/umount-l-needs-make-slave/</link>
      <pubDate>Sun, 03 Oct 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/umount-l-needs-make-slave/</guid>
      <description>The other day I learned &amp;mdash; the hard way &amp;mdash; that umount -l can be dangerous. Using the --make-slave mount option makes it safer.
The scenario went like this:
A virtual machine on our Proxmox VE cluster wouldn&#39;t boot. No biggie, I thought. Just mount the filesystem on the host and do a proper grub-install from a chroot:
# fdisk -l /dev/zvol/zl-pve2-ssd1/vm-215-disk-3 /dev/zvol/zl-pve2-ssd1/vm-215-disk-3p1 * 2048 124999679 124997632 59.6G 83 Linux /dev/zvol/zl-pve2-ssd1/vm-215-disk-3p2 124999680 125827071 827392 404M 82 Linux swap / Solaris # mount /dev/zvol/zl-pve2-ssd1/vm-215-disk-3p1 /mnt/root # cd /mnt/root # for x in dev proc sys; do mount --rbind /$x $x; done # chroot /mnt/root There I could run the necessary commands to fix the boot procedure.</description>
    </item>
      
    <item>
      <title>a singal 17 is raised</title>
      <link>/blog/2021/a-singal-17-is-raised/</link>
      <pubDate>Tue, 28 Sep 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/a-singal-17-is-raised/</guid>
      <description>When running the iKVM software on the BMC of SuperMicro machines, we regularly see an interesting &amp;quot;singal&amp;quot; typo.
(For the interested, we use a helper script to access the KVM console: ipmikvm. Without it, you need Java support enabled in your browser, and that has always given us trouble. The ipmikvm script logs on to the web interface, downloads the required Java bytecode and runs it locally.)
Connect to somewhere, wait for the KVM console to open, close it, and you might see something like this:</description>
    </item>
      
    <item>
      <title>mariabackup / selective table restore</title>
      <link>/blog/2021/mariabackup-selective-table-restore/</link>
      <pubDate>Sun, 12 Sep 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/mariabackup-selective-table-restore/</guid>
      <description>When using mariabackup (xtrabackup/innobackupex) for your MySQL/MariaDB backups, you get a snapshot of the mysql lib dir. This is faster than doing an old-style mysqldump, but it is slightly more complicated to restore. Especially if you just want access to data from a single table.
Assume you have a big database, and you&#39;re backing it up like this, using the mariadb-backup package:
# ulimit -n 16384 # mariabackup \ --defaults-file=/etc/mysql/debian.cnf \ --backup \ --compress --compress-threads=2 \ --target-dir=/var/backups/mysql \ [--parallel=8] [--galera-info] .</description>
    </item>
      
    <item>
      <title>apt / downgrading back to current release</title>
      <link>/blog/2021/apt-downgrading-back-to-current-release/</link>
      <pubDate>Tue, 31 Aug 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/apt-downgrading-back-to-current-release/</guid>
      <description>If you&#39;re running an older Debian or Ubuntu, you may sometimes want to check out a newer version of a package, to see if a particular bug has been fixed.
I know, this is not supported, but this scheme Generally Works (*):
 replace the current release name in /etc/apt/sources.list, with the next release &amp;mdash; e.g. from bionic to focal do an apt-get update and an apt-get install SOME-PACKAGE  You can test the package while replacing the sources.</description>
    </item>
      
    <item>
      <title>k8s / lightweight redirect</title>
      <link>/blog/2021/k8s-lightweight-redirect/</link>
      <pubDate>Sun, 15 Aug 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/k8s-lightweight-redirect/</guid>
      <description>Spinning up pods just to for parked/redirect sites? I think not.
Recently, I had to HTTP(S)-redirect a handful of hostnames to elsewhere. Pointing them into our well maintained K8S cluster was the easy thing to do. It would manage LetsEncrypt certificates automatically using cert-manager.io.
From the cluster, I could spin up a service and an nginx deployment with a bunch of redirect/302 rules.
However, spinning up one or more nginx instances just to have it do simple redirects sounds like overkill.</description>
    </item>
      
    <item>
      <title>traverse path permissions / namei</title>
      <link>/blog/2021/traverse-path-permissions-namei/</link>
      <pubDate>Thu, 12 Aug 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/traverse-path-permissions-namei/</guid>
      <description>How does one traverse a long path to quickly find out where you lack permissions?
So, I wanted to test some stuff in Debian/Buster. I already had an LXC container through LXD. I just needed to get some source files to the right place.
lxd$ sudo zfs list | grep buster data/containers/buster-builder 692M 117G 862M /var/snap/lxd/common/lxd/storage-pools/data/containers/buster-builder lxd$ sudo zfs mount data/containers/buster-builder Make sure there&#39;s somewhere where I can write:
lxd$ sudo mkdir \  /var/snap/lxd/common/lxd/storage-pools/data/containers/buster-builder/rootfs/home/osso/walter lxd$ sudo chown walter \  /var/snap/lxd/common/lxd/storage-pools/data/containers/buster-builder/rootfs/home/osso/walter Awesome.</description>
    </item>
      
    <item>
      <title>migrating vm interfaces / eth0 to ens18</title>
      <link>/blog/2021/migrating-vm-interfaces-eth0-to-ens18/</link>
      <pubDate>Fri, 06 Aug 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/migrating-vm-interfaces-eth0-to-ens18/</guid>
      <description>How about finally getting rid of eth0 and eth1 in those ancient Ubuntu VMs that you keep upgrading?
Debian and Ubuntu have been doing a good job at keeping the old names during upgrades. But it&#39;s time to move past that.
We expect ens18 and ens19 now. There&#39;s no need to hang on to the past. (And you have moved on to Netplan already, yes?)
Steps:
 rm /etc/udev/rules.d/80-net-setup-link.rules update-initramfs -u rm /etc/systemd/network/50-virtio-kernel-names.</description>
    </item>
      
    <item>
      <title>kioxia nvme / num_err_log_entries 0xc004 / smartctl</title>
      <link>/blog/2021/kioxia-nvme-num-err-log-entries-0xc004-smartctl/</link>
      <pubDate>Thu, 05 Aug 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/kioxia-nvme-num-err-log-entries-0xc004-smartctl/</guid>
      <description>So, these new Kioxia NVMe drives were incrementing the num_err_log_entries as soon as they were inserted into the machine. But the error said INVALID_FIELD. What gives?
In contrast to the other (mostly Intel) drives, these drives started incrementing the num_err_log_entries as soon as they were plugged in:
# nvme smart-log /dev/nvme21n1 Smart Log for NVME device:nvme21n1 namespace-id:ffffffff ... num_err_log_entries : 932 The relevant errors should be readable in the error-log. All 64 errors in the log looked the same:</description>
    </item>
      
    <item>
      <title>openssl / error 42 / certificate not yet valid</title>
      <link>/blog/2021/openssl-error-42-certificate-not-yet-valid/</link>
      <pubDate>Fri, 18 Jun 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/openssl-error-42-certificate-not-yet-valid/</guid>
      <description>In yesterday&#39;s post about not being able to connect to the SuperMicro iKVM IPMI, I wondered &amp;ldquo;why stunnel/openssl did not send error 45 (certificate_expired) for a not-yet-valid certificate.&amp;rdquo; Here&#39;s a closer examination.
Quick recap: yesterday, I got SSL alert/error 42 as response to a client certificate that was not yet valid. The server was living in 2015 and refused to accept a client certificate that would be valid first in 2016.</description>
    </item>
      
    <item>
      <title>supermicro / ikvm / sslv3 alert bad certificate</title>
      <link>/blog/2021/supermicro-ikvm-sslv3-alert-bad-certificate/</link>
      <pubDate>Thu, 17 Jun 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/supermicro-ikvm-sslv3-alert-bad-certificate/</guid>
      <description>Today I was asked to look at a machine that disallowed iKVM IPMI console access. It allowed access through the &amp;ldquo;iKVM/HTML5&amp;rdquo;, but when connecting using the &amp;ldquo;Console Redirection&amp;rdquo; (Java client, see also ipmikvm) it would quit after 10 failed attempts.
TL;DR: The clock of the machine had been reset to a timestamp earlier than the first validity of the supplied client certificate. After changing the BMC time from 2015 to 2021, everything worked fine again.</description>
    </item>
      
    <item>
      <title>partially removed pve node / proxmox cluster</title>
      <link>/blog/2021/partially-removed-pve-node-proxmox-cluster/</link>
      <pubDate>Thu, 20 May 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/partially-removed-pve-node-proxmox-cluster/</guid>
      <description>The case of the stale (removed but not removed) PVE node in our Proxmox cluster.
On one of our virtual machine clusters, a node &amp;mdash; pve3 &amp;mdash; had been removed on purpose, yet is was still visible in the GUI with a big red cross (because it was unavailable). This was not only ugly, but also caused problems for the node enumeration done by proxmove.
The node had been properly removed, according to the removing a cluster node documentation.</description>
    </item>
      
    <item>
      <title>enable noisy build / opensips</title>
      <link>/blog/2021/enable-noisy-build-opensips/</link>
      <pubDate>Tue, 11 May 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/enable-noisy-build-opensips/</guid>
      <description>How do you enable the noisy build when building OpenSIPS? The one where the actual gcc invocations are not hidden.
In various projects the compilation and linking steps called by make are cleaned up, so you only see things like:
Compiling db/db_query.c Compiling db/db_id.c ... This looks cleaner. But sometimes you want to see (or temporarily change) the compilation/linking call:
gcc -g -O9 -funroll-loops -Wcast-align -Wall [...] -c db/db_query.c -o db/db_query.</description>
    </item>
      
    <item>
      <title>missing serial / scsi / disk by-id</title>
      <link>/blog/2021/missing-serial-scsi-disk-by-id/</link>
      <pubDate>Wed, 05 May 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/missing-serial-scsi-disk-by-id/</guid>
      <description>When you have a lot of storage devices, it&#39;s best practice to assign them to raid arrays or ZFS pools by something identifiable. And preferably something that&#39;s also readable when outside a computer. Commonly: the disk manufacturer and the serial number.
Usually, both the disk manufacturer and the disk serial number are printed on a small label on the disk. So, if you&#39;re in the data center replacing a disk, one glance is sufficient to know you got the correct disk.</description>
    </item>
      
    <item>
      <title>smtp_domain / gitlab configuration</title>
      <link>/blog/2021/smtp-domain-gitlab-configuration/</link>
      <pubDate>Thu, 29 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/smtp-domain-gitlab-configuration/</guid>
      <description>What is the smtp_domain in the GitLab configuration? There is also a smtp_address and smtp_user_name; so what would you put in the &amp;ldquo;domain&amp;rdquo; field?
Contrary to what the examples on GitLab Omnibus SMTP lead you to believe: smtp_domain is the HELO/EHLO domain; i.e. your hostname.
RFC 5321 has this to say about the HELO/EHLO parameter:
 o The domain name given in the EHLO command MUST be either a primary host name (a domain name that resolves to an address RR) or, if the host has no name, an address literal, as described in Section 4.</description>
    </item>
      
    <item>
      <title>yubico otp / pam / openvpn</title>
      <link>/blog/2021/yubico-otp-pam-openvpn/</link>
      <pubDate>Mon, 26 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/yubico-otp-pam-openvpn/</guid>
      <description>Quick notes on setting up pam_yubico.so with OpenVPN.
Add to OpenVPN server config:
plugin /usr/lib/x86_64-linux-gnu/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn # Use a generated token instead of user/password for up # to 16 hours, so you&#39;ll need to re-enter your otp daily. auth-gen-token 57600 Sign up at https://upgrade.yubico.com/getapikey/. It&#39;s really quick. Store client_id and secret (or id and key respectively). You&#39;ll need them in the config below.
Get PAM module:
# apt-get install --no-install-recommends libpam-yubico Create /etc/pam.</description>
    </item>
      
    <item>
      <title>proxmox / virtio-blk / disk by-id</title>
      <link>/blog/2021/proxmox-virtio-blk-disk-by-id/</link>
      <pubDate>Thu, 08 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/proxmox-virtio-blk-disk-by-id/</guid>
      <description>Why does the virtio-blk /dev/vda block device not show up in /dev/disk/by-id?
Yesterday, I wrote about how Proxmox VE attaches scsi0 and virtio0 block devices differently. That is the starting point for todays question: how come do I get /dev/sda in /dev/disk/by-id while /dev/vda is nowhere to be found?
This question is relevant if you&#39;re used to referencing disks through /dev/disk/by-id (for example when setting up ZFS, using the device identifiers).</description>
    </item>
      
    <item>
      <title>proxmox / alter default create vm parameters</title>
      <link>/blog/2021/proxmox-alter-default-create-vm-parameters/</link>
      <pubDate>Wed, 07 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/proxmox-alter-default-create-vm-parameters/</guid>
      <description>The Proxmox Virtual Environment has defaults when creating a new VM, but it has no option to change those defaults. Here&#39;s a quick example of hacking in some defaults.
Why? (Changing SCSI controller does not change existing disks) In the next post I wanted to talk about /dev/disk/by-id and why disks that use the VirtIO SCSI controller do not show up there. A confusing matter in this situation was that creating a VM disk using a different SCSI controller and then switching does not change the storage driver for the existing disks completely!</description>
    </item>
      
    <item>
      <title>openvpn / hardened fox-it openvpn-nl</title>
      <link>/blog/2021/openvpn-hardened-fox-it-openvpn-nl/</link>
      <pubDate>Thu, 21 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/openvpn-hardened-fox-it-openvpn-nl/</guid>
      <description>Today, we will be evaluating OpenVPN-NL &amp;mdash; &amp;ldquo;[a] hardened version of OpenVPN that includes as many of the security measures required to operate in a classified environment as possible &amp;mdash; and whether we can use it as a drop-in replacement for regular OpenVPN.
While OpenVPN allows many insecure configurations, such as turning off encryption, or the use of outdated cryptographic functions in security critical places, the goal of OpenVPN-NL &amp;mdash; a fork created and maintained by Fox-IT &amp;mdash; is to strip insecure configuration and verify that the distributed version is uncompromised.</description>
    </item>
      
    <item>
      <title>postgresql inside kubernetes / no space left on device</title>
      <link>/blog/2021/postgresql-inside-kubernetes-no-space-left-on-device/</link>
      <pubDate>Fri, 15 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/postgresql-inside-kubernetes-no-space-left-on-device/</guid>
      <description>Running PostgreSQL inside Kubernetes? Getting occasional &amp;quot;No space left on device&amp;quot; errors? Know that 64MB is not enough for everyone.
With the advent of more services running inside Kubernetes, we&#39;re now running into new issues and complexities specific to the containerization. For instance, to solve the problem of regular file backups of distributed filesystems, we&#39;ve resorted to using rsync wrapped inside a pod (or sidecar). And now for containerized PostgreSQL, we&#39;re running into an artificial memory limit that needs fixing.</description>
    </item>
      
    <item>
      <title>chromium snap / wrong fonts</title>
      <link>/blog/2021/chromium-snap-wrong-fonts/</link>
      <pubDate>Tue, 05 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/chromium-snap-wrong-fonts/</guid>
      <description>So, since a couple of weeks my snap-installed Chromium browser on Ubuntu Focal started acting up: suddenly it chooses the wrong fonts on some web pages. The chosen fonts are from the ~/.local/share/fonts/ directory.
Look! That&#39;s not the correct font. And it&#39;s even more apparent that the font is off when seeing the source view.
Bah. That&#39;s not even a monospaced font.
A fix that appeared to work &amp;mdash; but unfortunately only temporarily &amp;mdash; involves temporarily moving the custom local fonts out of the way and then flushing the font cache:</description>
    </item>
      
    <item>
      <title>stale apparmor config / mysql refuses to start</title>
      <link>/blog/2021/stale-apparmor-config-mysql-refuses-to-start/</link>
      <pubDate>Sat, 02 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/stale-apparmor-config-mysql-refuses-to-start/</guid>
      <description>So, recently we had an issue with a MariaDB server that refused to start. Or, actually, it would start, but before long, SystemD would kill it. But why?
# systemctl start mariadb.service Job for mariadb.service failed because a timeout was exceeded. See &amp;#34;systemctl status mariadb.service&amp;#34; and &amp;#34;journalctl -xe&amp;#34; for details. After 90 seconds, it would be killed. systemctl status mariadb.service shows the immediate cause:
# systemctl status mariadb.service ... systemd[1]: mariadb.</description>
    </item>
      
    <item>
      <title>zfs / zvol / partition does not show up</title>
      <link>/blog/2021/zfs-zvol-partition-does-not-show-up/</link>
      <pubDate>Fri, 01 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>/blog/2021/zfs-zvol-partition-does-not-show-up/</guid>
      <description>On our Proxmox virtual machine I had to go into a volume to quickly fix an IP address. The volume exists on the VM host, so surely mounting is easy. Right?
I checked in /dev/zvol/pve2-pool/ where I found the disk:
# ls /dev/zvol/pve2-pool/vm-125-virtio0* total 0 lrwxrwxrwx 1 root root 10 Dec 29 15:55 vm-125-virtio0 -&amp;gt; ../../zd48 Good, there&#39;s a disk:
# fdisk -l /dev/zd48 Disk /dev/zd48: 50 GiB, 53687091200 bytes, 104857600 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 8192 bytes I/O size (minimum/optimal): 8192 bytes / 8192 bytes Disklabel type: dos Disk identifier: 0x000aec27 Device Boot Start End Sectors Size Id Type /dev/zd48p1 * 2048 97656831 97654784 46.</description>
    </item>
      
    <item>
      <title>recap 2020</title>
      <link>/blog/2020/recap2020/</link>
      <pubDate>Wed, 16 Dec 2020 12:50:01 +0100</pubDate>
      
      <guid>/blog/2020/recap2020/</guid>
      <description>(I&amp;rsquo;m sorry, this time the recap is in Dutch instead of English. If you&amp;rsquo;re reading this, you&amp;rsquo;re probably Dutch anyway, so it won&amp;rsquo;t be a problem.)
COVID-jaar 2020 is een vreemd jaar geweest, maar voor OSSO was het ook een goed jaar. Waar 2020 nog in mineur begon, omdat we eind 2019 nog een dierbare collega verloren aan een emigratiewens naar het land van de kangoeroes, hebben we in 2020 twee nieuwe collega&amp;rsquo;s mogen verwelkomen.</description>
    </item>
      
    <item>
      <title>zfs destroy / dataset is busy</title>
      <link>/blog/2020/zfs-destroy-dataset-is-busy/</link>
      <pubDate>Fri, 11 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/zfs-destroy-dataset-is-busy/</guid>
      <description>Just now, I tried to remove a ZFS dataset, and it reported dataset is busy for no apparent reason.
# zfs list -r data NAME USED AVAIL REFER MOUNTPOINT data 3.12T 405G 251M /data data/kubernetes-logging 2.08T 405G 2.08T /data/kubernetes/logging data/rook-config 36.5M 405G 36.5M /data/rook-config data/rook-data 1.03T 708G 753G - # zfs destroy data/kubernetes-logging cannot destroy &amp;#39;data/kubernetes-logging&amp;#39;: dataset is busy The usual suspects were checked:
 The dataset was not mounted (cat /proc/mounts | grep kubernetes).</description>
    </item>
      
    <item>
      <title>cumulus / postfix in the right vrf</title>
      <link>/blog/2020/cumulus-postfix-in-the-right-vrf/</link>
      <pubDate>Tue, 27 Oct 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/cumulus-postfix-in-the-right-vrf/</guid>
      <description>Cumulus Linux is a network operating system. It is a switch, but it also runs Linux OS, allowing us to run our automation tools on it. We use it to automate the configuration of our network. A network where we use VRF (virtual routing and forwarding) to separate customer traffic. The presence of VRFs in the OS however means that we have to tell the daemons in which VRF to run.</description>
    </item>
      
    <item>
      <title>offsite / on-the-fly encrypted backups / gocryptfs</title>
      <link>/blog/2020/offsite-on-the-fly-encrypted-backups-gocryptfs/</link>
      <pubDate>Fri, 23 Oct 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/offsite-on-the-fly-encrypted-backups-gocryptfs/</guid>
      <description>Earlier, I wrote about using encfs to do on-the-fly encrypted backups (using encfs). The idea was that you grant ssh+rsync access to a backup system, but that that system does not know what it is backing up. This provides a layer of security between your backup provider and your private data.
That scheme works like this:
 there is a remote system doing periodic incremental rsync backups, like a PlanB Backup server; you grant ssh+rsync access to that system; but only to a specific path; on that path, you mount an encrypted view of your filesystem — a.</description>
    </item>
      
    <item>
      <title>pgp on yubikey / refresh expiry</title>
      <link>/blog/2020/pgp-on-yubikey-refresh-expiry/</link>
      <pubDate>Tue, 13 Oct 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/pgp-on-yubikey-refresh-expiry/</guid>
      <description>Generally, I try to follow security best practices. This means that I have my PGP signing, authentication and encryption keys on my YubiKey, and I have configured the keys to expire after a year. Unfortunately, refreshing the expiry every year is not quite enough to store how to do that into muscle memory. Here are the steps relevant to my use case.
Putting the keys on the YubiKey in the first place is worth a post of its own.</description>
    </item>
      
    <item>
      <title>tls / testing certificate chains / easycert</title>
      <link>/blog/2020/tls-testing-certificate-chains-easycert/</link>
      <pubDate>Thu, 10 Sep 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/tls-testing-certificate-chains-easycert/</guid>
      <description>The openssl client is a very versatile tool, but also a bit cryptic. The easycert utility from the ossobv/vcutil scripts makes validating/managing certificates easier.
easycert from ossobv/vcutil has a few modes of operation: CLI, CGI, generating certificates and testing certificates. Nowadays we mostly use the testing mode: -T
The utility is a convenient wrapper around openssl s_client and x509 calls. Get it from github.com/ossobv/vcutil easycert.
Usage Run it like this:</description>
    </item>
      
    <item>
      <title>excel / generate sheet password collision</title>
      <link>/blog/2020/excel-generate-sheet-password-collision/</link>
      <pubDate>Wed, 09 Sep 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/excel-generate-sheet-password-collision/</guid>
      <description>Yesterday, I demonstrated how to brute force the Excel protected sheet/cells password. (Write protection! Not read protection a.k.a. encryption!) Today, I figured there must be a faster way, as the hash is not at all complicated.
After fiddling around a little, I hacked together this bit of Python:
def reverse_f(wanted): &amp;#34;Calculate Excel protected sheet password&amp;#34; # https://wjd.nu/notes/2020#excel-generate-sheet-password-collision # https://wjd.nu/notes/2020#libreoffice-asking-for-cell-password-brute-force def reverse_rotate(v): &amp;#34;Right shift by one, rotating the right most bit to bit 15&amp;#34; if v &amp;amp; 0x1: return (v &amp;gt;&amp;gt; 1) | 0x4000 return v &amp;gt;&amp;gt; 1 chars = [] valid_tokens = tuple([ord(i) for i in ( &amp;#39;ABCDEFGHIJKLMNOPQRSTUVWXYZ&amp;#39; &amp;#39;abcdefghijklmnopqrstuvwxyz&amp;#39; &amp;#39;0123456789&amp;#39;)]) # Length 9 should be enough to go down from 16 to 7 bits: # we skip some shorter solutions, but there are only a few hashes # that benefit from that.</description>
    </item>
      
    <item>
      <title>libreoffice / asking for cell password / brute force</title>
      <link>/blog/2020/libreoffice-asking-for-cell-password-brute-force/</link>
      <pubDate>Tue, 08 Sep 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/libreoffice-asking-for-cell-password-brute-force/</guid>
      <description>While we were editing a provider-supplied Excel document using LibreOffice, at seemingly random times, it would show a popup asking us for a password to a cell. This popup would only go away if we set a new (non-blank) password on it. Annoying!
Apparently, it has to do with Sheet and Cell protection whereby an editing user is disallowed to edit certain cells/rows/sheets in a document.
Having certain cells marked read-only, sure.</description>
    </item>
      
    <item>
      <title>docker unprivileged user / becoming root</title>
      <link>/blog/2020/docker-unprivileged-user-becoming-root/</link>
      <pubDate>Fri, 03 Jul 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/docker-unprivileged-user-becoming-root/</guid>
      <description>My colleague was rightly annoyed that our USER www-data docker images greatly hindered effective debugging. Can we become root again, while still keeping the additional secure-by-default non-root images?
If we have enough permissions on the filesystem, then: yes, we can.
Take the following example, where we&amp;rsquo;ll be looking at a myproject pod. (You can skip the Kubernetes steps if you already know where the Docker instance resides.)
$ kubectl get pods -o wide myproject-66dd6b4dd-jskgf NAME READY STATUS AGE IP NODE myproject-66dd6b4dd-jskgf 1/1 Running 64d 10.</description>
    </item>
      
    <item>
      <title>nss-dns4only / libc / disable AAAA lookups</title>
      <link>/blog/2020/nss-dns4only-libc-disable-aaaa-lookups/</link>
      <pubDate>Mon, 25 May 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/nss-dns4only-libc-disable-aaaa-lookups/</guid>
      <description>Have you ever noticed how some applications can do AAAA DNS record lookups even though the host has no IPv6 connectivity? That means double DNS lookups for zero profit. Why is that? And how can you disable it?
Problem To make a long story short, a common combination of circumstances can cause useless gratuitous AAAA lookups:
 Applications that are IPv6 ready (or applications that don&#39;t care); on hosts using libc; where IPv6 is enabled (net.</description>
    </item>
      
    <item>
      <title>gitlab / securing public repositories</title>
      <link>/blog/2020/gitlab-securing-public-repositories/</link>
      <pubDate>Sun, 24 May 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/gitlab-securing-public-repositories/</guid>
      <description>In the past, GitLab repositories were created with Public Visibility by default. Now they have a more sensible security setting. Still, it can be nice to assert that public repositories are not Public-by-Accident.
How? Well, one fix is to check that Public repositories are in a whitelisted public namespace (e.g. /public/). That way it&amp;rsquo;s immediately obvious that the repositories herein are visible to everyone.
Use a Private browser and go to: https://YOUR_GITLAB_INSTANCE/explore/projects</description>
    </item>
      
    <item>
      <title>more or less useless tips and tricks 3</title>
      <link>/blog/2020/more-or-less-useless-tips-and-tricks-3/</link>
      <pubDate>Sat, 23 May 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/more-or-less-useless-tips-and-tricks-3/</guid>
      <description>More or less useless/useful tips and tricks, bundled together. They weren&amp;rsquo;t worthy of a box div on their own. I gave them only a li each.
  gsettings set org.gnome.desktop.calendar show-weekdate true — to enable week numbers in the gnome-shell datetime calendar popup. (You may need to set LC_TIME to en_GB so the week starts on a Monday instead of, American style, on a Sunday. You&amp;rsquo;ll probably have set LC_PAPER too already, to get A4 paper size printing defaults.</description>
    </item>
      
    <item>
      <title>encryption decryption speed / gnupg / openssl</title>
      <link>/blog/2020/encryption-decryption-speed-gnupg-openssl/</link>
      <pubDate>Wed, 13 May 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/encryption-decryption-speed-gnupg-openssl/</guid>
      <description>We were looking at encryption ingredients the other day. Because, if we want to compare encryption methods, we shouldn&amp;rsquo;t compare apples and oranges. With that newfound knowledge, we can run a few speed tests.
The aggregated data (raw data sources can be found below):
EncryptionDecryption user (ms)sys (ms)total (ms)mem (10K) user (ms)sys (ms)total (ms)mem (10K) gpg 1.4 76453547999354 1573832216060359 gpg 2.2 28633403203507 62123406552515 gpg 2.3* 27522813033527 44943184812536 gpg 2.3* nohw 45082814789 52575473187865537 openssl 17543392093 506421391812506 openssl nohw 35643443908504 27653963161507 customcrypt 333842137592458 356543540002461   First a few notes about the graph:</description>
    </item>
      
    <item>
      <title>encryption / vocabulary / long term storage</title>
      <link>/blog/2020/encryption-vocabulary-long-term-storage/</link>
      <pubDate>Fri, 01 May 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/encryption-vocabulary-long-term-storage/</guid>
      <description>While investigating the most appropriate encryption cipher and format, I realised I didn&amp;rsquo;t have enough vocabulary on the subject. This post aims to close that knowledge gap somewhat.
I&amp;rsquo;m looking at symmetric ciphers here, as they are used when storing lots of data. (In fact, when encrypting larger amounts of data, public/private key encryption (an asymmetric cipher) is only used to encrypt a separate key for the symmetric cipher, which is then used for bulk of the data.</description>
    </item>
      
    <item>
      <title>saltstack / printf IO-error / debianutils / which</title>
      <link>/blog/2020/saltstack-printf-io-error-debianutils-which/</link>
      <pubDate>Wed, 29 Apr 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/saltstack-printf-io-error-debianutils-which/</guid>
      <description>After some upgrades, I suddenly noticed unexpected sh: printf: I/O error output. Some debugging later, it turns out that it&#39;s the Dash way of informing us of a PIPE error. Apparently salt&#39;s cmd.run can cause so little output buffering, that the debianutils which command can be aborted mid-output.
Not-broken example:
$ which python3 python false | head -n1 /usr/bin/python3 Broken example, through a salt cmd.run call:
$ salt &#39;example.com&#39; cmd.run &#39;which python3 python false | head -n1&#39; example.</description>
    </item>
      
    <item>
      <title>supermicro / java / console redirection / kvm</title>
      <link>/blog/2020/supermicro-java-console-redirection-kvm/</link>
      <pubDate>Wed, 12 Feb 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/supermicro-java-console-redirection-kvm/</guid>
      <description>Connecting to the new SuperMicro iKVM management interfaces requires a working Java in your browser (IcedTea browser plugin). It will launch a Java Web Start (javaws) application. And java plugins (and needless web forms) are a pain in the behind. Is there a better way?
Obviously, running from the web interface just means downloading a Java application, and running it locally. So why can&amp;rsquo;t we do that directly, and skip the IcedTea Java browser plugins?</description>
    </item>
      
    <item>
      <title>openssl / sign / subject alternative names</title>
      <link>/blog/2020/openssl-sign-subject-alternative-names/</link>
      <pubDate>Fri, 31 Jan 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/openssl-sign-subject-alternative-names/</guid>
      <description>Recently, an automated job of mine failed because the latest and greatest Python refused to validate an SSL certificate with 127.0.0.1 in the common name (CN).
Apparently CN=127.0.0.1 will not be accepted anymore, as using the common name for hostname validation has been deprecated for ages now.
The fix? Use subject alternative names (SANs).
Generally, you&amp;rsquo;ll already have these when you have your certificates signed by somebody else. But if you&amp;rsquo;re signing certificates yourself, you&amp;rsquo;ll need to know how to pass them to openssl:</description>
    </item>
      
    <item>
      <title>3cx voip / letsencrypt tls</title>
      <link>/blog/2020/3cx-voip-letsencrypt-tls/</link>
      <pubDate>Thu, 30 Jan 2020 00:00:00 +0000</pubDate>
      
      <guid>/blog/2020/3cx-voip-letsencrypt-tls/</guid>
      <description>Can you get your 3CX Phone System to connect to your SIP provider Trunk over TLS, when the server uses a Let&amp;rsquo;s Encrypt certificate?
3CX documentation on this topic is scarce. There are posts like 3CX Forum: SIP TLS:
 It&amp;rsquo;s fairly straightforward: Your provider must give you a TLS Root Certificate (.pem) so you can encrypt the traffic. If they have SRV records the system will automatically know where to connect for TLS mode (Auto Discovery option on General trunk tab), or the provider might just tell you to change your port to the one they are listening to for TLS connections.</description>
    </item>
      
    <item>
      <title>recap2019</title>
      <link>/blog/2019/recap2019/</link>
      <pubDate>Thu, 19 Dec 2019 13:28:57 +0000</pubDate>
      
      <guid>/blog/2019/recap2019/</guid>
      <description>(ﾉ◕ヮ◕)ﾉ*:･ﾟ✧ ✧ﾟ･: *ヽ(◕ヮ◕ヽ)
2019 highlights  We are looking for new colleagues! The new website is finally up! Built a Cumulus network with automated deployment using Ansible and Netbox as the source of truth. Managed kubernetes has become a staple. Extended our ISO27001:2017 and NEN7510:2017 certifications. Visited Legoland as a team building exercise. Many improvements! Ronald may actually leave for australia, like for real, not kidding, probably, if they finally let him in, in the not too distant future.</description>
    </item>
      
    <item>
      <title>pgloader import / mysql to postgresql</title>
      <link>/blog/2019/pgloader-import-mysql-to-postgresql/</link>
      <pubDate>Fri, 20 Sep 2019 00:00:00 +0000</pubDate>
      
      <guid>/blog/2019/pgloader-import-mysql-to-postgresql/</guid>
      <description>When loading old (Django) projects in K8S, we&#39;ve decided to give PostgreSQL a go as default database. Here are some notes that aid in importing.
 After looking around, pgloader seems to be the right tool for the job. Feature and stability wise it beats any other solution. And it&#39;s available on recent Debian/Ubuntu. We need access to the remote PostgreSQL db; because pgloader will not provide an SQL dump (for reasons).</description>
    </item>
      
    <item>
      <title>asterisk pbx / generated doxygen docs</title>
      <link>/blog/2019/asterisk-pbx-generated-doxygen-docs/</link>
      <pubDate>Wed, 04 Sep 2019 00:00:00 +0000</pubDate>
      
      <guid>/blog/2019/asterisk-pbx-generated-doxygen-docs/</guid>
      <description>On the Asterisk PBX Development page you&#39;ll find a reference to Doxygen generated documentation:
 Most of the documentation related to the source code is embedded in the source files and is processed with Doxygen. The latest version of the Doxygen generated source documentation can be found on http://doxygen.asterisk.org.
 However, it cannot be found there, as that URL has been returning a 503 Service Unavailable for quite some time now.</description>
    </item>
      
    <item>
      <title>recap2018</title>
      <link>/blog/2018/recap2018/</link>
      <pubDate>Mon, 10 Dec 2018 10:08:57 +0000</pubDate>
      
      <guid>/blog/2018/recap2018/</guid>
      <description>(ﾉ◕ヮ◕)ﾉ*:･ﾟ✧ ✧ﾟ･: *ヽ(◕ヮ◕ヽ)
2018 highlights  Edgar joined our team Managed kubernetes moving forward  Many awesome upstream kubernetes releases Keeping up integrating improvements in our default kubernetes &amp;ldquo;distribution&amp;rdquo; Further expanding our managed kubernetes install base   Updated NEN7510:2011 to NEN7510:2017 ISO27001 ISMS improvements and further integrating customer scope New website coming up - bijna klaar TM.  </description>
    </item>
      
    <item>
      <title>gbp buildpackage / gpg2</title>
      <link>/blog/2018/gbp-buildpackage-gpg2/</link>
      <pubDate>Thu, 08 Nov 2018 00:00:00 +0000</pubDate>
      
      <guid>/blog/2018/gbp-buildpackage-gpg2/</guid>
      <description>If you prefer gpg2 over gpg, building a debian package with debuild or gbp buildpackage may require some fiddling.
In my case, I&amp;rsquo;m using gpg2 instead of gpg for signing because unlike version 1, version 2 does PGP key forwarding. That way I can sign on a remote machine, using a local PGP key card.
However gbp buildpackage, dpkg-buildpackage and debuild are hardwired to call gpg. And — it turns out — using a simple /usr/local/bin/gpg to /usr/bin/gpg2 symlink was not sufficient to convince gbp (and debuild) to use the gpg2 binary, while for dpkg-buildpackage that is sufficient.</description>
    </item>
      
    <item>
      <title>kubectl / broken terminal / ipython</title>
      <link>/blog/2018/kubectl-broken-terminal-ipython/</link>
      <pubDate>Thu, 20 Sep 2018 00:00:00 +0000</pubDate>
      
      <guid>/blog/2018/kubectl-broken-terminal-ipython/</guid>
      <description>Just now I ran into an IPython interpreter inside a Docker container inside Kubernetes misbehaving:
After starting ipython inside a kubectl for a second time, IPython wouldn&amp;rsquo;t show the input prompt. It only showed the output prompt.
Turns out it was due to the terminal settings. For some reasons, after logging out of kubectl exec, the next exec would get 0 rows and 0 columns; as if someone had run stty rows 0 on the terminal.</description>
    </item>
      
    <item>
      <title>vimrc / debian stretch</title>
      <link>/blog/2018/vimrc-debian-stretch/</link>
      <pubDate>Wed, 19 Sep 2018 00:00:00 +0000</pubDate>
      
      <guid>/blog/2018/vimrc-debian-stretch/</guid>
      <description>In Debian/Stretch, the default ViM settings have been changed — for the worse, in my opinion.
However, undoing the bad settings is not a matter of fixing them in your ~/.vimrc, because when that file is detected no defaults at all are set.
The quick fix is to create a custom /etc/vim/vimrc.local file with the following settings:
&amp;quot; Instead of auto-sourcing this afterwards, source it now. source $VIMRUNTIME/defaults.vim let g:skip_defaults_vim = 1 &amp;quot; Now we undo the &amp;quot;wrong&amp;quot; settings.</description>
    </item>
      
    <item>
      <title>core file / docker image / auplink</title>
      <link>/blog/2018/core-file-docker-image-auplink/</link>
      <pubDate>Tue, 18 Sep 2018 00:00:00 +0000</pubDate>
      
      <guid>/blog/2018/core-file-docker-image-auplink/</guid>
      <description>A while, I&amp;rsquo;ve been looking at a stray /core file in some of our daily Xenial Docker images. Time to find out where it comes from.
Tracing with a few well placed RUN ls -l /core || true, tells us that the dump appeared after a large RUN statement and not during one.
Running gdb on the core revealed that it was a dump of auplink, a part of Docker. Opening the core on a Xenial machine with docker installed, showed the following backtrace:</description>
    </item>
      
    <item>
      <title>ubuntu bionic / crashing gdm / eglgetdisplay</title>
      <link>/blog/2018/ubuntu-bionic-crashing-gdm-eglgetdisplay/</link>
      <pubDate>Wed, 11 Apr 2018 00:00:00 +0000</pubDate>
      
      <guid>/blog/2018/ubuntu-bionic-crashing-gdm-eglgetdisplay/</guid>
      <description>After upgrading from Ubuntu 17.10 to Ubuntu 18.04, and rebooting, the GNOME Display Manager (gdm) went into a restart loop. No promised speed gains. Instead, I got an unusable desktop.
Being quick with CTRL+ALT+F3, I could enter my username and password in the text console after a couple attempts — the gdm restart would continuously steal console/tty focus — after which a sudo systemctl stop gdm was possible. This left me with a shell and plenty of time to examine the situation.</description>
    </item>
      
    <item>
      <title>checking client ssl certificate / from python</title>
      <link>/blog/2018/checking-client-ssl-certificate-from-python/</link>
      <pubDate>Mon, 26 Mar 2018 00:00:00 +0000</pubDate>
      
      <guid>/blog/2018/checking-client-ssl-certificate-from-python/</guid>
      <description>A quick howto on checking SSL/TLS client certificates from Django/Python.
Generally, when you want to use client certificates, you&amp;rsquo;ll let the HTTPS server (e.g. NGINX) do the certificate validation.
For NGINX you&amp;rsquo;d add this config, and be done with it.
# TLS server certificate config: ... # TLS client certificate config: ssl_verify_client on; # or &#39;optional&#39; ssl_client_certificate /PATH/TO/my-ca.crt; ... location ... { ... # $ssl_client_s_dn contains: &amp;quot;/C=.../O=.../CN=...&amp;quot;, where you&#39;re # generally interested in the CN-part (commonName) to identify the # &amp;quot;who&amp;quot;.</description>
    </item>
      
    <item>
      <title>docker application placement / paths</title>
      <link>/blog/2018/docker-application-placement-paths/</link>
      <pubDate>Wed, 14 Feb 2018 00:00:00 +0000</pubDate>
      
      <guid>/blog/2018/docker-application-placement-paths/</guid>
      <description>Where do you place the application inside the Docker image?
In the past, when deploying Python/Django projects, we&amp;rsquo;d put them in /srv/django-projects/APPNAME on a (possibly shared) machine. The python-virtualenv that came with it, went into /srv/virtualenvs/APPNAME.
Now that we&amp;rsquo;re dockerizing many projects, we don&amp;rsquo;t need the virtualenv (there is only one environment) and we don&amp;rsquo;t need the APPNAME either (there is only one application). So, where should we place the project?</description>
    </item>
      
    <item>
      <title>ubuntu / goodbye unity / welcome gnome-shell</title>
      <link>/blog/2018/ubuntu-goodbye-unity-welcome-gnome-shell/</link>
      <pubDate>Thu, 01 Feb 2018 00:00:00 +0000</pubDate>
      
      <guid>/blog/2018/ubuntu-goodbye-unity-welcome-gnome-shell/</guid>
      <description>After having gotten used to Unity on the Ubuntu desktop, with Ubuntu Artful it is time to say goodbye. When Ubuntu first added the Unity shell with just the sidebar with big buttons, in favor of the more traditional GNOME with its Windows 95 style interface, many were skeptical, me included. But removing the clutter was good, and I&#39;ve happily worked with it for years. And you really don&#39;t want to waste time tweaking your desktop away from the OS provided defaults.</description>
    </item>
      
    <item>
      <title>screen / wipes copy buffer</title>
      <link>/blog/2018/screen-wipes-copy-buffer/</link>
      <pubDate>Wed, 10 Jan 2018 00:00:00 +0000</pubDate>
      
      <guid>/blog/2018/screen-wipes-copy-buffer/</guid>
      <description>A mismash of bugs and workarounds causes the copy buffer (X selection) to get wiped some of the time in my recent desktop environment. And that in a seemingly unpredictable manner.
The following bug is mostly in play: GNOME VTE soft reset wipes selection
That bug causes:
 reset(1) to wipe the middle-mouse (primary) buffer (although this differs per system — could not put my finger on this); reset(1) to wipe the clipboard buffer, but only if the reset was called from window that originated the current clipboard buffer contents; GNU screen(1) initialization to misbehave as reset does, as described above — even through an ssh session — by wiping the buffer, if TERM=xterm-256color.</description>
    </item>
      
    <item>
      <title>dovecot / roundcube / mail read error</title>
      <link>/blog/2018/dovecot-roundcube-mail-read-error/</link>
      <pubDate>Mon, 08 Jan 2018 00:00:00 +0000</pubDate>
      
      <guid>/blog/2018/dovecot-roundcube-mail-read-error/</guid>
      <description>Today we ran into a dovecot/imap crash on a Xenial box. The Dovecot in question was the patched dovecot-2.2.22.
Due to an as of yet unexplained cause, reading mail through Thunderbird mail client worked fine, but when opening a message with Roundcube (webmail), most messages would give an odd error about a &amp;ldquo;message that could not be opened&amp;rdquo;.
An IMAP trace of Roundcube revealed that the IMAP server stopped responding after the client A0004 UID FETCH command.</description>
    </item>
      
    <item>
      <title>Meltdown &amp; Spectre attacks</title>
      <link>/blog/2018/meltdown-spectre-attacks/</link>
      <pubDate>Thu, 04 Jan 2018 11:06:33 +0000</pubDate>
      
      <guid>/blog/2018/meltdown-spectre-attacks/</guid>
      <description>Information regarding Meltdown and Spectre attacks.
Current state  Waiting for software patch availability. Patched ubuntu kernels are available for testing.  Updates:  20180104: Created blogpost 20180105: Added new information/links 20180105: Status update 20180108: Added information from Redhat about performance impact from patches. 20180108: Updated links list. 20180108: Status update  Links  https://spectreattack.com / https://meltdownattack.com (same site) https://arstechnica.com/gadgets/2018/01/meltdown-and-spectre-every-modern-processor-has-unfixable-security-flaws/ https://arstechnica.com/gadgets/2018/01/meltdown-and-spectre-heres-what-intel-apple-microsoft-others-are-doing-about-it/ https://wiki.ubuntu.com/SecurityTeam/KnowledgeBase/SpectreAndMeltdown https://www.raspberrypi.org/blog/why-raspberry-pi-isnt-vulnerable-to-spectre-or-meltdown/  High level description CVE&amp;rsquo;s  Spectre - CVE-2017-5715 Spectre - CVE-2017-5753 Meltdown - CVE-2017-5754  As described on: https://spectreattack.</description>
    </item>
      
    <item>
      <title>Recap 2017 </title>
      <link>/blog/2017/recap-2017/</link>
      <pubDate>Thu, 21 Dec 2017 15:25:12 +0000</pubDate>
      
      <guid>/blog/2017/recap-2017/</guid>
      <description>2017  ISO27001 certified + NEN7510 Ewout joined our team as an SRE More projects opensourced at github: https://github.com/ossobv Uradesign designed logo&amp;rsquo;s for several of our open source projects Started providing Kubernetes as a Service / Managed Kubernetes Lots of interesting stuff  </description>
    </item>
      
    <item>
      <title>Hosting</title>
      <link>/hosting/</link>
      <pubDate>Tue, 12 Dec 2017 11:22:22 +0100</pubDate>
      
      <guid>/hosting/</guid>
      <description></description>
    </item>
      
    <item>
      <title>Kubernetes</title>
      <link>/kubernetes/</link>
      <pubDate>Tue, 12 Dec 2017 11:22:22 +0100</pubDate>
      
      <guid>/kubernetes/</guid>
      <description>OSSO provides managed kubernetes clusters including full operational support.
Compared to public cloud providers You should run your workload where it makes sense. Be it from a cost perspective, technical criteria, security requirements, or level of available support.
At OSSO, we focus on our strong points and where we can provide the most value.
Where we differ from the public cloud providers:
High reliability OSSO manages the full infrastructure stack. It provides us with full insight and control.</description>
    </item>
      
    <item>
      <title>Open Source</title>
      <link>/open-source/</link>
      <pubDate>Tue, 12 Dec 2017 11:22:22 +0100</pubDate>
      
      <guid>/open-source/</guid>
      <description></description>
    </item>
      
    <item>
      <title>Operations</title>
      <link>/operations/</link>
      <pubDate>Tue, 12 Dec 2017 11:10:20 +0100</pubDate>
      
      <guid>/operations/</guid>
      <description></description>
    </item>
      
    <item>
      <title>About</title>
      <link>/about/</link>
      <pubDate>Tue, 12 Dec 2017 11:07:30 +0100</pubDate>
      
      <guid>/about/</guid>
      <description></description>
    </item>
      
    <item>
      <title>flake8 / vim / python2 / python3</title>
      <link>/blog/2017/flake8-vim-python2-python3/</link>
      <pubDate>Sun, 03 Dec 2017 00:00:00 +0000</pubDate>
      
      <guid>/blog/2017/flake8-vim-python2-python3/</guid>
      <description>In 2015, I wrote a quick recipe to use Vim F7-key flake8 checking for both python2 and python3 using the nvie/vim-flake8 Vim plugin.
Here&#39;s a quick update that works today. Tested on Ubuntu/Zesty.
$ sudo apt-get install python3-flake8 # py3 version, no cli $ sudo pip -H install python-flake8 # py2 version, with cli $ sudo cp /usr/local/bin/flake8{,.2} # copy to flake8.2 $ sudo sed -i -e &amp;#39;s/python$/python3/&amp;#39; /usr/local/bin/flake8 # update shebang $ sudo mv /usr/local/bin/flake8{,.</description>
    </item>
      
    <item>
      <title>Availability during holiday December 2017</title>
      <link>/blog/2017/availability-during-holiday-december-2017/</link>
      <pubDate>Fri, 01 Dec 2017 08:30:37 +0000</pubDate>
      
      <guid>/blog/2017/availability-during-holiday-december-2017/</guid>
      <description>Starting the 16th of December we are on leave. We return to the office on the 2nd of January. During this period we are available 24/7 for incident response and other urgent matters as usual.
If you already know of any urgent requests which needs to be handled during this period, please inform us in advance so we can plan the required availability.</description>
    </item>
      
    <item>
      <title>reprepro / multiversion / build recipe</title>
      <link>/blog/2017/reprepro-multiversion-build-recipe/</link>
      <pubDate>Thu, 30 Nov 2017 00:00:00 +0000</pubDate>
      
      <guid>/blog/2017/reprepro-multiversion-build-recipe/</guid>
      <description>We used to use reprepro (4.17) to manage our package repository. However, it did not support serving multiple versions of the same package. The Benjamin Drung version from GitHub/profitbricks/reprepro does. Here&amp;rsquo;s our recipe to build it.
$ git clone -b 5.1.1-multiple-versions https://github.com/profitbricks/reprepro.git $ cd reprepro It lacks a couple of tags, so we&amp;rsquo;ll add some lightweight ones.
$ git tag 4.17.1 2d93fa35dd917077e9248c7e564648da3a5f1fe3 &amp;amp;&amp;amp; git tag 4.17.1-1 0c9f0f44a84f67ee5f14bccf6507540d4f7f8e39 &amp;amp;&amp;amp; git tag 5.</description>
    </item>
      
    <item>
      <title>Maintenance network Mediacentrale Nov 1st 2017 - 22:00</title>
      <link>/blog/2017/maintenance-network-mediacentrale-nov-1st-2017-2200/</link>
      <pubDate>Wed, 01 Nov 2017 17:01:59 +0000</pubDate>
      
      <guid>/blog/2017/maintenance-network-mediacentrale-nov-1st-2017-2200/</guid>
      <description>Maintenance network Mediacentrale On November 1st 2017 after 22:00 we will upgrade our network in the Mediacentrale. Due to roadworks around Julianaplein in Groningen that will impact our current connections, we will move our network traffic to an upgraded router and fiber path, thus minimizing downtime related to these roadworks. Furthermore, this maintenance also results in an upgrade in our capacity to the Mediacentrale, as we will upgrade from a 1G to 10G infrastructure.</description>
    </item>
      
    <item>
      <title>linux / process uptime / exact</title>
      <link>/blog/2017/linux-process-uptime-exact/</link>
      <pubDate>Mon, 11 Sep 2017 00:00:00 +0000</pubDate>
      
      <guid>/blog/2017/linux-process-uptime-exact/</guid>
      <description>How to get (semi)exact uptime values for processes?
If you look at the ps faux listing, you&amp;rsquo;ll see a bunch of values:
walter 27311 0.8 1.8 5904852 621728 ? SLl sep06 61:05 \_ /usr/lib/chromium-browser/... walter 27314 0.0 0.2 815508 80852 ? S sep06 0:00 | \_ /usr/lib/chromium-brow... walter 27316 0.0 0.0 815508 14132 ? S sep06 0:01 | | \_ /usr/lib/chromium-... That second value (27311) is the PID, the tenth (61:05) how much CPU time has been spent.</description>
    </item>
      
    <item>
      <title>sudo / cron / silence logging / authlog</title>
      <link>/blog/2017/sudo-cron-silence-logging-authlog/</link>
      <pubDate>Wed, 30 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>/blog/2017/sudo-cron-silence-logging-authlog/</guid>
      <description>Do you use sudo for automated tasks? For instance to let the Zabbix agent access privileged information? Then your auth.log may look a bit flooded, like this:
Aug 30 10:51:44 sudo: zabbix : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/sbin/iptables -S INPUT Aug 30 10:51:44 sudo: pam_unix(sudo:session): session opened for user root by (uid=0) Aug 30 10:51:44 sudo: pam_unix(sudo:session): session closed for user root Or, if you run periodic jobs by root from cron, you get this:</description>
    </item>
      
    <item>
      <title>powerdns / pdnsutil / remove-record</title>
      <link>/blog/2017/powerdns-pdnsutil-remove-record/</link>
      <pubDate>Wed, 23 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>/blog/2017/powerdns-pdnsutil-remove-record/</guid>
      <description>The PowerDNS nameserver pdnsutil utility has an add-record, but no remove-record. How can we remove records programmatically for many domains at once?
Step one: make sure we can list all domains. For our PowerDNS 4 setup, we could do the following:
$ list_all() { ( for type in master native; do pdnsutil list-all-zones $type; done ) | grep -vE &amp;#39;^.$|:&amp;#39; | sort -V; } $ list_all domain1.tld domain2.tld ... Step two: filter the domains where we want to remove anything.</description>
    </item>
      
    <item>
      <title>gdb / debugging asterisk / ao2_containers</title>
      <link>/blog/2017/gdb-debugging-asterisk-ao2-containers/</link>
      <pubDate>Fri, 23 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>/blog/2017/gdb-debugging-asterisk-ao2-containers/</guid>
      <description>One of our Asterisk telephony machines appeared to &amp;ldquo;leak&amp;rdquo; queue member agents. That is, refuse to ring them because they were supposedly busy.
When trying to find the cause, there weren&amp;rsquo;t any data dumping functions for the container I wanted to inspect in the CLI. In this case the pending_members which is of type struct ao2_container. So, we had to resort to using gdb to inspect the data.
The struct ao2_container container data type itself looks like this:</description>
    </item>
      
    <item>
      <title>letsencrypt / expiry mails / unsubscribe</title>
      <link>/blog/2017/letsencrypt-expiry-mails-unsubscribe/</link>
      <pubDate>Sat, 03 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>/blog/2017/letsencrypt-expiry-mails-unsubscribe/</guid>
      <description>Today I got one of these Letsencrypt Expiry mails again. It looks like this:
Your certificate (or certificates) for the names listed below will expire in 19 days (on 21 Jun 17 19:38 +0000). Please make sure to renew your certificate before then, or visitors to your website will encounter errors. [domain here] ... If you want to stop receiving all email from this address, click [link here] (Warning: this is a one-click action that cannot be undone) I don&amp;rsquo;t need this particular domain anymore.</description>
    </item>
      
    <item>
      <title>puppet / pip_version / facter</title>
      <link>/blog/2017/puppet-pip-version-facter/</link>
      <pubDate>Tue, 30 May 2017 00:00:00 +0000</pubDate>
      
      <guid>/blog/2017/puppet-pip-version-facter/</guid>
      <description>Every once in a while I have to deal with machines provisioned by puppet.
I can&amp;rsquo;t seem to get used to the fact that --test not only tests, but actually does. It displays what it does though output, which is nice. To test without applying, you need the --noop flag.
But, today I wanted to bring up the quick fix to this old warning/error:
Error: Facter: error while resolving custom fact &amp;quot;pip_version&amp;quot;: undefined method `[]&#39; for nil:NilClass  The cause of the issue is an old version of pip(1) which has no --version parameter.</description>
    </item>
      
    <item>
      <title>ubuntu zesty / apt / dns timeout / srv records</title>
      <link>/blog/2017/ubuntu-zesty-apt-dns-timeout-srv-records/</link>
      <pubDate>Thu, 18 May 2017 00:00:00 +0000</pubDate>
      
      <guid>/blog/2017/ubuntu-zesty-apt-dns-timeout-srv-records/</guid>
      <description>Ever since I updated from Ubuntu/Yakkety to Zesty, my apt-get(1) would sit and wait a while before doing actual work:
$ sudo apt-get update 0% [Working] Madness. Let&amp;rsquo;s see what it&amp;rsquo;s doing&amp;hellip;
$ sudo strace -f -s 512 apt-get update ... [pid 5603] connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr(&amp;#34;127.0.0.1&amp;#34;)}, 16) = 0 ... [pid 5603] sendto(3, &amp;#34;\1\271\1\0\0\1\0\0\0\0\0\0\5_http\4_tcp\3ppa\tlaunchpad\3net\0\0!\0\1&amp;#34;, 46, MSG_NOSIGNAL, NULL, 0) = 46 [pid 5603] poll([{fd=3, events=POLLIN}], 1, 5000 &amp;lt;unfinished ...&amp;gt; ... [pid 5600] select(8, [5 6 7], [], NULL, {0, 500000}) = 0 (Timeout) .</description>
    </item>
      
    <item>
      <title>squashing old git history</title>
      <link>/blog/2017/squashing-old-git-history/</link>
      <pubDate>Sat, 13 May 2017 00:00:00 +0000</pubDate>
      
      <guid>/blog/2017/squashing-old-git-history/</guid>
      <description>You may have an internal project that you wish to open source. When starting the project, you didn&amp;rsquo;t take that into account, so it&amp;rsquo;s likely to contain references to private data that you do not wish to share.
Step one would be to clean things up. If this is a slow process, this can take time, while in the mean time the project gets updates.
Now, at one point you&amp;rsquo;re confident that at commit X1000, the project contains only non-private data.</description>
    </item>
      
    <item>
      <title>Loadbalancer maintenance 22nd february 2017</title>
      <link>/blog/2017/loadbalancer-maintenance-22-february-2017/</link>
      <pubDate>Mon, 13 Feb 2017 11:59:05 +0000</pubDate>
      
      <guid>/blog/2017/loadbalancer-maintenance-22-february-2017/</guid>
      <description>In the night of Wednesday (22nd of Febr. 2017) to Thursday (23rd of Febr. 2017) between 23:45 and 03:00 we will perform maintenance on our loadbalancers.
####Maintenance window 22-02-2017 23:45 - 23-02-2017 03:00
####Description Loadbalancers will be upgraded to increase throughput and enable new capabilities.
####Impact When maintenance starts, we&amp;rsquo;ll reroute all traffic to the secondary loadbalancer. Customers that have a multi-site setup should therefore not have any service interruption.</description>
    </item>
      
    <item>
      <title>detect invisible selection / copy buffer / chrome</title>
      <link>/blog/2017/detect-invisible-selection-copy-buffer-chrome/</link>
      <pubDate>Thu, 26 Jan 2017 00:00:00 +0000</pubDate>
      
      <guid>/blog/2017/detect-invisible-selection-copy-buffer-chrome/</guid>
      <description>In Look before you paste from a website to terminal the author rightly warns us about carelessly pasting any input from a web page into the terminal.
This LookBeforePaste Chrome Extension is a quick attempt at trying to warn the user.
Example output when pressing CTRL-C on the malicious code:
Heuristics are defined as follows. They could certainly be improved, but it&amp;rsquo;s a start.
function isSuspicious(node) { if (node.nodeType == node.</description>
    </item>
      
    <item>
      <title>convert / dehydrated / certbot / letsencrypt config</title>
      <link>/blog/2016/convert-dehydrated-certbot-letsencrypt-config/</link>
      <pubDate>Wed, 21 Dec 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/convert-dehydrated-certbot-letsencrypt-config/</guid>
      <description>If you find yourself in the situation that you have to reuse your Letsencrypt credentials/account generated by Dehydrated (a bash Letsencrypt interface) with the official Certbot client, like me, you&amp;rsquo;ll want to convert your config files.
In my case, I wanted to change my e-mail address, and the Dehydrated client offered no such command. With Certbot you can do this:
$ certbot register --update-registration --account f65c... But you&amp;rsquo;ll need your credentials in a format that Certbot groks.</description>
    </item>
      
    <item>
      <title>mysql / deterministic / reads sql data</title>
      <link>/blog/2016/mysql-deterministic-reads-sql-data/</link>
      <pubDate>Fri, 16 Dec 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/mysql-deterministic-reads-sql-data/</guid>
      <description>Can I use the MySQL function characteristic DETERMINISTIC in combination with READS SQL DATA and do I want to?
TL;DR If the following two groups of statements are the same to you, you want the DETERMINISTIC characteristic on your FUNCTION, even if you have READS SQL DATA.
SET @id = (SELECT my_func()); SELECT * FROM my_large_table WHERE id = @id; -- versus  SELECT * FROM my_large_table WHERE id = my_func(); (All of this is tested with MySQL 5.</description>
    </item>
      
    <item>
      <title>Availability during holiday December 2016</title>
      <link>/blog/2016/availability-during-holiday-december-2016/</link>
      <pubDate>Wed, 14 Dec 2016 11:16:10 +0000</pubDate>
      
      <guid>/blog/2016/availability-during-holiday-december-2016/</guid>
      <description>Starting the 17th of December we are on leave. We return to the office on the 2nd of January. During this period we are available 24/7 for incident response and other urgent matters as usual.
If you already know of any urgent requests which needs to be handled during this period, please inform us in advance so we can plan the required availability.</description>
    </item>
      
    <item>
      <title>patch-a-day / pdns-recursor / broken edns lookups</title>
      <link>/blog/2016/patch-a-day-pdns-recursor-broken-edns-lookups/</link>
      <pubDate>Thu, 01 Dec 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/patch-a-day-pdns-recursor-broken-edns-lookups/</guid>
      <description>Last month, our e-mail exchange (Postfix) started having trouble delivering mail to certain destinations. These destinations all appeared to be using Microsoft Office 365 for their e-mail. What was wrong? Who was to blame? And how to fix it?
The problem appeared like this:
Nov 16 17:04:08 mail postfix/smtp[13330]: warning: no MX host for umcg.nl has a valid address record Nov 16 17:04:08 mail postfix/smtp[13330]: 1D1D21422C2: to=&amp;lt;-EMAIL-@umcg.nl&amp;gt;, relay=none, delay=2257, delays=2256/0.02/0.52/0, dsn=4.</description>
    </item>
      
    <item>
      <title>patch-a-day / dovecot / broken mime parts / xenial</title>
      <link>/blog/2016/patch-a-day-dovecot-broken-mime-parts-xenial/</link>
      <pubDate>Wed, 30 Nov 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/patch-a-day-dovecot-broken-mime-parts-xenial/</guid>
      <description>At times, Dovecot started spewing messages into dovecot.log about a corrupted index cache file because of “Broken MIME parts”. This happened on Ubuntu/Xenial with dovecot_2.2.22-1ubuntu2.2:
imap: Error: Corrupted index cache file dovecot.index.cache: Broken MIME parts for mail UID 33928 in mailbox INBOX: Cached MIME parts don&#39;t match message during parsing: Cached header size mismatch (parts=4100...) imap: Error: unlink(dovecot.index.cache) failed: No such file or directory (in mail-cache.c:28) imap: Error: Corrupted index cache file dovecot.</description>
    </item>
      
    <item>
      <title>tmpfs files not found / systemd</title>
      <link>/blog/2016/tmpfs-files-not-found-systemd/</link>
      <pubDate>Tue, 15 Nov 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/tmpfs-files-not-found-systemd/</guid>
      <description>While debugging a problem with EDNS records, I wanted to get some cache info from the PowerDNS pdns-recursor. rec_control dump-cache should supply it, but I did not see it.
# rec_control dump-cache out.txt Error opening dump file for writing: Permission denied Doh, it&amp;rsquo;s running as the pdns user. Let&amp;rsquo;s write in /tmp.
# rec_control dump-cache /tmp/out.txt dumped 42053 records # less /tmp/out.txt /tmp/out.txt: No such file or directory Wait what? No files?</description>
    </item>
      
    <item>
      <title>setting up powerdns slave / untrusted host</title>
      <link>/blog/2016/setting-up-powerdns-slave-untrusted-host/</link>
      <pubDate>Wed, 02 Nov 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/setting-up-powerdns-slave-untrusted-host/</guid>
      <description>When migrating our nameserver setup to start using DNSSEC, a second requirement was to offload a resolver to somewhere off-network.
You want your authoritative nameservers to be distributed both accross different geographical regions, networks and top level domains. That means, don&#39;t do this:
 ns1.thedomain.com - datacenter X in Groningen ns2.thedomain.com - datacenter X in Groningen  Do do this:
 ns1.thedomain.com - datacenter X in Groningen ns2.thedomain.org - datacenter Y in Amsterdam  In our case, we could use a third nameserver in a separate location: a virtual machine hosted by someone other than us.</description>
    </item>
      
    <item>
      <title>mysql sys schema / mysqldump failure</title>
      <link>/blog/2016/mysql-sys-schema-mysqldump-failure/</link>
      <pubDate>Fri, 28 Oct 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/mysql-sys-schema-mysqldump-failure/</guid>
      <description>After upgrading the mysql-server to 5.7 and enabling GTIDs, the mysql-backup script started spewing errors.
Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don&#39;t want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events. (...repeated for every database schema...) mysqldump: Couldn&#39;t execute &#39;SHOW FIELDS FROM `host_summary`&#39;: View &#39;sys.</description>
    </item>
      
    <item>
      <title>copy-pasting into java applications / x11</title>
      <link>/blog/2016/copy-pasting-into-java-applications-x11/</link>
      <pubDate>Thu, 27 Oct 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/copy-pasting-into-java-applications-x11/</guid>
      <description>The other day I was rebooting our development server. It has full disk encryption, and the password for it has to be specified at boot time, long before it has network access.
Even though the machine is in the same building, walking over there is obviously not an option. The machine has IPMI, like all modern machines do, so we can connect a virtual console over the local network. For that, we use the SuperMicro ipmiview tool.</description>
    </item>
      
    <item>
      <title>packaging supermicro ipmiview / debian</title>
      <link>/blog/2016/packaging-supermicro-ipmiview-debian/</link>
      <pubDate>Tue, 25 Oct 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/packaging-supermicro-ipmiview-debian/</guid>
      <description>Do you want to quickly deploy SuperMicro ipmiview on your desktop?
IPMI is a specification for monitoring and management of computer hardware. Usually this is used for accessing servers in a data center when the regular remote login is not available. Think: hard rebooting a stuck machine, specifying the full disk encryption password at boot time, logging onto a machine where the remote login (ssh daemon) has disappeared.
The SuperMicro IPMI devices have an embedded webserver, but it requires Java to access the console.</description>
    </item>
      
    <item>
      <title>golang / statically linked</title>
      <link>/blog/2016/golang-statically-linked/</link>
      <pubDate>Tue, 18 Oct 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/golang-statically-linked/</guid>
      <description>So, Go binaries are supposed to be statically linked. That&amp;rsquo;s nice if you run inside cut-down environments where not even libc is available. But sometimes they use shared libraries anyway?
TL;DR: Use CGO_ENABLED=0 or -tags netgo to create a static executable.
Take this example:
$ go version go version go1.6.2 linux/amd64 $ go build gocollect.go $ file gocollect gocollect: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, \  interpreter /lib64/ld-linux-x86-64.</description>
    </item>
      
    <item>
      <title>sipp / travis / osx build / openssl</title>
      <link>/blog/2016/sipp-travis-osx-build-openssl/</link>
      <pubDate>Wed, 05 Oct 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/sipp-travis-osx-build-openssl/</guid>
      <description>A couple of days ago our SIPp Travis CI builds started failing due to missing OpenSSL include files.
Between SIPp build 196 and SIPp build 215 the OSX builds on Travis started failing with the following configure error:
checking openssl/bio.h usability... no checking openssl/bio.h presence... no checking for openssl/bio.h... no configure: error: &amp;lt;openssl/bio.h&amp;gt; header missing  It turns out that something had changed in the build environment and OpenSSL headers and libraries were no longer reachable.</description>
    </item>
      
    <item>
      <title>lxc / create image / debian squeeze</title>
      <link>/blog/2016/lxc-create-image-debian-squeeze/</link>
      <pubDate>Wed, 14 Sep 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/lxc-create-image-debian-squeeze/</guid>
      <description>I&amp;rsquo;m quite happy with our LXC environment on which I&amp;rsquo;ve got various Debian and Ubuntu build VMs so I can package backports and other fixes into nice .deb packages.
Today I needed an old Debian/Squeeze machine to build backports on.
Step one: check the lists.
$ lxc remote list +-----------------+--------------------------+---------------+-----+-----+ | NAME | URL | PROTOCOL | PUB | STC | +-----------------+--------------------------+---------------+-----+-----+ | images | https://images.linuxco...| simplestreams | YES | NO | +-----------------+--------------------------+---------------+-----+-----+ | local (default) | unix:// | lxd | NO | YES | +-----------------+--------------------------+---------------+-----+-----+ | ubuntu | https://cloud-images.</description>
    </item>
      
    <item>
      <title>Planned maintenance 22 August 2016</title>
      <link>/blog/2016/planned-maintenance-22-august-2016/</link>
      <pubDate>Wed, 10 Aug 2016 13:04:16 +0000</pubDate>
      
      <guid>/blog/2016/planned-maintenance-22-august-2016/</guid>
      <description>In the night of Monday (August. 22nd) to Tuesday (August. 23rd) between 23:45 and 06:00 we will perform network maintenance on our core network.
####Maintenance window Monday (August. 22nd) to Tuesday (August. 23rd) between 23:45 and 06:00 (CEST)
####Description One of the core routers (CR2) at TCN will be relocated to a new rack to allow further expansion on this site and make some desired improvements in the meantime.
Impact During the maintenance, routing will be adjusted to free CR2 of traffic.</description>
    </item>
      
    <item>
      <title>HTTP_PROXY &#34;httpoxy&#34; vulnerability (Dutch)</title>
      <link>/blog/2016/http-proxy-httpoxy-vulnerability-dutch/</link>
      <pubDate>Tue, 19 Jul 2016 08:03:33 +0000</pubDate>
      
      <guid>/blog/2016/http-proxy-httpoxy-vulnerability-dutch/</guid>
      <description>Een stukje uitleg over de HTTP_PROXY vulnerability die op https://httpoxy.org/ gemeld is.
Je site is vulnerable indien aan de volgende criteria wordt voldaan:
 Je hebt een webapplicatie die zelf webaanroepen doet; bijvoorbeeld communicatie met een payment provider of interne backend (d.m.v. python-requests, curl, http_get, etc&amp;hellip;). De webserver laat de Proxy header door als HTTP_PROXY. Dit is standaard zo. De HTTP_PROXY header komt tussen de environment variabelen. Dit is niet zo onder bijvoorbeeld python met uwsgi, maar wel bij CGI applicaties en ook bij php-fpm en apache-mod_php!</description>
    </item>
      
    <item>
      <title>Planned maintenance 21 July 2016 [UPDATED]</title>
      <link>/blog/2016/planned-maintenance-21-july-2016/</link>
      <pubDate>Tue, 12 Jul 2016 12:31:31 +0000</pubDate>
      
      <guid>/blog/2016/planned-maintenance-21-july-2016/</guid>
      <description>In the night of Thursday (Jul. 21st) to Friday (Jul. 22nd) between 23:00 and 04:00 we will perform network maintenance on our core network.
####Maintenance window Thursday (Jul. 21st) to Friday (Jul. 22nd) between 23:00 and 04:00 (CEST)
####Description Extra network capacity on our core network will be deployed and tested. During the maintenance, routing will be adjusted to free the links affected of any traffic.
Impact No impact expected. Increased chance for short service disruptions due to changes in network.</description>
    </item>
      
    <item>
      <title>letsencrypt / license update / show differences</title>
      <link>/blog/2016/letsencrypt-license-update-show-differences/</link>
      <pubDate>Sat, 09 Jul 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/letsencrypt-license-update-show-differences/</guid>
      <description>This morning, Let&amp;rsquo;s Encrypt e-mailed me that the Subscriber Agreement was updated; but it had no diff.
 Let&amp;rsquo;s Encrypt Subscriber,
We&amp;rsquo;re writing to let you know that we are updating the Let&amp;rsquo;s Encrypt Subscriber Agreement, effective August 1, 2016. You can find the updated agreement (v1.1.1) as well as the current agreement (v1.0.1) in the &amp;ldquo;Let&amp;rsquo;s Encrypt Subscriber Agreement&amp;rdquo; section of the following page:
https://letsencrypt.org/repository/
Thank you for helping to secure the Web by using Let&amp;rsquo;s Encrypt.</description>
    </item>
      
    <item>
      <title>Planned maintenance 17 June 2016</title>
      <link>/blog/2016/planned-maintenance-17-jun-2016/</link>
      <pubDate>Fri, 10 Jun 2016 12:14:48 +0000</pubDate>
      
      <guid>/blog/2016/planned-maintenance-17-jun-2016/</guid>
      <description>In the night of Friday (Jun. 17th) to Saturday (Jun. 18th) between 23:00 and 4:00 we will perform network maintenance on our core network.
####Maintenance window Friday (Jun. 17th 2016) to Saturday (Jun. 18th 2016) between 23:00 and 4:00.
####Description Extra network capacity on our core network will be deployed and tested. During the maintenance routing will be adjusted to allow active maintenance on certain fiber paths.
Impact No impact expected.</description>
    </item>
      
    <item>
      <title>apt / insufficiently signed / weak digest</title>
      <link>/blog/2016/apt-insufficiently-signed-weak-digest/</link>
      <pubDate>Thu, 24 Mar 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/apt-insufficiently-signed-weak-digest/</guid>
      <description>When adding our own apt repository to a new Ubuntu/Xenial machine, I got a &amp;ldquo;insufficiently signed (weak digest)&amp;rdquo; error.
# apt-get update ... W: gpgv:/var/lib/apt/lists/partial/ppa.osso.nl_ubuntu_dists_xenial_InRelease: The repository is insufficiently signed by key 4D1...0F5 (weak digest) Confirmed it with gpgv.
# gpgv --keyring /etc/apt/trusted.gpg \ /var/lib/apt/lists/ppa.osso.nl_ubuntu_dists_xenial_InRelease gpgv: Signature made Wed 23 Mar 2016 10:14:48 AM UTC using RSA key ID B36530F5 gpgv: Good signature from &amp;#34;PPA-OSSO-NL &amp;lt;support+ppa@osso.nl&amp;gt;&amp;#34; # gpgv --weak-digest sha1 --verbose --keyring /etc/apt/trusted.</description>
    </item>
      
    <item>
      <title>lxcfs - proc uptime</title>
      <link>/blog/2016/lxcfs-proc-uptime/</link>
      <pubDate>Wed, 23 Mar 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/lxcfs-proc-uptime/</guid>
      <description>When removing the excess LXC and LXD package from the LXC guest and working around Ubuntu/Xenial reboot issues I noticed the lxcfs mounts on my LXC guest.
(No, you don&amp;rsquo;t need the lxcfs package on the guest.)
guest# mount | grep lxc lxcfs on /proc/cpuinfo type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other) lxcfs on /proc/diskstats type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other) lxcfs on /proc/meminfo type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other) lxcfs on /proc/stat type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other) lxcfs on /proc/swaps type fuse.</description>
    </item>
      
    <item>
      <title>lxc - ubuntu xenial - reboot</title>
      <link>/blog/2016/lxc-ubuntu-xenial-reboot/</link>
      <pubDate>Tue, 22 Mar 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/lxc-ubuntu-xenial-reboot/</guid>
      <description>The current Ubuntu/Xenial guest image on our new LXD container host contained too many packages.
It held the lxd package and a bunch of lxc packages. They are not needed on the container guest. At some point before or after removing them, for some reason the ZFS container got unmounted.
This went unnoticed until I tried a reboot:
guest# reboot lxd# lxc exec guest /bin/bash error: Container is not running. lxd# lxc start guest error: Error calling &amp;#39;lxd forkstart guest /var/lib/lxd/containers /var/log/lxd/guest/lxc.</description>
    </item>
      
    <item>
      <title>renaming / lxd managed lxc container</title>
      <link>/blog/2016/renaming-lxd-managed-lxc-container/</link>
      <pubDate>Mon, 21 Mar 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/renaming-lxd-managed-lxc-container/</guid>
      <description>Renaming an LXD managed LXC container is not straight forward. But if you want to rename the host from inside the container, you should do so on the outside as well. If you don&amp;rsquo;t, you may notice that for instance the DHCP manual IP address assignment doesn&amp;rsquo;t work as expected.
Creating a new LXC container For example, we&amp;rsquo;ll create a new container called walter-old with a fresh Debian/Jessie on it.</description>
    </item>
      
    <item>
      <title>missing sofiles / linker / asterisk / pjsip</title>
      <link>/blog/2016/missing-sofiles-linker-asterisk-pjsip/</link>
      <pubDate>Sun, 21 Feb 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/missing-sofiles-linker-asterisk-pjsip/</guid>
      <description>When compiling Asterisk with a PJProject debianized using the debian/ directory to Ubuntu/Trusty, I got the following compile error:
$ gcc -o chan_pjsip.so -pthread -shared -Wl,--version-script,chan_pjsip.exports,--warn-common \  chan_pjsip.o pjsip/dialplan_functions.o -lpjsua2 -lstdc++ -lpjsua -lpjsip-ua \  -lpjsip-simple -lpjsip -lpjmedia-codec -lpjmedia-videodev -lpjmedia-audiodev \  -lpjmedia -lpjnath -lpjlib-util -lsrtp -lpj -lm -lrt -lpthread \  -lSDL2 -lavformat -lavcodec -lswscale -lavutil -lv4l2 -lopencore-amrnb \  -lopencore-amrwb /usr/bin/ld: cannot find -lSDL2 /usr/bin/ld: cannot find -lavformat /usr/bin/ld: cannot find -lavcodec /usr/bin/ld: cannot find -lswscale /usr/bin/ld: cannot find -lavutil /usr/bin/ld: cannot find -lv4l2 /usr/bin/ld: cannot find -lopencore-amrnb /usr/bin/ld: cannot find -lopencore-amrwb collect2: error: ld returned 1 exit status That&amp;rsquo;s odd.</description>
    </item>
      
    <item>
      <title>CVE-2015-7547: glibc getaddrinfo stack-based buffer overflow</title>
      <link>/blog/2016/cve-2015-7547-glibc-getaddrinfo-stack-based-buffer-overflow/</link>
      <pubDate>Tue, 16 Feb 2016 17:01:38 +0000</pubDate>
      
      <guid>/blog/2016/cve-2015-7547-glibc-getaddrinfo-stack-based-buffer-overflow/</guid>
      <description>On February 16, 2016 details on a vulnerability in glibc were released (CVE-2015-7547). The vulnerability is remotely exploitable and affects a lot of systems.
More info will be added later when more information is available.
We started emergency patch procedures for our environments and managed customer environments.
Summary  Classification: Critical. Remote exploitation possible. Impact: Wide impact, all services that use glibc and perform dns resolving are vulnerable.  upstream description The glibc DNS client side resolver is vulnerable to a stack-based buffer overflow when the getaddrinfo() library function is used.</description>
    </item>
      
    <item>
      <title>python / xinetd / virtualenv</title>
      <link>/blog/2016/python-xinetd-virtualenv/</link>
      <pubDate>Fri, 12 Feb 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/python-xinetd-virtualenv/</guid>
      <description>So, while developing a server application for a client, my colleague Harm decided it would be a waste of our programming time to add TCP server code.
Inetd and friends can do that really well. The amount of new connects to the server would be minimal, so the overhead of spawning a new Python process for every connect was negligible.
Using xinetd as an inetd server wrapper is simple. The config would look basically like this:</description>
    </item>
      
    <item>
      <title>Planned maintenance 13 Feb 2016</title>
      <link>/blog/2016/planned-maintenance-tcn-feb-2016/</link>
      <pubDate>Fri, 05 Feb 2016 17:24:25 +0000</pubDate>
      
      <guid>/blog/2016/planned-maintenance-tcn-feb-2016/</guid>
      <description>In the night of Friday (Feb. 12th) to Saturday (Feb. 13th) between 1:00 and 2:00 our co-location provider will perform maintenance on the PDU&amp;rsquo;s in one of our racks.
Customers we consider to be directly affected (bare metal servers) will receive an additional notification. Outside of that it&amp;rsquo;s mostly OSSO infrastructure services that are affected.
####Maintenance window 01:00-02:00 on 13th of Februari 2016.
####Description The PDU&amp;rsquo;s of one of the racks will be taken into service one by one (A and B feed).</description>
    </item>
      
    <item>
      <title>salt master losing children</title>
      <link>/blog/2016/salt-master-losing-children/</link>
      <pubDate>Fri, 15 Jan 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/salt-master-losing-children/</guid>
      <description>I recently set up psdiff on a few of my servers as a basic means to monitor process activity.
It disclosed that my SaltStack master daemon — which I&amp;rsquo;m running as a non-privileged user — was losing a single child, exactly 24 hours after I had ran salt commands. This seemed to be a recurring phenomenon.
The salt server — version 0.17.5+ds-1 on Ubuntu Trusty — was running these processes:</description>
    </item>
      
    <item>
      <title>polyglot xhtml</title>
      <link>/blog/2016/polyglot-xhtml/</link>
      <pubDate>Wed, 13 Jan 2016 00:00:00 +0000</pubDate>
      
      <guid>/blog/2016/polyglot-xhtml/</guid>
      <description>Polyglot XHTML: Serving pages that are valid HTML and valid XML at the same time.
A number of documents have been written on the subject, which I shall not repeat here.
My summary:
 HTML5 is not going away. XHTML pages validate in the browser. If you can get better validation during the development of your website, then you&amp;rsquo;ll save yourself time and headaches. Thus, for your development environment, you&amp;rsquo;ll set the equivalent of this:</description>
    </item>
      
    <item>
      <title>Availability during holiday december 2015</title>
      <link>/blog/2015/availability-december-2015/</link>
      <pubDate>Mon, 21 Dec 2015 14:59:35 +0000</pubDate>
      
      <guid>/blog/2015/availability-december-2015/</guid>
      <description>From 24th of December we are on leave and return to the office on the 4th of January. During this period we are available 24/7 for incident response and other urgent matters as usual.
If you already know of any urgent requests which needs to be handled during this period, please inform us in advance so we can plan the required availability.</description>
    </item>
      
    <item>
      <title>Planned maintenance - router upgrade RUG RH POP (01:00-04:00 8 DEC 2015)</title>
      <link>/blog/2015/router-upgrade-rug-rh-pop-dec-2015/</link>
      <pubDate>Mon, 30 Nov 2015 15:42:07 +0000</pubDate>
      
      <guid>/blog/2015/router-upgrade-rug-rh-pop-dec-2015/</guid>
      <description>In the night of Monday (Dec. 7th) to Tuesday (Dec. 8th) between 1:00 and 6:00 we will upgrade the router at our RUG Rekenhal POP. Impact is limited to IP Access locations and IP Transit customers on this POP.
####Maintenance window 01:00-04:00 on 8th of December 2015.
####Description We will upgrade the router to allow planned network upgrades.
Impact The router at the RUG Rekenhal POP will be unavailable for 30min-60min.</description>
    </item>
      
    <item>
      <title>asterisk / editline / key bindings</title>
      <link>/blog/2015/asterisk-editline-key-bindings/</link>
      <pubDate>Sat, 21 Nov 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/asterisk-editline-key-bindings/</guid>
      <description>Getting the Asterisk PBX CLI to work more like you&amp;rsquo;re used to from the (readline) bash shell can, be a time-saver.
For example, you may want reverse-i-search (^R), backward word deletion (^W) and word skipping (^&amp;lt;arrow-left&amp;gt; and ^&amp;lt;arrow-right&amp;gt;).
It can be done, but you must configure the editline library in a similar manner as you would configure .inputrc.
Support for the .editrc configuration file was added in May 2011 (git commit d508a921).</description>
    </item>
      
    <item>
      <title>Planned maintenance virtual servers TCN (01:00-06:00 27 NOV 2015)</title>
      <link>/blog/2015/planned-maintenance-virtual-servers-tcn-nov-2015/</link>
      <pubDate>Thu, 19 Nov 2015 15:21:27 +0000</pubDate>
      
      <guid>/blog/2015/planned-maintenance-virtual-servers-tcn-nov-2015/</guid>
      <description>In the night of Thursday (Nov. 26th) to Friday (Nov. 27th) between 1:00 and 6:00 we will perform maintenance to the virtual server infrastructure at location TCN.
####Maintenance window 01:00-06:00 on 27th of November 2015
####Description Virtual server infrastructure will be upgraded to a new major software release. Due to the major version upgrade and incompatibility between versions servers will experience downtime for 15-60 minutes
Impact Virtual servers will be offline for ~15 minutes (up to 60 minutes worst case).</description>
    </item>
      
    <item>
      <title>encfs / recursion into itself</title>
      <link>/blog/2015/encfs-recursion-into-itself/</link>
      <pubDate>Thu, 12 Nov 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/encfs-recursion-into-itself/</guid>
      <description>We wanted to use EncFS to be able to store encrypted backups.
The requirements for that are:
 The backup server initiates the backup. That&amp;rsquo;s where we configure which hours are safe (resource wise) and which files need backing up (etc, home, root, srv, &amp;hellip;). And it means the backup server can safely be placed behind a gateway disallowing all incoming connections. The backup server cannot know the passwords of files.</description>
    </item>
      
    <item>
      <title>encfs / configure / libboost</title>
      <link>/blog/2015/encfs-configure-libboost/</link>
      <pubDate>Tue, 10 Nov 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/encfs-configure-libboost/</guid>
      <description>I ran into an obscure Could not link against ! error when configuring EncFS:
~/src$ apt-get source encfs ... ~/src$ cd encfs-1.7.4/ ~/src/encfs-1.7.4$ ./configure ... configure: WARNING: BOOST_CPPFLAGS -I/usr/include checking whether the Boost::Serialization library is available... yes configure: error: Could not link against ! That&amp;rsquo;s odd. And not immediately obvious how to fix.
For starters we need all the dependencies that Debian defines:
~/src/encfs-1.7.4$ sed -e &amp;#39;/^Build-Depends: /!d;s/^[^:]*: //;s/([^)]*)//g;s/,//g&amp;#39; \  debian/control debhelper librlog-dev librlog5 libfuse-dev libssl-dev pkg-config libboost-serialization-dev libboost-filesystem-dev quilt dh-autoreconf ~/src/encfs-1.</description>
    </item>
      
    <item>
      <title>core router service disruption [UPDATED 5 Nov 2015]</title>
      <link>/blog/2015/core-router-issue-oct-nov-2015/</link>
      <pubDate>Wed, 04 Nov 2015 12:11:12 +0000</pubDate>
      
      <guid>/blog/2015/core-router-issue-oct-nov-2015/</guid>
      <description>Service disruptions on one of the core routers location (CR1) in TCN.
5 Nov 2015 - 01:00 CR1 Supervisor placement Following up the maintenance finished on Monday, we will add an extra Router Supervisor in CR1 for extended redundancy in case of main Supervisor failure. This maintenance will be carried out tonight, at 01:00 on the 5th of November. There is no expected impact.
This maintenance is a followup on the hardware replacement of the Supervisor in CR1.</description>
    </item>
      
    <item>
      <title>Planned network maintenance (01:00-03:00 6 NOV 2015)</title>
      <link>/blog/2015/planned-network-maintenance-0100-0300-6-nov-2015/</link>
      <pubDate>Wed, 28 Oct 2015 13:54:19 +0000</pubDate>
      
      <guid>/blog/2015/planned-network-maintenance-0100-0300-6-nov-2015/</guid>
      <description>In the night of Thursday (Nov. 5th) to Friday (Nov. 6th) between 1:00 and 3:00 we will perform network maintenance at our TCN co-location.
####Maintenance window 01:00-03:00 on 6th of November 2015
####Description
We will perform changes in the network configuration which will cause a change of mac address of the gateway for each subnet.
Impact Depending on the device it may take some time to pick up this change. Generally, busy servers will pick up the changes almost instantly and servers which are mostly idle may take a while.</description>
    </item>
      
    <item>
      <title>scapy / dns server / snippet</title>
      <link>/blog/2015/scapy-dns-server-snippet/</link>
      <pubDate>Mon, 05 Oct 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/scapy-dns-server-snippet/</guid>
      <description>A few days ago, the Scapy project was brought to my attention.
Scapy is an internet packet manipulation library for Python2. It can be used to sniff and decode packets, or to generate your own custom packets.
In the most basic form, it runs on raw sockets, sniffing and decoding traffic like tcpdump. See the sniff() examples and the send(IP(dst=&amp;quot;1.2.3.4&amp;quot;) / ICMP()) example for sending a simple packet.
But just as easily, it works on regular datagram sockets — those that you don&amp;rsquo;t need CAP_NET_RAW powers for.</description>
    </item>
      
    <item>
      <title>flake8 / vim / python2 / python3</title>
      <link>/blog/2015/flake8-vim-python2-python3/</link>
      <pubDate>Tue, 15 Sep 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/flake8-vim-python2-python3/</guid>
      <description>To syntax check Python code before executing, I use flake8. And when coding in the Vim editor, I use the vim-flake8 plugin that allows me to hit &amp;lt;F7&amp;gt; to quickly check for errors in the file I&amp;rsquo;m currently working in.
But, there are currently two common flavors of Python: python2 and python3. And therefore flake8 comes in two flavors as well — you guessed it — a python2 and a python3 flavor.</description>
    </item>
      
    <item>
      <title>python / subprocess / winch</title>
      <link>/blog/2015/python-subprocess-winch/</link>
      <pubDate>Tue, 01 Sep 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/python-subprocess-winch/</guid>
      <description>While I was writing a Python tool to wrap C Gdb so I could fetch some info out of it automatically, I ran into the issue that it reads the terminal size (lines x columns) to adjust its output.
I wanted consistent machine readable output, so I enlarged the terminal size programmatically: now row based output would not get wrapped by Gdb.
Later I noticed that it would cease to use the terminal size — in fact, use the default 80 columns — if I also redirected stderr to a non-tty.</description>
    </item>
      
    <item>
      <title>debian / packaging asterisk 13</title>
      <link>/blog/2015/debian-packaging-asterisk-13/</link>
      <pubDate>Tue, 18 Aug 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/debian-packaging-asterisk-13/</guid>
      <description>As of this writing, Debian testing (stretch) contains Asterisk version 13.1.0. The Debian source as GIT repository is here: https://anonscm.debian.org/git/pkg-voip/asterisk.git (browse)
Packaging a newer version is not that hard, if we start out with the debian/ directory kindly supplied by the Debian maintainers.
Hints to get things running:
Use a local git repository By using a local git repository in your unpacked Asterisk dir, you can quickly restart from scratch any time you mess anything up.</description>
    </item>
      
    <item>
      <title>on-the-fly encrypted backups</title>
      <link>/blog/2015/on-the-fly-encrypted-backups/</link>
      <pubDate>Wed, 24 Jun 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/on-the-fly-encrypted-backups/</guid>
      <description>I was wondering how easy it was to encrypt files before rsyncing them away to the backup machine.
A quick search turned up the suggestion to use encfs by the user Thor on ServerFault.
That looks like a decent solution. Let&amp;rsquo;s figure out if it meets our needs.
The idea is that we do this:
# mount read-only encrypted virtual copy of unencrypted local data: encfs --reverse -o ro ~/data/ ~/.</description>
    </item>
      
    <item>
      <title>monitoring / process open files / limit</title>
      <link>/blog/2015/monitoring-process-open-files-limit/</link>
      <pubDate>Thu, 23 Apr 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/monitoring-process-open-files-limit/</guid>
      <description>Here, an awesome shell one-liner to find which process uses the most files, relative to its max-open-files soft limit.
$ for x in /proc/[0-9]* do fds=0 max=`awk &amp;#39;/^Max open files/ {print $4}&amp;#39; $x/limits 2&amp;gt;/dev/null` &amp;amp;&amp;amp; for t in $x/fd/*; do fds=$((fds+1)); done &amp;amp;&amp;amp; test &amp;#34;${max:-0}&amp;#34; -gt 0 &amp;amp;&amp;amp; echo $((fds*100/max)) ${x##*/} done | sort -rn | while read l do pid=${l##* }; echo &amp;#34;$l`readlink /proc/$pid/exe`&amp;#34;; break; done 57 16674 /usr/lib/dovecot/imap-login So, my imap-login (pid 16674) apparently uses 57% percent of its allowed max open files.</description>
    </item>
      
    <item>
      <title>converting unprintable pdf / imagemagick</title>
      <link>/blog/2015/converting-unprintable-pdf-imagemagick/</link>
      <pubDate>Wed, 11 Mar 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/converting-unprintable-pdf-imagemagick/</guid>
      <description>Okay, so we all know that printers are sent from hell, but we still need to use them from time to time.
Today, we were trying to print a PDF document with bar codes on it. Amazingly enough, the text on the PDF looked fine, but the bar codes (images) appeared as if they were wrapped at the wrong place.
Luckily, convert(1) from ImageMagick came to the rescue:
$ convert -density 300 -define pdf:fit-page=A4 input.</description>
    </item>
      
    <item>
      <title>proxmox / resource usage</title>
      <link>/blog/2015/proxmox-resource-usage/</link>
      <pubDate>Wed, 04 Mar 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/proxmox-resource-usage/</guid>
      <description>As I mentioned the other day, my VM was slow, so I needed a way to figure out which VM guests were causing the heavy load on our Proxmox platform.
I hacked up proxtop to enumerate the top resource users:
$ ./proxtop -t day proxmox.example.com monitor@pve Password:&amp;lt;enter password&amp;gt; SORTED BY: cpu, avg ... SORTED BY: diskread, avg ------------------ #0: 3.1 MiB/s pve10 (acme-bugs-bunny) #1: 1.3 MiB/s pve07 (customerX-private) #2: 992.3 KiB/s pve10 (acme-road-runner) .</description>
    </item>
      
    <item>
      <title>proxmox api / python module</title>
      <link>/blog/2015/proxmox-api-python-module/</link>
      <pubDate>Mon, 02 Mar 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/proxmox-api-python-module/</guid>
      <description>So, my VM was slow, and I needed to know which VM guest was eating all the resources. These VM containers are all managed by Proxmox; which is great, but it doesn&amp;rsquo;t show which VM guest is eating all the resources.
Luckily, Proxmox provides an API to get that info.
The docs pointed to two API modules for Python, my language of choice for these kinds of jobs: proxmoxer and pyproxmox.</description>
    </item>
      
    <item>
      <title>zabbix api / python module</title>
      <link>/blog/2015/zabbix-api-python-module/</link>
      <pubDate>Fri, 27 Feb 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/zabbix-api-python-module/</guid>
      <description>Today, my choice of Python modules to Interface with Zabbix. They are all pretty similar, so that made it harder to choose.
Here the six modules, as mentioned on the Zabbix wiki are, in the order of my preference. Note that second and third came close, but I favor clean documented code and fewer dependencies. The last ones didn&amp;rsquo;t get tested because of my Python3 requirement.
zabbix-client # pip: zabbix-client # pep: 99% # last-update: Aug.</description>
    </item>
      
    <item>
      <title>asterisk / dialplan / variable expansion / security</title>
      <link>/blog/2015/asterisk-dialplan-variable-expansion-security/</link>
      <pubDate>Thu, 12 Feb 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/asterisk-dialplan-variable-expansion-security/</guid>
      <description>Even after writing plenty of Asterisk PBX dialplan, I occasionally get bitten by the unintuitiveness of the parser.
A few rules to avoid mistakes, are:
  Always use double quotes on no side of the expression, or better yet, on both if there is a chance that the value is empty:
$[${HANGUPCAUSE}=17] or
$[&amp;quot;${value_which_may_be_empty}&amp;quot;=&amp;quot;somevalue&amp;quot;]
  Otherwise try to avoid double quotes (and semi-colons, and backslashes) whenever possible. If you need to escape them, it&amp;rsquo;s too easy to get it wrong.</description>
    </item>
      
    <item>
      <title>GHOST: glibc gethostbyname buffer overflow</title>
      <link>/blog/2015/ghost-glibc-gethostbyname-buffer-overflow/</link>
      <pubDate>Wed, 28 Jan 2015 10:25:50 +0000</pubDate>
      
      <guid>/blog/2015/ghost-glibc-gethostbyname-buffer-overflow/</guid>
      <description>A high risk security issue in glibc was disclosed last night. Because of the potential high impact we started our emergency patch procedures for osso managed environments and notify customers with self managed environments.
Ghost vulnerability details Qualys discovered a buffer overflow in dns resolve functions in the GNU C library (glibc). They created a proof of concept exploit for exim and dubbed the vulnerability &#34;GHOST&#34;. All processes that might do dns lookups are susceptible to attacks when using a vulnerable glibc version.</description>
    </item>
      
    <item>
      <title>gitlab / upgrade / ruby / bundle</title>
      <link>/blog/2015/gitlab-upgrade-ruby-bundle/</link>
      <pubDate>Wed, 28 Jan 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/gitlab-upgrade-ruby-bundle/</guid>
      <description>While we do Python VirtualEnv stuff every day, we rarely do Ruby environments.
And after the Ubuntu dist-upgrade, the Ruby dependencies for our GitLab were broken — as was expected. This happens for Python pip installed packages as well. They&amp;rsquo;re linked against older system libraries, which have been removed by the upgrade.
How to fix the Gitlab dependencies?
Browse through the upgrade docs to find a bundle install command.
# cd /home/git/gitlab # sudo -u git -H bundle install \ --without development test postgres --deployment # for MySQL That did&amp;hellip; absolutely nothing — again, as was expected.</description>
    </item>
      
    <item>
      <title>fail2ban / started / e-mail / disable</title>
      <link>/blog/2015/fail2ban-started-e-mail-disable/</link>
      <pubDate>Sat, 10 Jan 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/fail2ban-started-e-mail-disable/</guid>
      <description>Tired of the Fail2ban start and stop e-mails?
Especially after a manual fail2ban restart, the [Fail2Ban] vsftpd: stopped on HOSTNAME and [Fail2Ban] vsftpd: started on HOSTNAME mail tuple is too spammy.
Quick fix to disable them:
Create a new file, named /etc/fail2ban/actions.d/sendmail-no-start-stop.local:
diff --git /etc/fail2ban/action.d/sendmail-no-start-stop.local /etc/fail2ban/action.d/sendmail-no-start-stop.local new file mode 100644 index 0000000..cb7ecb9 --- /dev/null +++ /etc/fail2ban/action.d/sendmail-no-start-stop.local @@ -0,0 +1,3 @@ +[Definition] +actionstart = +actionstop = And — you&amp;rsquo;re using mta = sendmail right?</description>
    </item>
      
    <item>
      <title>git / gnutls / handshake failed / nginx ciphers</title>
      <link>/blog/2015/git-gnutls-handshake-failed-nginx-ciphers/</link>
      <pubDate>Fri, 09 Jan 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/git-gnutls-handshake-failed-nginx-ciphers/</guid>
      <description>When trying to keep up with all the TLS/SSL security changes, you need to modify your nginx config every now and then.
The good TLS config may look like this:
# nginx.conf: http { ssl_certificate /etc/ssl/MY_DOMAIN.pem; ssl_certificate_key /etc/ssl/MY_DOMAIN.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA; ssl_session_cache shared:SSL:5m; ssl_session_timeout 5m; ssl_prefer_server_ciphers on; add_header Strict-Transport-Security &amp;quot;max-age=15768000; includeSubDomains&amp;quot;; And the above config is accompanied by a fairly good A grade from the Qualys SSL Labs Analyzer.</description>
    </item>
      
    <item>
      <title>uuid / storage / mysql</title>
      <link>/blog/2015/uuid-storage-mysql/</link>
      <pubDate>Tue, 06 Jan 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/uuid-storage-mysql/</guid>
      <description>Storing an UUID in MySQL efficiently:
DROP FUNCTION IF EXISTS uuidbin; CREATE FUNCTION uuidbin(uuid_val varchar(36)) RETURNS varbinary(16) DETERMINISTIC SQL SECURITY INVOKER RETURN CONCAT(UNHEX(LEFT(uuid_val,8)),UNHEX(MID(uuid_val,10,4)), UNHEX(MID(uuid_val,15,4)),UNHEX(MID(uuid_val,20,4)), UNHEX(RIGHT(uuid_val,12))); DROP FUNCTION IF EXISTS uuidstr; CREATE FUNCTION uuidstr(uuid_val varbinary(16)) RETURNS varchar(36) DETERMINISTIC SQL SECURITY INVOKER RETURN LOWER(CONCAT(HEX(LEFT(uuid_val,4)),&amp;#39;-&amp;#39;,HEX(MID(uuid_val,5,2)), &amp;#39;-&amp;#39;,HEX(MID(uuid_val,7,2)),&amp;#39;-&amp;#39;,HEX(MID(uuid_val,9,2)), &amp;#39;-&amp;#39;,HEX(RIGHT(uuid_val,6)))); Now you can create your uuid columns with type binary(16).
And conversion is easy:
mysql&amp;gt; select uuidstr(uuidbin(uuidstr(uuidbin(uuidstr(uuidbin( &amp;#39;a89e6d7b-f2ec-11e3-bcfb-5c514fe65f2f&amp;#39;)))))) as uuid_back_and_forth; +--------------------------------------+ | uuid_back_and_forth | +--------------------------------------+ | a89e6d7b-f2ec-11e3-bcfb-5c514fe65f2f | +--------------------------------------+ </description>
    </item>
      
    <item>
      <title>django / makemessages / slow</title>
      <link>/blog/2015/django-makemessages-slow/</link>
      <pubDate>Mon, 05 Jan 2015 00:00:00 +0000</pubDate>
      
      <guid>/blog/2015/django-makemessages-slow/</guid>
      <description>Django makemessages can be quite slow on larger projects.
$ time python ../manage.py makemessages -lnl -ddjango processing language nl real 0m8.203s user 0m2.670s sys 0m5.763s Why does it take so long? Well, it&amp;rsquo;s system call heaven:
$ strace -f python ../manage.py makemessages -lnl -ddjango \  &amp;gt;tmp.log 2&amp;gt;&amp;amp;1 $ sed -e &amp;#39;s/(.*//;s/^\[[^]]*\] //;/^ \?&amp;lt;/d;/,/d;/^+/d&amp;#39; tmp.log | sort | uniq -c | sort -n | tail -n10 10893 rt_sigaction 16179 stat 16819 fcntl 22875 access 27833 read 32469 open 33650 fstat 40891 mprotect 69181 mmap 1267039 close For every file, a call to xgettext(1) is made.</description>
    </item>
      
    <item>
      <title>photo exif timestamp / filesystem mtime</title>
      <link>/blog/2014/photo-exif-timestamp-filesystem-mtime/</link>
      <pubDate>Mon, 17 Nov 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/photo-exif-timestamp-filesystem-mtime/</guid>
      <description>Sometimes, after a stray copy operation, your filesystem times may reflect the time the files were copied instead of when the file was actually last altered.
For example this image folder here:
$ ls -l phone2013 total 320856 -rw-rw-r-- 1 walter walter 1524591 nov 17 21:52 2012-10-28 08.54.58.jpg -rw-rw-r-- 1 walter walter 1534840 nov 17 21:52 2012-10-28 08.55.04.jpg -rw-rw-r-- 1 walter walter 1635908 nov 17 21:52 2012-10-28 08.55.09.jpg ... -rw-rw-r-- 1 walter walter 1600504 nov 17 21:52 2013-10-22 11.</description>
    </item>
      
    <item>
      <title>python / ctypes / socket / datagram</title>
      <link>/blog/2014/python-ctypes-socket-datagram/</link>
      <pubDate>Fri, 17 Oct 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/python-ctypes-socket-datagram/</guid>
      <description>So, I was really simply trying to figure out why talking to my OpenSIPS instance over a datagram unix socket failed. If I had bothered to check the server logs, I would immediately have seen that it was a simple stupid permission issue.
Instead, I ended up reimplementing recvfrom and sendto in Python using the ctypes library. Which was completely useless, since Python socket.recvfrom and socket.sendto already work properly.
To let the time spent on that not go to a complete waste, I give you (and myself) an example of ctypes usage.</description>
    </item>
      
    <item>
      <title>rsyslog / cron / deleting rules</title>
      <link>/blog/2014/rsyslog-cron-deleting-rules/</link>
      <pubDate>Wed, 10 Sep 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/rsyslog-cron-deleting-rules/</guid>
      <description>Syslog generally works fine as it is, so I don&amp;rsquo;t need to poke around in it often. That also means that I forget how to tweak it.
How did you move those every-5-minutes cron jobs out of /var/log/syslog?
The rules (selection + action) look like this in the Debian default config:
*.*;auth,authpriv.none -/var/log/syslog #cron.* /var/log/cron.log The manual has this to say about it:
 You can specify multiple facilities with the same priority pattern in one statement using the comma (,) operator.</description>
    </item>
      
    <item>
      <title>Maintenance datacenter TCN (13, 20, 27 Sept.)</title>
      <link>/blog/2014/maintenance-power-datacenter-tcn-13-20-27-sept/</link>
      <pubDate>Tue, 09 Sep 2014 09:36:33 +0000</pubDate>
      
      <guid>/blog/2014/maintenance-power-datacenter-tcn-13-20-27-sept/</guid>
      <description>One of our datacenter locations (TCN Telehouse) will have major maintenance on its power infrastructure this month. They scheduled 4 maintenance windows of 1,5 hours each during which either the A or B feed will be powerless.
In the last weeks we&amp;rsquo;ve double checked our infrastructure and this week we will finish our last preparations. All equipment that is not equipped with dual power supplies is connected to an ATS (Automatic Transfer Switch) to achieve power redundancy.</description>
    </item>
      
    <item>
      <title>daemon reparented / init --user</title>
      <link>/blog/2014/daemon-reparented-init-user/</link>
      <pubDate>Sat, 06 Sep 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/daemon-reparented-init-user/</guid>
      <description>While I was battling an obscure Ubuntu shutdown issue — more about that later — I noticed that daemonized jobs started from my X session were not reparented to PID 1 init, but to a custom init --user, owned by me.
What? I cannot start daemon that outlives my X session?
That&amp;rsquo;s right, I cannot. Check this out:
$ sh -c &amp;#39;sleep 61 &amp;amp;&amp;#39; $ ps faxu | egrep &amp;#39;init|sleep 61&amp;#39; root 1 .</description>
    </item>
      
    <item>
      <title>git / resetting merges</title>
      <link>/blog/2014/git-resetting-merges/</link>
      <pubDate>Fri, 05 Sep 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/git-resetting-merges/</guid>
      <description>Today&amp;rsquo;s git question: does git reset undo a merge or only parts of it?
TL;DR: It undoes the entire merge.
If you think about it logically, it must, since an object describes the entire state of the repository. But it can feel awkward and unexpected that older items than the object that we&amp;rsquo;re resetting to, are removed as well.
Let&amp;rsquo;s just try it. Set up a repository with two branches:</description>
    </item>
      
    <item>
      <title>apt / hold upgrades / dependencies</title>
      <link>/blog/2014/apt-hold-upgrades-dependencies/</link>
      <pubDate>Fri, 15 Aug 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/apt-hold-upgrades-dependencies/</guid>
      <description>Recently I wrote about cherry picking upgrades. Sometimes you&amp;rsquo;ll want to do the inverse.
For that purpose there exists apt-mark hold (and its counterpart apt-mark unhold).
For example, you may to delay the mysql upgrade I mentioned, for now. In that case you do:
# apt-mark hold mysql-client-5.5 mysql-common mysql-server-5.5 mysql-server-core-5.5 Now you can apt-get upgrade all the other packages while the mysql packages stay on hold. Note that these are shown in the held list every time you run upgrade, so you won&amp;rsquo;t forget about them.</description>
    </item>
      
    <item>
      <title>squirrelmail / clicking on empty subject</title>
      <link>/blog/2014/squirrelmail-clicking-on-empty-subject/</link>
      <pubDate>Thu, 14 Aug 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/squirrelmail-clicking-on-empty-subject/</guid>
      <description>SquirrelMail on Debian/Wheezy (2:1.4.23~svn20120406-2) stopped showing (none) for e-mails that lack a subject. Now I cannot open any subject-less mail because there is nothing to click on.
The quick fix:
--- /usr/share/squirrelmail/functions/mailbox_display.php.orig 2014-08-15 10:37:37.000000000 +0200 +++ /usr/share/squirrelmail/functions/mailbox_display.php 2014-08-15 10:38:27.000000000 +0200 @@ -268,6 +268,9 @@ function printMessageInfo($imapConnectio  $title = str_replace(&amp;#39;&amp;#34;&amp;#39;, &amp;#34;&amp;#39;&amp;#39;&amp;#34;, $title); $td_str .= &amp;#34; title=\&amp;#34;$title\&amp;#34;&amp;#34;; } + if (!$subject) { + $subject = &amp;#39;(none)&amp;#39;; + }  $td_str .= &amp;#34;&amp;gt;$flag$subject$flag_end&amp;lt;/a&amp;gt;$bold_end&amp;#34;; echo html_tag( &amp;#39;td&amp;#39;, $td_str, &amp;#39;left&amp;#39;, $hlt_color ); break; </description>
    </item>
      
    <item>
      <title>Import one database instead of all from sql dump </title>
      <link>/blog/2014/import-one-database-from-sql-dump/</link>
      <pubDate>Thu, 17 Jul 2014 14:05:19 +0000</pubDate>
      
      <guid>/blog/2014/import-one-database-from-sql-dump/</guid>
      <description>Ever needed to restore only one database on a MySQL server and found out you only had one SQL dump containing all databases?
Its quite common to dump all databases in one SQL file (mysqldump &amp;ndash;all-databases or -A). But when using multiple databases on one MySQL instance you often need to restore just one of them.
The minimal effort solution:
mysql --one-database desired_db_name &amp;lt; alldatabases.sql
fix!</description>
    </item>
      
    <item>
      <title>compose key / irony punctuation / x11</title>
      <link>/blog/2014/compose-key-irony-punctuation-x11/</link>
      <pubDate>Thu, 26 Jun 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/compose-key-irony-punctuation-x11/</guid>
      <description>Transcript follows:
[him] did I mention I&#39;ll be off from work earlier today because I&#39;m having dinner with friends. I&#39;ll be off earlier today because I&#39;m having dinner with friends. [me] where did you say you were going? [him] I&#39;ll be having dinner at the Grand Cafe  Apparently the irony was lost on him. I should&amp;rsquo;ve used emoticons.
But! Instead of emoticons, one may also use the irony punctuation: ⸮</description>
    </item>
      
    <item>
      <title>apt / cherry-pick upgrades / dependencies</title>
      <link>/blog/2014/apt-cherry-pick-upgrades-dependencies/</link>
      <pubDate>Mon, 09 Jun 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/apt-cherry-pick-upgrades-dependencies/</guid>
      <description>So, doing an apt-get upgrade on a Debian or Ubuntu machine sometimes does more than you want at once.
See this upgrade example I encountered just now:
# apt-get upgrade ... The following packages will be upgraded: curl dpkg ifupdown iproute libcurl3 libcurl3-gnutls libgnutls26 libmysqlclient18 libsnmp-base libsnmp15 libssl1.0.0 libxml2 linux-firmware linux-generic-lts-quantal mysql-client-5.5 mysql-client-core-5.5 mysql-common mysql-server mysql-server-5.5 mysql-server-core-5.5 openssh-client openssh-server openssl tzdata update-manager-core whoopsie 26 upgraded, 0 newly installed, 0 to remove and 2 not upgraded.</description>
    </item>
      
    <item>
      <title>vim / position markers</title>
      <link>/blog/2014/vim-position-markers/</link>
      <pubDate>Sun, 08 Jun 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/vim-position-markers/</guid>
      <description>Did you ever wonder what the &#39;&amp;lt;,&#39;&amp;gt; characters mean when you CTRL-V visual block select text in vim?
For example: you press CTRL-V and select a bit of text. Then type : (colon). Instead of just the colon, you see: :&#39;&amp;lt;,&#39;&amp;gt;. You append s/^/#/ hit enter. As requested, the selected block is now “commented out”.
That&amp;rsquo;s a nice feature, but why the funny characters? In order to understand that, we remind you of the % (percent sign) that we use to select the entire file.</description>
    </item>
      
    <item>
      <title>vim / reformat textwidth 72</title>
      <link>/blog/2014/vim-reformat-textwidth-72/</link>
      <pubDate>Sat, 07 Jun 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/vim-reformat-textwidth-72/</guid>
      <description>My .vimrc usually starts out with this. Syntax highlighting is super, and my terminals always have a black background. The modeline option enables me and others to set certain options for certain files only. Like: {# vim: syntax=htmldjango: #} to mark a .html file as using the django html syntax instead of regular html syntax. See also my Inserting vim modelines tip.
syn onset bg=darkset modelineSecond, since I develop a lot in Python, I enable the vim-flake8 python source code checker plugin:</description>
    </item>
      
    <item>
      <title>postgresql / upgrade / ubuntu</title>
      <link>/blog/2014/postgresql-upgrade-ubuntu/</link>
      <pubDate>Thu, 08 May 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/postgresql-upgrade-ubuntu/</guid>
      <description>I always forget how easy it is to upgrade postgresql on Ubuntu (from 9.1 to 9.3 this time). It seems like a pain to have to manually upgrade the cluster, but when it comes down to it, it&amp;rsquo;s self-documenting and quick.
My shell session basically went like this:
$ sudo apt-get install postgresql-9.3 ... The following extra packages will be installed: postgresql-client-9.3 ... $ sudo /etc/init.d/postgresql stop * Stopping PostgreSQL 9.</description>
    </item>
      
    <item>
      <title>openssh / nagle / too much buffering</title>
      <link>/blog/2014/openssh-nagle-too-much-buffering/</link>
      <pubDate>Wed, 07 May 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/openssh-nagle-too-much-buffering/</guid>
      <description>Recently I tried to open a connection to a remote server over SSH at a new location. The connection opened just fine, but it seemed that a few bytes kept getting buffered.
It looked like this first animated gif you see.
After a long wait, you realise that the data you&amp;rsquo;re wating just won&amp;rsquo;t come. First after pressing a key, you get the data.
This isn&amp;rsquo;t workable&amp;hellip;
Enumerating the possible culprits, there could really only be the wifi-nat-modem — a Thomson TG789vn, Telia device — doing extra buffering, possibly conflicting with the Nagle algorithm (TCP_NODELAY).</description>
    </item>
      
    <item>
      <title>ubuntu trusty / git diff color</title>
      <link>/blog/2014/ubuntu-trusty-git-diff-color/</link>
      <pubDate>Sat, 26 Apr 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/ubuntu-trusty-git-diff-color/</guid>
      <description>On my recently upgraded Ubuntu Trusty (14.04) machine, git diff started producing colorized output.
That&amp;rsquo;s nice, but it&amp;rsquo;d be even nicer if it recognised that I&amp;rsquo;m using a dark background.
Put this in your ~/.gitconfig. This colorscheme is the one you&amp;rsquo;re used to from vim.
[color &amp;quot;diff&amp;quot;] meta = green bold frag = yellow bold old = red bold new = cyan bold </description>
    </item>
      
    <item>
      <title>Heart bleed; OpenSSL security issue</title>
      <link>/blog/2014/heart-bleed-openssl-security-issue/</link>
      <pubDate>Tue, 08 Apr 2014 20:31:01 +0000</pubDate>
      
      <guid>/blog/2014/heart-bleed-openssl-security-issue/</guid>
      <description>Last night an important security vulnerability was made public with corresponding security updates. It risks exposing private keys when vulnerable.
OpenSSL was vulnerable starting from their OpenSSL 1.0.1 release on 14th of March 2012 till OpenSSL 1.0.1g released on 7th of April 2014. Two security teams independently reported this issue and it&amp;rsquo;s safe to assume others did as well. On top of that it&amp;rsquo;s not possible to trace whether you were successfully exploited.</description>
    </item>
      
    <item>
      <title>Internet connectivity issue. (31/3/2014)</title>
      <link>/blog/2014/internet-connectivity-issue-3132014/</link>
      <pubDate>Mon, 31 Mar 2014 10:55:43 +0000</pubDate>
      
      <guid>/blog/2014/internet-connectivity-issue-3132014/</guid>
      <description>This morning we experienced packet loss on one of our links. After rerouting the traffic the problem was resolved. Only routes over the GN-IX were affected.
timeline  12:15 first notification of the packetloss. 12:36 - 12:40 Hickups in the internet connectivity due to rerouting of traffic. after 12:40 No more issues for our customers. Offhour followup re-enable temporary disabled links and rebalance traffic.  Background information The issue occurred because GN-IX hit its capacity limit on their links between Groningen and Amsterdam.</description>
    </item>
      
    <item>
      <title>zabbix / counting security updates</title>
      <link>/blog/2014/zabbix-counting-security-updates/</link>
      <pubDate>Sat, 22 Mar 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/zabbix-counting-security-updates/</guid>
      <description>When you&amp;rsquo;re monitoring security update availability using Zabbix or some other monitoring tool, you&amp;rsquo;ll need a method to discern regular updates from security updates.
I&amp;rsquo;ve seen my collegues do this:
$ /usr/lib/update-notifier/apt-check --human-readable | grep security | awk &amp;#39;{print $1}&amp;#39; But that requires an install of the update-notifier-common package. (Note the -common. The main package has tons of requirements you don&amp;rsquo;t need.)
In the quest for less dependencies — less installed packages — I used aptitude to get the info.</description>
    </item>
      
    <item>
      <title>mysql innodb process locks in limbo</title>
      <link>/blog/2014/mysql-innodb-process-locks-in-limbo/</link>
      <pubDate>Wed, 12 Mar 2014 13:18:50 +0000</pubDate>
      
      <guid>/blog/2014/mysql-innodb-process-locks-in-limbo/</guid>
      <description>After switching a virtual IP around with keepalived we experienced a locking issue. Some client process on the server had some locks which did not get released but we could not see which query caused it.
This broke our MySQL replication in this case, it was waiting on the locks to be released while executing the binlogs.
We located the locks with
mysql&amp;gt; show engine innodb status\G;  The specific transaction did not show any query details but did show us a whole list of locks.</description>
    </item>
      
    <item>
      <title>FreeBSD fix/cheat sheet</title>
      <link>/blog/2014/freebsd-fix-cheat-sheet/</link>
      <pubDate>Wed, 12 Mar 2014 12:05:43 +0000</pubDate>
      
      <guid>/blog/2014/freebsd-fix-cheat-sheet/</guid>
      <description>For me, using FreeBSD is still a bit like eating soup with a fork. Everything seems to make perfect sense but when I get to work I feel crippled and get annoyed by small differences with a GNU/Linux environment.
A post to reduce the horror. The examples below work for a clean FreeBSD 10 install. This post is mostly useful for Linux users. I welcome additional tips.
software management You can now use pkg which is quite friendly.</description>
    </item>
      
    <item>
      <title>DDoS mitigated; NTP Amplification attack</title>
      <link>/blog/2014/ddos-mitigated-ntp-amplification/</link>
      <pubDate>Thu, 20 Feb 2014 15:13:07 +0000</pubDate>
      
      <guid>/blog/2014/ddos-mitigated-ntp-amplification/</guid>
      <description>Today we received a DDoS on our network which caused a service interruption for our customers for about 20 minutes. This blogpost is a short report on the impact and nature of the attack.
Impact Impact was network wide and caused degraded service for our customers between 14:45 and 15:08, a little over 20 minutes.
The graph shows the impact as seen from our UK monitoring node (off net).
Incoming traffic All our uplinks were saturated.</description>
    </item>
      
    <item>
      <title>python parsestring / silently skips entities</title>
      <link>/blog/2014/python-parsestring-silently-skips-entities/</link>
      <pubDate>Wed, 15 Jan 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/python-parsestring-silently-skips-entities/</guid>
      <description>The Python xml.dom.minidom parseString silently skips over unknown entities.
The only entities it does know, are &amp;amp;lt;, &amp;amp;gt;, &amp;amp;amp;, &amp;amp;apos; and &amp;amp;quot; and of course the numeric entities &amp;amp;#nn; and &amp;amp;#xhh;.
That&amp;rsquo;s obvious, because those are the only ones defined in the XML 1.0 spec.
However, if you&amp;rsquo;re parsing XHTML documents, it&amp;rsquo;s not nice that the entity references to special characters silently get dropped.
Other people have stubled on the same issue, like in parsing xml containing &amp;amp;entities; with minidom and Problem with minidom and special chars in HTML.</description>
    </item>
      
    <item>
      <title>bson / json / converter</title>
      <link>/blog/2014/bson-json-converter/</link>
      <pubDate>Mon, 13 Jan 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/bson-json-converter/</guid>
      <description>A simple script to convert BSON data to JSON data: bson2json.py (view)
Example usage:
$ bson2json.py /var/backups/mongodb/all-dbs.mon/graylog2/streams.bson --pretty [ { &amp;#34;_id&amp;#34;: &amp;#34;506ed227dc1d710c0700000e&amp;#34;, &amp;#34;additional_columns&amp;#34;: [], &amp;#34;alarm_active&amp;#34;: true, &amp;#34;alarm_callbacks&amp;#34;: [ &amp;#34;org.graylog2.emailalarmcallback.callback.EmailAlarmCallback&amp;#34;, &amp;#34;org.graylog2.execalarmcallback.callback.ExecAlarmCallback&amp;#34; ], &amp;#34;alarm_limit&amp;#34;: 80, &amp;#34;alarm_period&amp;#34;: 5, &amp;#34;alarm_timespan&amp;#34;: 5, &amp;#34;created_at&amp;#34;: &amp;#34;2012-10-05T12:27:19Z&amp;#34;, ... </description>
    </item>
      
    <item>
      <title>thunderbird / reply / only selected text</title>
      <link>/blog/2014/thunderbird-reply-only-selected-text/</link>
      <pubDate>Wed, 08 Jan 2014 00:00:00 +0000</pubDate>
      
      <guid>/blog/2014/thunderbird-reply-only-selected-text/</guid>
      <description>Apparently I&amp;rsquo;m not the only one who randomly selects text as they read. My colleagues complained about this issue too.
If you click Reply in Thunderbird Mail, only the text you recently selected is included in the new message. That&amp;rsquo;s not what I wanted!
Luckily the Mozilla developers realised this too. Go to about:config and flip the switch.
mailnews.reply_quoting_selection = false  </description>
    </item>
      
    <item>
      <title>amavis / tag subject / virus</title>
      <link>/blog/2013/amavis-tag-subject-virus/</link>
      <pubDate>Thu, 26 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/amavis-tag-subject-virus/</guid>
      <description>Today we got a suspiciously good looking e-mail in the inbox. Someone who supposedly got a reminder about an unpaid invoice from us.
The mail contained a zip-file with two scans. The first was a PDF, the second was an executable (a virus obviously).
So.. where was the Amavis virus/spam scanner in all this?
Show headers revealed that something was detected:
X-Amavis-Alert: BANNED, message contains .exe,scan2/HP scan scan =?iso-8859-1?Q?HYJKIOPH5600002.=E2=80=AEfdp.exe?= Then why weren&amp;rsquo;t we informed?</description>
    </item>
      
    <item>
      <title>gnome-calculator / missing menu</title>
      <link>/blog/2013/gnome-calculator-missing-menu/</link>
      <pubDate>Tue, 24 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/gnome-calculator-missing-menu/</guid>
      <description>After the upgrade of my desktop to Ubuntu Raring (13.04) my gnome-calculator&amp;rsquo;s menu bar had become unreachable.
I don&amp;rsquo;t need the menu, except that it went into default BASIC mode. And I need the PROGRAMMING mode.
The configuration seemed to be okay (accessible through gconf-editor):
$ gconftool /apps/gcalctool --dump | grep -B1 -A4 mode &amp;lt;entry&amp;gt; &amp;lt;key&amp;gt;mode&amp;lt;/key&amp;gt; &amp;lt;value&amp;gt; &amp;lt;string&amp;gt;PROGRAMMING&amp;lt;/string&amp;gt; &amp;lt;/value&amp;gt; &amp;lt;/entry&amp;gt; &amp;lt;entry&amp;gt; &amp;lt;key&amp;gt;modetype&amp;lt;/key&amp;gt; &amp;lt;value&amp;gt; &amp;lt;string&amp;gt;PROGRAMMING&amp;lt;/string&amp;gt; &amp;lt;/value&amp;gt; &amp;lt;/entry&amp;gt; But that was apparently the old config.</description>
    </item>
      
    <item>
      <title>teamviewer / without all ia32-libs</title>
      <link>/blog/2013/teamviewer-without-all-ia32-libs/</link>
      <pubDate>Mon, 16 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/teamviewer-without-all-ia32-libs/</guid>
      <description>A quick rundown on installing TeamViewer without a gazillion ia32-libs.
The problem: if you attempt to install teamviewer_linux_x64.deb on your 64-bit machine, the ia32-libs dependency tries to install more than 200 packages.
That not only feels like overkill, it takes a hell of a long time too.
The solution: alter the dependency list in the .deb and create a small metapackage that references only the required libs.
What follows, is the steps how.</description>
    </item>
      
    <item>
      <title>mysql / count occurrences</title>
      <link>/blog/2013/mysql-count-occurrences/</link>
      <pubDate>Wed, 11 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/mysql-count-occurrences/</guid>
      <description>Voilà, a MySQL function to count occurrences of a character (or a string of characters).
DROP FUNCTION IF EXISTS OCCURRENCES; delimiter // CREATE FUNCTION OCCURRENCES (`needle` VARCHAR(255), `hackstack` TEXT) RETURNS INT NOT DETERMINISTIC READS SQL DATA SQL SECURITY INVOKER BEGIN DECLARE `result` INT DEFAULT -1; DECLARE `pos` INT DEFAULT 0; DECLARE `skip` INT DEFAULT LENGTH(`needle`); REPEAT SET `pos` = (SELECT LOCATE(`needle`, `hackstack`, `pos` + `skip`)); SET `result` = `result` + 1; UNTIL `pos` = 0 END REPEAT; RETURN `result`; END; // delimiter ; Now you can do things like this:</description>
    </item>
      
    <item>
      <title>mysql / datetime / indexes</title>
      <link>/blog/2013/mysql-datetime-indexes/</link>
      <pubDate>Fri, 06 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/mysql-datetime-indexes/</guid>
      <description>MySQL has many odd quirks. One that bit us recently was this:
regression: &amp;gt;=mysql-5.4 utf8 collations are marked as not ascii compatible
When using the utf8_unicode_ci collation, datetime column comparisons against strings would ignore any indexes. The lack of working indexes obviously caused huge performance degradation.
Our bug report was ignored in Februari. Apparently a new bug was opened in March:
Datetime field comparisons do not work properly with utf8_unicode_ci collation</description>
    </item>
      
    <item>
      <title>thunderbird / postfix / dkim / invalid body hash</title>
      <link>/blog/2013/thunderbird-postfix-dkim-invalid-body-hash/</link>
      <pubDate>Wed, 04 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/thunderbird-postfix-dkim-invalid-body-hash/</guid>
      <description>Mozilla Thunderbird uses an odd max line length of 999 + CRLF: 1001 characters. When using DKIM preprocessing, this can result in DKIM validation failure.
To reproduce, we would send a mail that didn&amp;rsquo;t wrap well with line lengths in excess of 999 characters. Like this mail with 1000 &#39;x&#39; characters:
Thunderbird splits that into 999 times &#39;x&#39;, and CRLF and another line with a single &#39;x&#39;. However, that first line gets split again.</description>
    </item>
      
    <item>
      <title>virtualenv / pil pillow mess</title>
      <link>/blog/2013/virtualenv-pil-pillow-mess/</link>
      <pubDate>Fri, 30 Aug 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/virtualenv-pil-pillow-mess/</guid>
      <description>Numerous articles have been written about why you want to install Pillow instead of PIL to get the Python Imaging tools. Like Problems with PIL? Use Pillow instead!
(Find more by searching for “IOError: decoder zip not available”.)
This note concerns something more insidious: a seemingly broken Pillow installation after the removal of PIL.
~$ mkvirtualenv piltest (piltest)~$ pip install PIL (piltest)~$ pip freeze | grep -i pil PIL==1.1.7 Now this should work:</description>
    </item>
      
    <item>
      <title>Two-node MariaDB-galera-cluster</title>
      <link>/blog/2013/two-node-mariadb-galera-cluster-with-arbiter/</link>
      <pubDate>Thu, 18 Jul 2013 14:01:09 +0000</pubDate>
      
      <guid>/blog/2013/two-node-mariadb-galera-cluster-with-arbiter/</guid>
      <description>Caveats  arbiter - 10.10.10.1 node1 - 10.10.10.10 node1 - 10.10.10.11  Installing the nodes update /etc/hosts to make sure all the machines are resolvable, perform this on all 3 hosts (2 active mysql nodes and the machine the arbiter resides on). Update the hostnames and addresses accordingly.
 $ cat &amp;lt;&amp;lt; EOF &amp;gt;&amp;gt; /etc/hosts 10.10.10.1 arbiter 10.10.10.10 node1 10.10.10.11 node2 EOF  Setup APT to use the MariaDB repositories</description>
    </item>
      
    <item>
      <title>webserver ssl configuration cheatsheet</title>
      <link>/blog/2013/webserver-ssl-configuration-cheatsheet/</link>
      <pubDate>Mon, 15 Apr 2013 19:49:14 +0000</pubDate>
      
      <guid>/blog/2013/webserver-ssl-configuration-cheatsheet/</guid>
      <description>Just a quick post with the most straight forward way to configure http webservers/proxies in regard to ssl certificate chains.
I&amp;rsquo;m open for improvements if it improves readability or reduces linecount. :-)
pound In /etc/pound/pound.cfg you only need one line in the HTTPS listener:
ListenHTTPS Cert &#34;/etc/pound/file-with-key-and-cert-chain.pem&#34;  apache2 SSLCertificateFile /path/to/file-with-key-and-cert-chain.pem SSLCertificateChainFile /path/to/file-with-key-and-cert-chain.pem  </description>
    </item>
      
    <item>
      <title>SSL certificate chains, intermediate certs</title>
      <link>/blog/2013/fixing-ssl-certificate-chains-and-verify-they-work-properly/</link>
      <pubDate>Mon, 15 Apr 2013 15:02:51 +0000</pubDate>
      
      <guid>/blog/2013/fixing-ssl-certificate-chains-and-verify-they-work-properly/</guid>
      <description>Most browser trusted SSL certificates work with intermediate certificates nowadays. The CA only ships the root certificates for inclusion with the browsers and because they do this your certificate can&amp;rsquo;t be verified if you don&amp;rsquo;t include the intermediate certificates in your webserver configuration.
chain order So you&amp;rsquo;re in the bottom in a chain of trust. Your certificate is signed by a certificate which is signed by another certificate and so on.</description>
    </item>
      
    <item>
      <title>brief / dbase backup bonanza</title>
      <link>/blog/2013/brief-dbase-backup-bonanza/</link>
      <pubDate>Mon, 15 Apr 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/brief-dbase-backup-bonanza/</guid>
      <description>Of course you do daily backups of your data. For your databases, you generally need a dump of the data for it to be useful. For your and my reference, here are a few database dump scripts. Make sure /var/backups is backed up daily.
Observe that we keep extra backups around. I&amp;rsquo;ve found that the need to access an old database is far more common than accessing old files (from the backup storage).</description>
    </item>
      
    <item>
      <title>probook 4510s / high fan speed</title>
      <link>/blog/2013/probook-4510s-high-fan-speed/</link>
      <pubDate>Sun, 14 Apr 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/probook-4510s-high-fan-speed/</guid>
      <description>So, there have been numerous reports around the internet that the HP ProBook 4510s has fan speed issues.
In my case, the following happens:
 Turn on the laptop: no problem. Using the laptop while on AC: no problem. Switch on the laptop from suspend mode without AC plugged in: problem!  The fan goes into overdrive and stays there.
It&#39;s related to the temperature measurements, somehow. According to the sensors(1) tool, it&#39;s the temp6 value that&#39;s off.</description>
    </item>
      
    <item>
      <title>Scan for new hotplug added disks</title>
      <link>/blog/2013/scan-for-new-hotplug-added-disks/</link>
      <pubDate>Thu, 11 Apr 2013 11:53:51 +0000</pubDate>
      
      <guid>/blog/2013/scan-for-new-hotplug-added-disks/</guid>
      <description>If you add new disks to a virtual machine you don&amp;rsquo;t have to reboot to be able to use them.
I assume this works the same for normal hotswappable disks as well but that just doesn&amp;rsquo;t happen too often these days. Didn&amp;rsquo;t test for all drivers/use cases but the example below is in a VMWARE environment. It has to be handled as scsi by the kernel obviously.
check for current disks:</description>
    </item>
      
    <item>
      <title>mysql / show procedure / grant</title>
      <link>/blog/2013/mysql-show-procedure-grant/</link>
      <pubDate>Fri, 05 Apr 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/mysql-show-procedure-grant/</guid>
      <description>How to I grant myself permissions to show MySQL FUNCTION and PROCEDURE bodies?
It isn&amp;rsquo;t this:
mysql&amp;gt; grant all privileges on procedure *.* to walter; ERROR 1144 (42000): Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used But it is this:
mysql&amp;gt; grant select on mysql.proc to walter; Query OK, 0 rows affected (0.00 sec) </description>
    </item>
      
    <item>
      <title>python / twisted / exec environment</title>
      <link>/blog/2013/python-twisted-exec-environment/</link>
      <pubDate>Thu, 21 Mar 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/python-twisted-exec-environment/</guid>
      <description>Does Python Twisted pass the parent environment to child processes?
By default no, but if you pass env=None then it does. Ergo, default is env={}.
Let&amp;rsquo;s build a quick example. For those unfamiliar with twisted this may provide a quick intro.
import os from twisted.internet import protocol, reactor, utils This is what we&amp;rsquo;re going to &amp;ldquo;run&amp;rdquo;:
proc = [&amp;#39;/bin/sh&amp;#39;, &amp;#39;-c&amp;#39;, &amp;#39;export&amp;#39;] #kwargs = {&amp;#39;env&amp;#39;: None} kwargs = {} A quick way to show output and end after the 2 runs.</description>
    </item>
      
    <item>
      <title>python / temporarily blocking signals</title>
      <link>/blog/2013/python-temporarily-blocking-signals/</link>
      <pubDate>Wed, 20 Mar 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/python-temporarily-blocking-signals/</guid>
      <description>There is no way to “block” signals temporarily from critical sections (since this is not supported by all Unix flavors). Says the python signal module manual.
But I&amp;rsquo;m using Linux, where it is possible to block signals, so I don&amp;rsquo;t think that limitation applies. And it doesn&amp;rsquo;t.
pysigset takes the burden off calling sigprocmask(2) through ctypes and provides a “pythonic” interface to temporarily blocking signals in python.
from signal import SIGINT, SIGTERM from pysigset import suspended_signals with suspended_signals(SIGINT, SIGTERM): # Signals are blocked here.</description>
    </item>
      
    <item>
      <title>darwin / sed / limited regular expressions</title>
      <link>/blog/2013/darwin-sed-limited-regular-expressions/</link>
      <pubDate>Sat, 16 Mar 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/darwin-sed-limited-regular-expressions/</guid>
      <description>For someone who is used to using only GNU sed(1) it may come as a surprise that some of the metacharacters don&amp;rsquo;t work with sed on other OS&amp;rsquo;es.
Specifically: sed on Darwin (BSD) does not grok \+, \| and \? when in basic regular expression mode (the default).
Switching to extended (modern) regular expression isn&amp;rsquo;t a good idea if you&amp;rsquo;re aiming for compatibility, because the option -E differs from the GNU sed option -r.</description>
    </item>
      
    <item>
      <title>callerid in rpid / opensips / kamailio</title>
      <link>/blog/2013/callerid-in-rpid-opensips-kamailio/</link>
      <pubDate>Tue, 12 Mar 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/callerid-in-rpid-opensips-kamailio/</guid>
      <description>For reuse, an OpenSIPS/Kamailio snippet to translate commonly used SIP (VoIP) phone Caller-ID (CLI) headers into a single one (Remote-Party-ID).
It tries these headers in order, to do a best guess of what the caller wants:
P-Asserted-Identity (with Privacy)
P-Preferred-Identity (with Privacy)
Remote-Party-ID
From
Of course you&amp;rsquo;ll have to run the found CLI against an allow list, but this code expects that to be done on the next hop.
route[sub_cli_as_rpid] { $var(tmp_name) = &amp;quot;&amp;quot;; # (nothing) $var(tmp_num) = &amp;quot;Anonymous&amp;quot;; # (unknown) $var(tmp_clir) = 0; # PAI/PPI-privacy if (is_present_hf(&amp;quot;Privacy&amp;quot;)) { if (!</description>
    </item>
      
    <item>
      <title>more or less useless tips and tricks 2</title>
      <link>/blog/2013/more-or-less-useless-tips-and-tricks-2/</link>
      <pubDate>Fri, 18 Jan 2013 00:00:00 +0000</pubDate>
      
      <guid>/blog/2013/more-or-less-useless-tips-and-tricks-2/</guid>
      <description>More or less useless/useful tips and tricks, bundled together. They weren&amp;rsquo;t worthy of a box div on their own. I gave them only a li each.
 kill -WINCH $$ — when your terminal is messed up where the row moves up one line before you&amp;rsquo;ve reached the line-length ($COLUMNS):
a SIGWINCH signal to the current shell will make everything alright again. hash -r — you moved applications around in your $PATH and bash claims that some applications don&amp;rsquo;t exist in your $PATH even though you (and ls) know that they do:</description>
    </item>
      
    <item>
      <title>Upgrading Ubuntu command line</title>
      <link>/blog/2013/upgrading-ubuntu-command-line/</link>
      <pubDate>Tue, 15 Jan 2013 13:03:27 +0000</pubDate>
      
      <guid>/blog/2013/upgrading-ubuntu-command-line/</guid>
      <description>When upgrading Ubuntu command line, many people probably still change the release name in the sources.list and update &amp;amp;&amp;amp; dist-upgrade. Although is still works fine, Ubuntu also provides extras on this front.
Upgrade the new way:
sudo do-release-upgrade  Whats the benefit? It provides things like a temporary SSH server and probably does other sanity checks to increase the chances of an successful upgrade and eases the troubleshooting if things go wrong.</description>
    </item>
      
    <item>
      <title>etckeeper</title>
      <link>/blog/2013/etckeeper/</link>
      <pubDate>Tue, 15 Jan 2013 13:01:35 +0000</pubDate>
      
      <guid>/blog/2013/etckeeper/</guid>
      <description>One useful tool we recently started using is etckeeper.
It provides version control over your /etc/ directory, which may prove quite useful when you maintain system in co-op way with your customers. Etckeeper also comes with hooks for apt, so even if you use it terribly it does give you an insightful history of when which package was installed.
Installation and setup in Ubuntu:
apt-get install git etckeeper # change VCS in /etc/etckeeper/etckeeper.</description>
    </item>
      
    <item>
      <title>canon / mf8350 / driver hell</title>
      <link>/blog/2012/canon-mf8350-driver-hell/</link>
      <pubDate>Wed, 12 Dec 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/canon-mf8350-driver-hell/</guid>
      <description>Building Canon MF8350Cdn (and other) CUPS drivers for Linux Debian and/or Ubuntu on amd64 is still a pain in the behind.
Problems encountered during the installation, include:
 Regular make installed stuff in different places but forgot many parts.
Solution: use dpkg-buildpackage The libtool copied wasn&amp;rsquo;t able to build for shared libs.
Solution: remove --enable-shared/--disable-shared command line options. amd64 had to be added to the architecture targets. A shell script had to lose a bashism.</description>
    </item>
      
    <item>
      <title>easy / certificate generation / testing</title>
      <link>/blog/2012/easy-certificate-generation-testing/</link>
      <pubDate>Thu, 25 Oct 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/easy-certificate-generation-testing/</guid>
      <description>If I&amp;rsquo;m going to be requesting SSL certificates more often, I&amp;rsquo;d better automate the process a bit.
The result:
easycert.sh (view)
Possible invocation styles:
$ easycert.sh -h Usage: easycert.sh -c NL -l Groningen -o OSSO\ B.V. -e info@osso.nl osso.nl Usage: easycert.sh osso.nl &amp;#34;/C=NL/L=Groningen/O=OSSO B.V./CN=osso.nl/&amp;#34; Usage: easycert.sh -T www.osso.nl 443 Generating a key and certificate:
$ easycert.sh -o &amp;#34;My Company&amp;#34; mycompany.com Subject: /C=NL/L=Groningen/O=My Company/CN=mycompany.com/emailAddress=info@osso.nl Enter to proceed... Generating RSA private key, 4096 bit long modulus .</description>
    </item>
      
    <item>
      <title>setuid / seteuid / uid / euid</title>
      <link>/blog/2012/setuid-seteuid-uid-euid/</link>
      <pubDate>Fri, 17 Aug 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/setuid-seteuid-uid-euid/</guid>
      <description>So, what is the difference between uid and euid and the setuid and seteuid calls?
Hao Chen, David Wagner and Drew Dean wrote an excellent paper called Setuid Demystified. It explains all the ins and outs. To answer the question, we need only parts of the article.
Let the quoting begin.
 Each process has three user IDs: the real user ID (real uid, or ruid), the effective user ID (effective uid, or euid), and the saved user ID (saved uid, or suid).</description>
    </item>
      
    <item>
      <title>postfix / submission / smtpd_client_restrictions / sleep</title>
      <link>/blog/2012/postfix-submission-smtpd-client-restrictions-sleep/</link>
      <pubDate>Mon, 16 Jul 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/postfix-submission-smtpd-client-restrictions-sleep/</guid>
      <description>After tweaking my postfix configuration, I apparently broke submission on port 587. Every time I connected, I immediately got:
554 5.7.1 &amp;lt;my.host.name[1.2.3.4]&amp;gt;: Client host rejected: Access denied  That&amp;rsquo;s strange. Postfix is supposed to reject unauthenticated clients only in master.cf:
submission inet n - n - - smtpd -o smtpd_tls_security_level=encrypt -o smtpd_tls_auth_only=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject But if it rejects me at connect time, I don&amp;rsquo;t have a chance to identify myself.</description>
    </item>
      
    <item>
      <title>new ipython / old django</title>
      <link>/blog/2012/new-ipython-old-django/</link>
      <pubDate>Mon, 09 Jul 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/new-ipython-old-django/</guid>
      <description>IPython after version 0.10 is not friends with older Django (e.g. 1.1.x) versions anymore.
shell = IPython.Shell.IPShell(argv=[]) AttributeError: &amp;#39;module&amp;#39; object has no attribute &amp;#39;Shell&amp;#39; This is fixed in newer Django&amp;rsquo;s, but this isn&amp;rsquo;t backported.
Here, a patch. (Nothing more than a diff between the old and the new Django version.)
--- django/core/management/commands/shell.py 2012-03-28 16:10:28.000000000 +0200 +++ django/core/management/commands/shell.py 2012-01-24 10:27:50.405338739 +0100 @@ -8,9 +8,38 @@  help=&amp;#39;Tells Django to use plain Python, not IPython.</description>
    </item>
      
    <item>
      <title>serialize json date / microsoft extension</title>
      <link>/blog/2012/serialize-json-date-microsoft-extension/</link>
      <pubDate>Thu, 21 Jun 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/serialize-json-date-microsoft-extension/</guid>
      <description>Bertrand Le Roy describes how Microsoft added a Date object extension to JSON in a compatible fashion to implement serialization and serialization of timezone agnostic datetimes.
 Our current approach is using a small loophole in the JSON specs. In a JSON string literal, you may (or may not) escape some characters. Among those characters, weirdly enough, there is the slash character (&#39;/&#39;). This is weird because there actually is no reason that I can think of why you&amp;rsquo;d want to do that.</description>
    </item>
      
    <item>
      <title>gigaset n300a / respect srv</title>
      <link>/blog/2012/gigaset-n300a-respect-srv/</link>
      <pubDate>Thu, 14 Jun 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/gigaset-n300a-respect-srv/</guid>
      <description>Does the Siemens Gigaset N300A handle SRV records?
Yes it does.. but..
Let&amp;rsquo;s look at a bit of Gigaset DNS traffic:
09:24:26.059850 IP gigaset.local.32978 &amp;gt; nameserver.local.53: 50512+ NAPTR? gigaset.voip.example.com. (28) 09:24:26.061552 IP nameserver.local.53 &amp;gt; gigaset.local.32978: 50512 0/1/0 (87) 09:24:26.063894 IP gigaset.local.32978 &amp;gt; nameserver.local.53: 25738+ SRV? _sip._udp.gigaset.voip.example.com. (38) 09:24:26.064445 IP nameserver.local.53 &amp;gt; gigaset.local.32978: 25738 2/3/2 SRV proxy1.voip.example.com.:5060 10 0, SRV proxy2.voip.example.com.:5060 20 0 (231) 09:24:26.066939 IP gigaset.local.32978 &amp;gt; nameserver.local.53: 22676+ SRV? _sip.</description>
    </item>
      
    <item>
      <title>thunderbird / mailing list / reply</title>
      <link>/blog/2012/thunderbird-mailing-list-reply/</link>
      <pubDate>Wed, 13 Jun 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/thunderbird-mailing-list-reply/</guid>
      <description>How do you reply to a mailing list post when you do not have the mail in your INBOX? With Thunderbird it is easy enough, as long as you know how.
How it works Mail threads are matched by comparing the In-Reply-To header with the Message-ID.
Here&amp;rsquo;s an example from an Asterisk project reviewboard mailing:
Date: Fri, 08 Jun 2012 08:08:42 -0000 Message-ID: &amp;lt;20120608080842.8103.32910@hotblack.digium.com&amp;gt; In-Reply-To: &amp;lt;20120607143847.27705.11556@hotblack.digium.com&amp;gt; References: &amp;lt;20120607143847.27705.11556@hotblack.digium.com&amp;gt; Subject: Re: [asterisk-dev] [Code Review] Fix issue of unrecognized inbound ACK when Asterisk responds to an INVITE with a 481 Every e-mail message has a globally unique message identifier.</description>
    </item>
      
    <item>
      <title>python / base85 / ascii85</title>
      <link>/blog/2012/python-base85-ascii85/</link>
      <pubDate>Wed, 06 Jun 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/python-base85-ascii85/</guid>
      <description>So python&amp;rsquo;s base64 does not have a b85decode function? Adobe uses it the ASCII-85 encoding in PDF and PostScript files.
Here is a quick and dirty one hacked together. See the wikipedia article for the ASCII-85 (base85) specs.
Prologue; we only need sys to print a warning.
# vim: set ts=8 sw=4 sts=4 et ai: # Example base85 decoder, Walter Doekes 2012 import sys Split the data up into 5-character chunks; 5 characters encode 4 octets.</description>
    </item>
      
    <item>
      <title>libreoffice / spreadsheet l10n / date format</title>
      <link>/blog/2012/libreoffice-spreadsheet-l10n-date-format/</link>
      <pubDate>Mon, 04 Jun 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/libreoffice-spreadsheet-l10n-date-format/</guid>
      <description>For LibreOffice&amp;rsquo;s oocalc on latest Ubuntu (libreoffice-base 1:3.5.2-2ubuntu1 to take the locale settings into account for the date types, the LC_CTYPE needs to be set.
$ LC_CTYPE=en_US.UTF-8 oocalc This causes a date input of 31-01-2012 to not get parsed as a date.
$ LC_CTYPE=nl_NL.UTF-8 oocalc This causes the same input of 31-01-2012 to get properly understood as the DD-MM-YYYY format.
That does not make sense. LC_CTYPE should be used for character classification, collation and case conversion.</description>
    </item>
      
    <item>
      <title>ubuntu / sip video / softphone</title>
      <link>/blog/2012/ubuntu-sip-video-softphone/</link>
      <pubDate>Mon, 14 May 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/ubuntu-sip-video-softphone/</guid>
      <description>So, I wanted to test video support with Asterisk. That was easier said than done, because the SIP softphones that ship with Ubuntu don&amp;rsquo;t all do what they promise.
This was done on a setup that works for numerous hardphones and PBXs out there. Looking through the registration list at any given time reveals at least 40+ different user agents and a large multiple of that if you take the different versions into account.</description>
    </item>
      
    <item>
      <title>django / mark_safe / translatables</title>
      <link>/blog/2012/django-mark-safe-translatables/</link>
      <pubDate>Fri, 04 May 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/django-mark-safe-translatables/</guid>
      <description>Look at this snippet of Django code in models.py, and in particular the help_text bit:
from django.db import models from django.utils.translation import ugettext_lazy as _ from django.utils.safestring import mark_safe class MyModel(models.Model): my_field = models.CharField(max_length=123, help_text=mark_safe(_(&amp;#39;Some &amp;lt;b&amp;gt;help&amp;lt;/b&amp;gt; text.&amp;#39;))) For those unfamiliar with Django. A quick run-down:
 The definition of MyModel creates a mapping between the MyModel class and a underlying app_mymodel table in a database. That table will consist of two columns: id, an automatic integer as primary key (created by default), and my_field, a varchar/text field of at most 123 characters.</description>
    </item>
      
    <item>
      <title>ipython classic mode / precise pangolin</title>
      <link>/blog/2012/ipython-classic-mode-precise-pangolin/</link>
      <pubDate>Mon, 30 Apr 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/ipython-classic-mode-precise-pangolin/</guid>
      <description>The Ubuntu do-release-upgrade broke my ipython classic mode. The ipython package was upgraded, and apparently the configuration parser was changed.
In bash, I want colors to help me find the beginning and end of output — see this bug report for others agreeing with me that the derogatory comment about &amp;ldquo;focus should be on the output, not on the prompt&amp;rdquo; in the skeleton .bashrc is is retared, but I diverge — in ipython, I just want to see the nice &amp;gt;&amp;gt;&amp;gt; blocks that I&amp;rsquo;m used to and no extra spaces.</description>
    </item>
      
    <item>
      <title>safe_asterisk / init.d</title>
      <link>/blog/2012/safe-asterisk-init-d/</link>
      <pubDate>Thu, 12 Apr 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/safe-asterisk-init-d/</guid>
      <description>An init.d script to stop and start safe_asterisk started asterisk. If asterisk is not stopped in 5 seconds, it is forcibly killed.
safe_asterisk-init.d (view)
# wget http://wjd.nu/files/2012/04/safe_asterisk-init.d -O/etc/init.d/asterisk ; chmod 755 /etc/init.d/asterisk Also possibly useful, the changes I made to safe_asterisk on a machine where:
 there wasn&amp;rsquo;t a tty left to spam output on, root is configured in /etc/aliases to a sane destination, /var/spool/asterisk is the asterisk user homedir anyway, and, attempting to set maxfiles to the highest value possible, wasn&amp;rsquo;t allowed.</description>
    </item>
      
    <item>
      <title>sip / digest calculation</title>
      <link>/blog/2012/sip-digest-calculation/</link>
      <pubDate>Thu, 29 Mar 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/sip-digest-calculation/</guid>
      <description>Every one in a while, I see an unexpected 403 response to a SIP client&amp;rsquo;s REGISTER request. Thusfar the digest response calculation has never been wrong, but it feels good to get that check out of the way and move on to other possible causes.
For your enjoyment and mine, a Bourne-shell compatible shell script that calculates (qop-less) Digest authentication responses.
Download: hahacalc.sh (view)
$ hahacalc Usage: hahacalc.sh USERNAME REALM METHOD DIGESTURI NONCE [PASSWORD] [COMPARE] Or: hahacalc.</description>
    </item>
      
    <item>
      <title>python virtualenv / global site-packages</title>
      <link>/blog/2012/python-virtualenv-global-site-packages/</link>
      <pubDate>Tue, 13 Mar 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/python-virtualenv-global-site-packages/</guid>
      <description>If you&amp;rsquo;re switching from Ubuntu Oneiric to Ubuntu Precise and you&amp;rsquo;re using python-virtualenv, you might be in for a surprise:
The default access to the global site-packages modules is reversed between virtualenv 1.6.x and 1.7.
When you were used to finding your apt-get installed python modules like python-mysqldb and python-psycopg2 in your new virtualenv environment, now they&amp;rsquo;re suddenly unavailable.
The culprit:
--no-site-packages Ignored (the default). Don´t give access to the global site-packages modules to the virtual environment.</description>
    </item>
      
    <item>
      <title>mysql / replicating repair table</title>
      <link>/blog/2012/mysql-replicating-repair-table/</link>
      <pubDate>Mon, 27 Feb 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/mysql-replicating-repair-table/</guid>
      <description>From the MySQL 5.1 manual:
 15.4.1.16. Replication and REPAIR TABLE
When used on a corrupted or otherwise damaged table, it is possible for the REPAIR TABLE statement to delete rows that cannot be recovered. However, any such modifications of table data performed by this statement are not replicated, which can cause master and slave to lose synchronization. For this reason, in the event that a table on the master becomes damaged and you use REPAIR TABLE to repair it, you should first stop replication (if it is still running) before using REPAIR TABLE, then afterward compare the master&amp;rsquo;s and slave&amp;rsquo;s copies of the table and be prepared to correct any discrepancies manually, before restarting replication.</description>
    </item>
      
    <item>
      <title>indirect scp / bypass remote firewall rules</title>
      <link>/blog/2012/indirect-scp-bypass-remote-firewall-rules/</link>
      <pubDate>Fri, 17 Feb 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/indirect-scp-bypass-remote-firewall-rules/</guid>
      <description>Suppose I&amp;rsquo;m on machine DESKTOP and I want to copy files from server APPLE to server BANANA. DESKTOP has access to both, but firewalls and/or missing ssh keys prevent direct access between APPLE and BANANA.
Regular scp(1) will now fail. It will attempt to do a direct copy and then give up. This is where this indirect scp wrapper (view) comes in:
 First, it tries to do the direct copy.</description>
    </item>
      
    <item>
      <title>mysql replication / relay log pos</title>
      <link>/blog/2012/mysql-replication-relay-log-pos/</link>
      <pubDate>Wed, 25 Jan 2012 00:00:00 +0000</pubDate>
      
      <guid>/blog/2012/mysql-replication-relay-log-pos/</guid>
      <description>So, hardware trouble caused a VPS to go down. This VPS was running a MySQL server in a slave setup. Not surprisingly, the unclean shutdown broke succesful slaving.
There are several possibly causes for slave setup breakage. This time it was the local relay log file (mysqld-relay-bin.xxxx) that was out of sync.
SHOW SLAVE STATUS\G looked like this:
... Master_Log_File: mysql-bin.001814 &amp;lt;-- remote/master file (IO thread)  Read_Master_Log_Pos: 33453535 &amp;lt;-- remote/master pos (IO thread)  Relay_Log_File: mysqld-relay-bin.</description>
    </item>
      
    <item>
      <title>mysql slow / queries / sample</title>
      <link>/blog/2011/mysql-slow-queries-sample/</link>
      <pubDate>Mon, 12 Dec 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/mysql-slow-queries-sample/</guid>
      <description>Sometimes you&amp;rsquo;re in a situation where you know that a database is more heavily loaded than it should be. Time to figure out which queries are stressing it the most.
The standard thing to do with a MySQL database would be to enable query logging with general_log_file. Or, to get only slow queries and those not using indexes, the log_slow_queries.
But, if this is a mission critical and heavily loaded database, adding expensive logging may be just enough to give it that final push to become overloaded.</description>
    </item>
      
    <item>
      <title>postgres / alter column / look closer</title>
      <link>/blog/2011/postgres-alter-column-look-closer/</link>
      <pubDate>Sun, 11 Dec 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/postgres-alter-column-look-closer/</guid>
      <description>Just now, I tried to convert an integer column in a PostgreSQL database to one of type VARCHAR. I knew you had to do an explicit cast, so I was a bit stumped that I still wasn&amp;rsquo;t allowed to perform the ALTER TABLE.
mydb=&amp;gt; ALTER TABLE mytable ALTER COLUMN mycolumn TYPE VARCHAR(31) USING mycolumn::text; ERROR: operator does not exist: character varying &amp;gt;= integer HINT: No operator matches the given name and argument type(s).</description>
    </item>
      
    <item>
      <title>fixing symptoms / not problems</title>
      <link>/blog/2011/fixing-symptoms-not-problems/</link>
      <pubDate>Fri, 02 Dec 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/fixing-symptoms-not-problems/</guid>
      <description>Some people seem to think that fixing the symptom is fixing the problem.
import random def return_one_of(list): return list[random.randint(0, len(list))] def say_something(): try: print return_one_of([&amp;#34;Hello World!&amp;#34;, &amp;#34;Hi!&amp;#34;, &amp;#34;How you doin&amp;#39;?&amp;#34;]) except: return say_something() say_something() Gah!
This is obviously an example, but there are people who do this and claim to have &amp;ldquo;fixed the problem&amp;rdquo;.
Let me reiterate: the fact that your code does not raise any exceptions does NOT mean that it is not broken code!</description>
    </item>
      
    <item>
      <title>django / mongodb / manage dbshell</title>
      <link>/blog/2011/django-mongodb-manage-dbshell/</link>
      <pubDate>Tue, 15 Nov 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/django-mongodb-manage-dbshell/</guid>
      <description>The current django-mongodb-engine doesn&amp;rsquo;t seem to ship with a working manage dbshell command yet. Right now it returns this:
$ ./manage.py dbshell ... File &amp;#34;/home/walter/.virtualenvs/myproject/lib/python2.6/site-packages/django/core/management/commands/dbshell.py&amp;#34;, line 21, in handle connection.client.runshell() File &amp;#34;/home/walter/.virtualenvs/myproject/lib/python2.6/site-packages/django_mongodb_engine/base.py&amp;#34;, line 108, in __getattr__ raise AttributeError(attr) AttributeError: client The fix is simple, patch your django_mongodb_engine with this:
--- django_mongodb_engine/base.py.orig 2011-11-15 11:53:47.000000000 +0100 +++ django_mongodb_engine/base.py 2011-11-15 11:54:07.000000000 +0100 @@ -7,6 +7,7 @@  from pymongo.connection import Connection from pymongo.collection import Collection +from .</description>
    </item>
      
    <item>
      <title>certificate verify fail / crt / bundle</title>
      <link>/blog/2011/certificate-verify-fail-crt-bundle/</link>
      <pubDate>Thu, 20 Oct 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/certificate-verify-fail-crt-bundle/</guid>
      <description>So. SSL certificates are still black magic to me. Especially when they cause trouble.
Like when one of the sysadmins has forgotten to add the certificate bundle to the apache2 config.
Then you get stuff like this:
$ hg pull -u abort: error: _ssl.c:503: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed Most web browsers do not notice this as they already have the intermediate CA files, but /etc/ssl/certs/ca-certificates.crt seemingly doesn&amp;rsquo;t.
The problem in this case was not that I was missing any certificates locally.</description>
    </item>
      
    <item>
      <title>backtrace / without debugger</title>
      <link>/blog/2011/backtrace-without-debugger/</link>
      <pubDate>Mon, 12 Sep 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/backtrace-without-debugger/</guid>
      <description>You may not always have gdb(1) at hand. Here are a couple of other options at your disposal.
#1 Use addr2line to get the crash location $ cat badmem.c void function_c() { int *i = (int*)0xdeadbeef; *i = 123; } // &amp;lt;-- line 1 void function_b() { function_c(); } void function_a() { function_b(); } int main() { function_a(); return 0; } $ gcc -g badmem.c -o badmem $ ./badmem Segmentation fault No core dump?</description>
    </item>
      
    <item>
      <title>gdb / backtrace / running process</title>
      <link>/blog/2011/gdb-backtrace-running-process/</link>
      <pubDate>Tue, 06 Sep 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/gdb-backtrace-running-process/</guid>
      <description>Sometimes you want a backtrace or a core dump from a process that you do not want to stall. This could concern a multithreaded application of which some threads are still doing important work (like handling customer calls). Firing up gdb would halt the process for as long as you&amp;rsquo;re getting info, and raising a SIGABRT to get a core dump has the negative side-effect of killing the process. Neither is acceptable in a production environment.</description>
    </item>
      
    <item>
      <title>sip / six digit port number / invalid</title>
      <link>/blog/2011/sip-six-digit-port-number-invalid/</link>
      <pubDate>Sun, 04 Sep 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/sip-six-digit-port-number-invalid/</guid>
      <description>While looking through opensips logs of a customer, sometimes we would see the following:
ERROR:core:parse_via: invalid port number &amp;lt;110900&amp;gt; ERROR:core:parse_via: &amp;lt;SIP/2.0/UDP 1.2.3.4:110900;branch=z9hG4bKabcdef... ERROR:core:parse_via: parsed so far:&amp;lt;SIP/2.0/UDP 1.2.3.4:110900;branch=z9hG4bKabcdef... ERROR:core:get_hdr_field: bad via As you can see, that 6-digit port number is invalid. Furthermore, when sniffing this traffic, we could see that the port number is almost right. The traffic came from port 11090 (one less zero at the end).
Not only the Via header, the Contact header too had the extra appended zero.</description>
    </item>
      
    <item>
      <title>openswan klips install / modules</title>
      <link>/blog/2011/openswan-klips-install-modules/</link>
      <pubDate>Wed, 13 Jul 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/openswan-klips-install-modules/</guid>
      <description>If you want to be able to sniff your IPsec traffic with OpenSwan, you&amp;rsquo;ll need to get KLIPS instead of the default NETKEY IPsec protocol stack.
Installing that on Ubuntu/Karmic should be a matter of:
~# apt-get install openswan-modules-source ~# cd /usr/src /usr/src# tar jxvf openswan-modules.tar.bz2 /usr/src# cd modules/openswan /usr/src/modules/openswan# make KERNELSRC=/lib/modules/`uname -r`/build module module_install But it&amp;rsquo;s not.
Right now, we&amp;rsquo;re running the default Linux kernel 2.6.31-23-server on this Karmic machine.</description>
    </item>
      
    <item>
      <title>mocp / random / enqueue</title>
      <link>/blog/2011/mocp-random-enqueue/</link>
      <pubDate>Tue, 12 Jul 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/mocp-random-enqueue/</guid>
      <description>After disk failure on our company music server, I lost my enqueue-some-random-music-script.
That shan&amp;rsquo;t happen again. So here, for my own enjoyment: autoenq.sh
#!/bin/sh enqueue_app=&amp;#34;mocp -a&amp;#34; music_glob=&amp;#34;*.mp3&amp;#34; music_path=&amp;#34;`dirname &amp;#34;$0&amp;#34;`&amp;#34; list_path=&amp;#34;$music_path/.autoenq.list&amp;#34; if [ &amp;#34;$*&amp;#34; = &amp;#34;-c&amp;#34; ]; then # Create list of all files find . -type f -iname &amp;#34;$music_glob&amp;#34; &amp;gt; &amp;#34;$list_path.tmp&amp;#34; 2&amp;gt;/dev/null # no lost+found # Create list of all dirs that have files cat &amp;#34;$list_path.tmp&amp;#34; | sed -e &amp;#39;s/\/[^\/]*$//&amp;#39; | sort | uniq &amp;gt; &amp;#34;$list_path&amp;#34; exit 0 fi args=&amp;#34;`echo &amp;#34;$*&amp;#34; | sed -e &amp;#34;s/[&amp;#39;\\\\]//g&amp;#34;`&amp;#34; # no backslashes and single quotes please args=&amp;#34;`echo &amp;#34;$args&amp;#34; | sed -e &amp;#39;s/[[:blank:]]\+/.</description>
    </item>
      
    <item>
      <title>asterisk dialplan peculiarities / regex with eqtilde</title>
      <link>/blog/2011/asterisk-dialplan-peculiarities-regex-with-eqtilde/</link>
      <pubDate>Mon, 04 Jul 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/asterisk-dialplan-peculiarities-regex-with-eqtilde/</guid>
      <description>In the Asterisk PBX dialplan, expressions can be formed using the $[...] syntax. Addition, subtraction, comparison and so on are defined. As is a regex operator: =~
Unfortunately, the documentation about the details of the implementation is hard to find.
Here, a breakdown of my findings:
 static struct val * op_eqtilde is defined in main/ast_expr2.y It uses the REG_EXTENDED flag when calling regcomp: so extended regular expression syntax is used.</description>
    </item>
      
    <item>
      <title>executing remote command / ssh / extra escaping</title>
      <link>/blog/2011/executing-remote-command-ssh-extra-escaping/</link>
      <pubDate>Thu, 09 Jun 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/executing-remote-command-ssh-extra-escaping/</guid>
      <description>If you use ssh to run commands remotely, you may have run into the problem that you need an extra layer of escaping.
Let&amp;rsquo;s say you have application myapp that for some reason only runs on host myserver. If you have functional ssh keys to log onto myserver it can be helpful to create a myapp wrapper on your desktop. After all, this:
$ myapp myargs &amp;hellip; is far more convenient than doing this:</description>
    </item>
      
    <item>
      <title>django / query expression / negate</title>
      <link>/blog/2011/django-query-expression-negate/</link>
      <pubDate>Wed, 08 Jun 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/django-query-expression-negate/</guid>
      <description>Suppose you have an is_enabled boolean in your Django model.
class Rule(models.Model): is_enabled = models.BooleanField(blank=True) # other exciting fields here And now imagine you want to negate the is_enabled values. Something you would easily do in SQL, with: UPDATE myapp_rule SET is_enabled = NOT is_enabled;
The Django F-syntax is nice, and looks like it should be up for the task.
Let&amp;rsquo;s sum up a couple of attempts:
Rule.objects.update(is_enabled=(not F(&amp;#39;is_enabled&amp;#39;))) No! You get this:</description>
    </item>
      
    <item>
      <title>mysql issue warnings / cron</title>
      <link>/blog/2011/mysql-issue-warnings-cron/</link>
      <pubDate>Mon, 16 May 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/mysql-issue-warnings-cron/</guid>
      <description>I&amp;rsquo;ve previously written about MySQL pain in the behind issues involving views with SECURITY DEFINER and bad client collation selection.
For the former problem, I wrote a script that you could call periodically to warn you of potential problems with your views. Now I&amp;rsquo;ve extended it to warn you about collation issues as well.
Put warn-mysql-issues.sh (view) in your cron tab and run it periodically. It&amp;rsquo;ll save you from production-time errors that you get when attempting to compare a string of one collation with another.</description>
    </item>
      
    <item>
      <title>linux / canon mf8350 / printer driver</title>
      <link>/blog/2011/linux-canon-mf8350-printer-driver/</link>
      <pubDate>Thu, 28 Apr 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/linux-canon-mf8350-printer-driver/</guid>
      <description>Getting printer drivers for the Canon MF8350 to work under Ubuntu is a big pain in the behind. (Installation using custom scripts that abuse both /usr/lib and /usr/local/lib and ultimately fail to compile for obscure reasons.)
My colleague found that the easiest way to get it to work, was converting the RPM to DEB using alien(1). For your enjoyment, here are the two debian packages needed for Ubuntu 10.04 (amd64):</description>
    </item>
      
    <item>
      <title>diff / memory exhausted / udiff</title>
      <link>/blog/2011/diff-memory-exhausted-udiff/</link>
      <pubDate>Thu, 07 Apr 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/diff-memory-exhausted-udiff/</guid>
      <description>Sometimes when I&amp;rsquo;m unsure what a button in a database-driven application does, I simply click it and check the differences in the database before and after the click.
If the database dumped is (somewhat) sorted and with one line per row (for MySQL use &amp;ndash;skip-extended-insert), this can be an easy method of verifying that your application action does exactly what you expect and nothing more.
Create a pre.sql before the click, click the button and watch the action happen.</description>
    </item>
      
    <item>
      <title>pcap / capture fragments / udp</title>
      <link>/blog/2011/pcap-capture-fragments-udp/</link>
      <pubDate>Thu, 31 Mar 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/pcap-capture-fragments-udp/</guid>
      <description>When dealing with internet protocols that operate on top of UDP, fragmenting suddenly becomes a lot less uncommon.
Normally, you would only encounter fragments on TCP connections when the MTU on the sending host is larger then the MTU in any of the next hops. Hosts usually attempt to avoid fragmentation for obvious reasons. (Inefficiëncy, extra reassembly work.)
For connectionless UDP packets this is a different matter. Protocols over UDP expect packets to be single entities.</description>
    </item>
      
    <item>
      <title>no sql security definer / please</title>
      <link>/blog/2011/no-sql-security-definer-please/</link>
      <pubDate>Tue, 15 Mar 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/no-sql-security-definer-please/</guid>
      <description>Have you ever had it happen that you removed a MySQL user and suddently parts of your application stopped working? Not because you removed the user that was connecting, but because you removed the user that defined the particular view or function that you were using.
I have, and it was quite stressful ;-)
We moved a slave machine to a different IP, I updated the mysql.user host column, and BAM, the application running on the master mysql stopped working.</description>
    </item>
      
    <item>
      <title>build error / unixodbc / debian-squeeze</title>
      <link>/blog/2011/build-error-unixodbc-debian-squeeze/</link>
      <pubDate>Thu, 10 Mar 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/build-error-unixodbc-debian-squeeze/</guid>
      <description>Building unixodbc-2.2.14p2 on debian/squeeze which you just fetched through apt-get source unixodbc.
~/src/unixodbc-2.2.14p2$ ./configure ... works fine ... ~/src/unixodbc-2.2.14p2$ make ... make[1]: Entering directory `/home/walter/src/unixodbc-2.2.14p2/odbcinst&amp;#39; make[1]: *** No rule to make target `libltdl/libltdlc.la&amp;#39;, needed by `libodbcinst.la&amp;#39;. Stop. make[1]: Leaving directory `/home/walter/src/unixodbc-2.2.14p2/odbcinst&amp;#39; make: *** [install-recursive] Error 1 The fix: add top_build_prefix to the environment.
~/src/unixodbc-2.2.14p2$ top_build_prefix=`pwd`/ make ... success! </description>
    </item>
      
    <item>
      <title>asterisk / nat keepalive / round robin dns</title>
      <link>/blog/2011/asterisk-nat-keepalive-round-robin-dns/</link>
      <pubDate>Sun, 27 Feb 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/asterisk-nat-keepalive-round-robin-dns/</guid>
      <description>Current Asterisk (telephony software) version 1.6.2.x (and probably 1.4 and 1.8), has an odd quirk with the qualify option.
The qualify option enables a function that checks the response times of the SIP peer. By default, it sends an OPTIONS SIP packet every 60 seconds. The quirk here, is that it sends the packet to the first A-record resolved for this peers hostname at startup (or sip reload).
This works fine in most cases when the host has only one A-record.</description>
    </item>
      
    <item>
      <title>pruning old data / mysql / csv</title>
      <link>/blog/2011/pruning-old-data-mysql-csv/</link>
      <pubDate>Fri, 21 Jan 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/pruning-old-data-mysql-csv/</guid>
      <description>It is not uncommon to have a database with records that just accumulate and accumulate over time. Think of log files, telephony billing records, traffic data and so forth.
The chances that you&amp;rsquo;ll ever need this data again are very slim. And letting your database grow indefinitely is not particularly smart. Time to prune!
Two things you need to worry about while pruning your data:
 Throwing it all away without a backup doesn&amp;rsquo;t feel right.</description>
    </item>
      
    <item>
      <title>port forwarded ssh / port 22</title>
      <link>/blog/2011/port-forwarded-ssh-port-22/</link>
      <pubDate>Fri, 14 Jan 2011 00:00:00 +0000</pubDate>
      
      <guid>/blog/2011/port-forwarded-ssh-port-22/</guid>
      <description>Sometimes you need to access your source code repository-server from a new server which hasn&amp;rsquo;t been whitelisted yet. You check out the source over port 22, but you can&amp;rsquo;t, because traffic from new-server to 22 is rejected.
The quick solution, you know this, is ssh port forwarding. Connect to old-server and forward connections to repository-server from there.
$ ssh old-server -L1234:repository-server:22 That works. For mercurial, at least.
$ hg clone ssh://walter@localhost:1234//srv/hg/myproject myproject walter@localhost&amp;#39;s password: requesting all changes .</description>
    </item>
      
    <item>
      <title>faxable images / asterisk pbx</title>
      <link>/blog/2010/faxable-images-asterisk-pbx/</link>
      <pubDate>Tue, 30 Nov 2010 00:00:00 +0000</pubDate>
      
      <guid>/blog/2010/faxable-images-asterisk-pbx/</guid>
      <description>Because creating images that the open source PBX Asterisk(tm) will properly fax using the SendFAX() application, was a pain in the ass, I&amp;rsquo;d like to share my findings.
The HOWTO for creating TIFF images that are laid out so the spandsp fax back-end in asterisk, is embedded in the images2fax.sh shell script, below.
In short, you need to have images of 1728x2292, in 2 colors, with the correct DPI (204x196) and the right compression.</description>
    </item>
      
    <item>
      <title>nat / switch external source port</title>
      <link>/blog/2010/nat-switch-external-source-port/</link>
      <pubDate>Tue, 23 Nov 2010 00:00:00 +0000</pubDate>
      
      <guid>/blog/2010/nat-switch-external-source-port/</guid>
      <description>When reproducing an issue with IP phones speaking SIP, I ran into the question of how to switch source port on my linux NAT router.
The problem the clients were having, were a result of a failing (or reset) NAT-gateway. The NAT-gateway would change the external source port mid-dialog (some SIP dialogs can persist for quite a long time).
So, how do you go about switching source port on an UDP connection on your Linux NAT router without resetting it (or disturbing anyone else using it)?</description>
    </item>
      
    <item>
      <title>sip totag / grandstream / register</title>
      <link>/blog/2010/sip-totag-grandstream-register/</link>
      <pubDate>Mon, 30 Aug 2010 00:00:00 +0000</pubDate>
      
      <guid>/blog/2010/sip-totag-grandstream-register/</guid>
      <description>SIP Question: The Grandstream GXP2000 1.1.2.23 sends SIP REGISTER requests with a To tag. Is my proxy wrong in refusing the request?
REGISTER sip:server SIP/2.0 Via: SIP/2.0/UDP 1.2.3.4:5074;branch=z9hG4bK0b90873d634698eb From: &amp;quot;phone 123&amp;quot; &amp;lt;sip:123@server&amp;gt;;tag=c29eb9104c6a5a86 To: &amp;lt;sip:123@server&amp;gt;;tag=as77984b6 Contact: &amp;lt;sip:123@1.2.3.4:5074;transport=udp&amp;gt; Supported: path Authorization: Digest username=&amp;quot;123&amp;quot;, realm=&amp;quot;server&amp;quot;, algorithm=MD5, uri=&amp;quot;sip:server&amp;quot;, nonce=&amp;quot;0997652c&amp;quot;, response=&amp;quot;3b91afb768c11ae0a0405e1bed41bc23&amp;quot; Call-ID: 3033205eb0b5d203@192.168.4.117 CSeq: 56349 REGISTER Expires: 3600 User-Agent: Grandstream GXP2000 1.1.2.23 Max-Forwards: 70 Allow: INVITE,ACK,CANCEL,BYE,NOTIFY,REFER,OPTIONS,INFO,SUBSCRIBE,UPDATE,PRACK,MESSAGE Content-Length: 0 Answer: no, the proxy is right. RFC 3261 says this about it.</description>
    </item>
      
    <item>
      <title>nxclient / locale passing</title>
      <link>/blog/2010/nxclient-locale-passing/</link>
      <pubDate>Wed, 04 Aug 2010 00:00:00 +0000</pubDate>
      
      <guid>/blog/2010/nxclient-locale-passing/</guid>
      <description>So, I achieved victory on getting the compose key to work in the NX session. On to get a proper English language setting on our Terminal Server.
The configuration suffers from two problems:
(1) /etc/environment had values set (LANG=nl_NL.UTF-8 and LANGUAGE=nl_NL:nl). (2) nxssh does not pass the LANG/LC_* environment variables.
If I were to remove the /etc/environment variables and configure everything like in a previous post of mine, everyone gets the POSIX locale (nxssh doesn&amp;rsquo;t pass anything).</description>
    </item>
      
    <item>
      <title>altgr / nxclient / compose key</title>
      <link>/blog/2010/altgr-nxclient-compose-key/</link>
      <pubDate>Tue, 03 Aug 2010 00:00:00 +0000</pubDate>
      
      <guid>/blog/2010/altgr-nxclient-compose-key/</guid>
      <description>Like various reports on the internet suggest, the AltGr compose key doesn&amp;rsquo;t work properly or not at all from an NXClient connected to an NXServer (FreeNX in my case).
Note that this is a different issue from the one where Alt_R (and Super_L, Super_R, Ctrl_R en Menu) remains pressed after which no normal typing is possible. That issue is described in Alt Gr keeps stuck and involves a new int sendKey = 0; in nxagent that should be reverted.</description>
    </item>
      
    <item>
      <title>python2.6 features / python2.5</title>
      <link>/blog/2010/python2-6-features-python2-5/</link>
      <pubDate>Sun, 20 Jun 2010 00:00:00 +0000</pubDate>
      
      <guid>/blog/2010/python2-6-features-python2-5/</guid>
      <description>Today I&#39;ll show you some quick and dirty python2.5 compatibility fixes. Of course you&#39;re developing on python2.6 or even python3.x, but your customer still lives in the dark ages. Here are two fixes that might come in handy.
ImportError: No module named ssl Falling back to python2.5 socket.SSL if there is no python2.6 ssl through a small wrap_socket replacement:
import socket try: from ssl import wrap_socket except ImportError: class wrap_socket: def __init__(self, socket): self.</description>
    </item>
      
    <item>
      <title>uninitialized globals / C language</title>
      <link>/blog/2010/uninitialized-globals-c-language/</link>
      <pubDate>Wed, 16 Jun 2010 22:00:00 +0000</pubDate>
      
      <guid>/blog/2010/uninitialized-globals-c-language/</guid>
      <description>As per the C language spec., uninitialized globals are initialized to zero (0). Nandu310 tells us why on his blog about the memory areas in the C language.
 Data segment: the data segment is to hold the value of those variables that need to be available throughout the life time of the program. [&amp;hellip;]
There are two parts in this segment. The initialized data segment and uninitialized data segment. When variables are initialized to some value (other than 0 or which is different value), they are allocated in the initialized segment (.</description>
    </item>
      
    <item>
      <title>unexpanded tabs / mercurial web / diff</title>
      <link>/blog/2010/unexpanded-tabs-mercurial-web-diff/</link>
      <pubDate>Fri, 07 May 2010 00:00:00 +0000</pubDate>
      
      <guid>/blog/2010/unexpanded-tabs-mercurial-web-diff/</guid>
      <description>The hgweb mercurial web interface on current Debian/Squeeze (mercurial-common 1.5.1-2) lists tab characters as-is in the diff view.
Every line is prefixed not only by a plus or a minus (unified diff), but also by file and line numbers. This can cause a tab (0x9) character to appear as a single space. This does not look nice.
The following patch can be applied to expand the tab character so the intentation looks right again.</description>
    </item>
      
    <item>
      <title>mysql utf8 collation / conversion</title>
      <link>/blog/2010/mysql-utf8-collation-conversion/</link>
      <pubDate>Fri, 09 Apr 2010 00:00:00 +0000</pubDate>
      
      <guid>/blog/2010/mysql-utf8-collation-conversion/</guid>
      <description>On a clean MySQL install — on a Debian or Ubuntu system at least — the MySQL server gets the latin1_swedish_ci with latin1 character set by default. Every time you set up a new machine, you must remember to either fix the defaults in my.cnf config file or to supply character set and collation options when creating databases.
Of course you&amp;rsquo;ll opt to set this by default in my.cnf first:</description>
    </item>
      
    
  </channel>
</rss>
